用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/doggy8088/fb-blocker --skill fb-blocker命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
正在显示 SKILL.md
| name | fb-blocker |
| description | 自動依關鍵字搜尋或名單在 Facebook 上批次封鎖特定用戶或專頁,並強制選取「封鎖___和對方可能建立的新個人檔案」選項以徹底封鎖。使用 Chrome DevTools MCP 工具。 |
本 Skill 專門用於透過 Chrome DevTools MCP 工具自動化執行 Facebook 用戶與粉絲專頁的關鍵字搜尋、名單採集、逐一前往個人檔案頁面,並強制選取「封鎖 [用戶名] 和對方可能建立的新個人檔案」進行徹底封鎖與結果驗證。
chrome-devtools-mcp
list_pages: 確認目前已開啟的 Facebook 頁面與 pageId。navigate_page: 導航至搜尋頁面或各個人檔案頁面。evaluate_script: 在頁面上下文中執行 DOM 抓取與非同步點擊封鎖流程。list_pages 找到 Facebook 頁面(例如 title: Facebook 或 url: https://www.facebook.com/...),記下其 pageId。navigate_page 前往搜尋頁面:
https://www.facebook.com/search/people?q=<URL編碼關鍵字>evaluate_script),將搜尋結果中符合名稱的所有個人檔案連結提取出來:async () => {
const wait = (ms) => new Promise(r => setTimeout(r, ms));
const keyword = "目標關鍵字"; // 請替換成搜尋關鍵字
const urls = new Set();
let lastHeight = 0;
let noChangeCount = 0;
for (let i = 0; i < 30; i++) {
const links = Array.from(document.querySelectorAll('a[role="presentation"], a[role="link"]'));
for (const a of links) {
const text = a.innerText || a.textContent || '';
if (text.includes(keyword) && a.href && a.href.includes('facebook.com/')) {
// 清理 URL 參數(保留純 profile 網址或 profile.php?id=xxx)
try {
const u = new URL(a.href);
if (u.pathname === '/profile.php') {
urls.add(`${u.origin}${u.pathname}?id=${u.searchParams.get('id')}`);
} else {
urls.add(`${u.origin}${u.pathname}`);
}
} catch (e) {
urls.add(a.href.split('?')[0]);
}
}
}
window.scrollTo(0, document.body.scrollHeight);
await wait(1500);
const newHeight = document.body.scrollHeight;
if (newHeight === lastHeight) {
noChangeCount++;
if (noChangeCount >= 3) break;
} else {
noChangeCount = 0;
lastHeight = newHeight;
}
}
return Array.from(urls);
}
對名單中的每個 URL,依序執行:
navigate_page 前往目標 URL。evaluate_script 執行以下標準封鎖腳本:async () => {
const wait = (ms) => new Promise(r => setTimeout(r, ms));
// 0. 檢查是否已被關聯封鎖或帳號已不存在
if (document.body.innerText.includes('目前無法查看此內容') ||
document.body.innerText.includes('此內容目前無法顯示')) {
return { status: 'already_blocked_or_unavailable', checkedOption: '封鎖和對方可能建立的新個人檔案' };
}
// 1. 尋找個人檔案/專頁的「更多」按鈕(三個點)
let btn = null;
for (let i = 0; i < 12; i++) {
btn = Array.from(document.querySelectorAll('div[role="button"], button')).find(el => {
const aria = el.getAttribute('aria-label') || '';
return (aria.includes('查看更多') || aria.includes('個人檔案設定') || aria.includes() || aria.()) &&
!aria.() && !aria.() && !aria.() && !aria.();
});
(btn) ;
();
}
(!btn) {
(...() || ...()) {
{ : , : };
}
{ : , : };
}
btn.();
();
blockItem = ;
( i = ; i < ; i++) {
blockItem = .(.()).( {
text = (el. || el. || ).();
text === || text.();
});
(blockItem) ;
();
}
(!blockItem) { : , : };
blockItem.();
();
dialog = ;
( i = ; i < ; i++) {
dialog = .(.()).( {
aria = d.() || ;
text = d. || ;
aria.() || text.() || text.();
});
(dialog) ;
();
}
(!dialog) { : , : };
radios = .(dialog.());
targetRadio = ;
( r radios) {
parentContainer = r.() || r.;
(parentContainer && (parentContainer.?.() || parentContainer.?.())) {
targetRadio = r;
;
}
}
(!targetRadio && radios. >= ) {
targetRadio = radios[];
}
(targetRadio) {
targetRadio.();
} {
textEl = .(dialog.()).( {
el. && el..();
});
(textEl) textEl.();
}
();
confirmBtn = .(dialog.()).( {
aria = el.() || ;
text = (el. || ).();
aria === || text === || aria === || text === ;
});
(!confirmBtn) { : , : };
confirmBtn.();
();
successDialog = .(.()).( {
text = d. || ;
text.() || text.();
});
(successDialog) {
closeBtn = .(successDialog.()).( {
text = (el. || el.() || ).();
text === || text === ;
});
(closeBtn) closeBtn.();
}
{ : , : };
}
navigate_page 重新前往搜尋頁面:
https://www.facebook.com/search/people?q=<URL編碼關鍵字>async () => {
const wait = (ms) => new Promise(r => setTimeout(r, ms));
const keyword = "目標關鍵字";
window.scrollTo(0, document.body.scrollHeight);
await wait(1500);
window.scrollTo(0, document.body.scrollHeight);
await wait(1500);
const links = Array.from(document.querySelectorAll('a[role="presentation"], a[role="link"]'))
.map(a => ({ text: a.innerText, href: a.href }))
.filter(a => a.text && a.text.includes(keyword));
return { remainingCount: links.length, remainingLinks: links };
}
remainingCount 為 0,向用戶回報最終處理結果。| 狀況 | 原因分析 | 應對方式 |
|---|---|---|
| 目前無法查看此內容 | 先前封鎖時選取了「連同可能建立的新個人檔案」,Facebook 已自動連帶封鎖該關聯帳號;或是該帳號已被刪除。 | 視為 already_blocked_or_unavailable,直接記錄為已封鎖並繼續處理下一個。 |
| 三點按鈕找不到 | 頁面尚未加載完全,或處於通知下拉視窗狀態。 | 腳本內建 12 次重試 (6秒);若仍失敗可重新呼叫 navigate_page 一次。 |
| 彈出對話框點擊失效 | Facebook 動態渲染延遲。 | 各動作間加入適當 wait(ms) 緩衝(500ms ~ 2200ms),確保網路請求完成。 |