您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Remove LinkedIn connections in bulk by full name input
// ==UserScript== // @name LinkedIn Bulk Connection Remover // @namespace https://matthias-isler.com/ // @version 1.1 // @license MIT // @description Remove LinkedIn connections in bulk by full name input // @author Matthias Isler // @match https://www.linkedin.com/mynetwork/invite-connect/connections/ // @grant none // @run-at document-idle // ==/UserScript== (function () { 'use strict'; // Inject floating button const button = document.createElement('button'); button.textContent = '🗑️ Remove Connections'; Object.assign(button.style, { position: 'fixed', top: '100px', right: '20px', padding: '10px 16px', backgroundColor: '#cb112d', color: 'white', border: 'none', borderRadius: '6px', cursor: 'pointer', zIndex: 9999, boxShadow: '0 2px 4px rgba(0,0,0,0.2)', }); document.body.appendChild(button); const sleep = (ms) => new Promise(r => setTimeout(r, ms)); function normalizeName(name) { return name .toLowerCase() .normalize('NFKD') .replace(/[\p{P}\p{S}\u200B-\u200F\u202A-\u202E\u2060-\u206F\u00A0]/gu, '') .replace(/\s+/g, '') .trim(); } async function typeLikeHuman(inputEl, text) { inputEl.focus(); inputEl.value = ''; inputEl.dispatchEvent(new InputEvent('input', { bubbles: true })); for (const char of text) { const setter = Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, 'value').set; setter.call(inputEl, inputEl.value + char); inputEl.dispatchEvent(new KeyboardEvent('keydown', { bubbles: true })); inputEl.dispatchEvent(new InputEvent('input', { bubbles: true })); inputEl.dispatchEvent(new KeyboardEvent('keyup', { bubbles: true })); await sleep(100); } } async function removeConnection(fullNameRaw) { console.log(`🔍 Searching for: ${fullNameRaw}`); const input = document.querySelector('input[placeholder="Search by name"]'); if (!input) return console.error('❌ Search input not found'); await typeLikeHuman(input, fullNameRaw); await sleep(2500); const cards = [ ...document.querySelectorAll('div[data-view-name="connections-list"] a[data-view-name="connections-profile"]') ].map(a => a.closest('div')).filter(Boolean); const card = cards.find(el => { const nameText = el.querySelector('a[data-view-name="connections-profile"] p > a')?.innerText?.trim() || ''; return normalizeName(nameText) === normalizeName(fullNameRaw); }); if (!card) { console.warn(`❌ No match found for "${fullNameRaw}"`); return; } const menuBtn = card.querySelector('button[aria-label="Show more actions"]'); if (!menuBtn) { console.warn(`⚠️ Menu button not found for "${fullNameRaw}"`); return; } menuBtn.click(); await sleep(1000); const removeBtn = [...document.querySelectorAll('div[role="button"]')] .find(el => el.textContent.trim().toLowerCase().includes('remove connection')); if (!removeBtn) { console.warn(`⚠️ Remove option not found for "${fullNameRaw}"`); return; } removeBtn.click(); await sleep(1000); const confirmBtn = document.querySelector('button[data-view-name="connections-remove"]'); if (confirmBtn) { confirmBtn.click(); console.log(`✅ Removed: ${fullNameRaw}`); } else { console.warn(`⚠️ Confirm button missing for "${fullNameRaw}"`); } await sleep(2000); } button.onclick = async () => { const raw = prompt("Paste full list (tab-separated, one per line):\nFirstname[TAB]Lastname"); if (!raw) return; const names = raw .split('\n') .map(line => line.trim().replace(/\s+/g, ' ')) .filter(Boolean) .map(line => line.split('\t').join(' ').trim()); for (const name of names) { await removeConnection(name); } }; })();