使用專用的有頭 Chrome 設定檔(含持久登入狀態),從網頁中擷取聚焦且特定區域的螢幕截圖。根據使用者提供的內容(網址、搜尋查詢、社群媒體貼文)導航至正確頁面,透過 DOM 選擇器定位目標區域,並裁切出乾淨、聚焦的螢幕截圖,而不會附加到使用者的日常瀏覽器。
技能:瀏覽器螢幕截圖
從網頁中擷取特定區域的聚焦螢幕截圖——Reddit 貼文、推文、文章區塊、圖表等——而不只是全頁傾印。
先決條件:必須安裝
agent-browser。此技能使用自己的有頭 Chrome 搭配專用持久設定檔;使用者的日常 Chrome 不需要遠端除錯。
專用瀏覽器設定檔
使用與 my-chrome-automation 相同的專用持久設定檔慣例:
PROFILE_DIR="${AGENT_BROWSER_PROFILE:-$HOME/.agent-browser-recorder-chrome}"
NAMESPACE="${NAMESPACE:-browser-screenshot}"
SESSION="${SESSION:-focused-capture}"
ab() {
agent-browser --namespace "$NAMESPACE" --session "$SESSION" --headed --profile "$PROFILE_DIR" "$@"
}
所有瀏覽器指令都透過 ab 執行。請勿使用 --auto-connect、通用 CDP 發現或使用者的日常 Chrome 設定檔。專用設定檔可在任務之間保留 Cookie 和登入狀態,同時讓使用者的正常 Chrome 保持開啟且不受影響。
在實際可行時,為任務選擇描述性的 SESSION。請勿同時對同一個設定檔執行多個任務;應依序重複使用,以避免設定檔鎖定衝突。
如果目標網站需要登入,請使用 ab 開啟它,暫停讓使用者在專用的有頭視窗中完成登入或驗證,然後繼續使用相同的設定檔和工作階段。
如果專用設定檔已在執行中
第二次啟動 Chrome 使用相同設定檔時,可能會在建立 DevTools 端點之前退出。絕對不要回退到任何已開啟的 Chrome。請重複使用此設定檔的已知 Agent Browser 工作階段,或明確僅附加到命令列中包含確切 --user-data-dir=$PROFILE_DIR 值的 Chrome 程序。
在 macOS 上,像這樣識別該專用程序及其本機 CDP 連接埠:
PROFILE_PID="$(ps -axo pid=,command= | awk -v profile="--user-data-dir=$PROFILE_DIR" 'index($0, profile) && index($0, "--remote-debugging-port=") && $0 !~ /Helper/ {print $1; exit}')"
CDP_PORT="$(lsof -nP -a -p "$PROFILE_PID" -iTCP -sTCP:LISTEN | awk 'NR > 1 && $9 ~ /^127\.0\.0\.1:[0-9]+$/ {split($9, parts, ":"); print parts[2]; exit}')"
ab() {
agent-browser --namespace "$NAMESPACE" --session "$SESSION" --cdp "$CDP_PORT" "$@"
}
在附加之前,要求非空且明確的 PROFILE_PID 和 CDP_PORT 值。如果無法驗證,請要求使用者關閉專用自動化視窗並重試。請勿關閉此任務僅附加到的瀏覽器。
概述
此技能處理完整的流程:
- 研究要截圖的最佳頁面(網路搜尋、擷取)
- 導航到瀏覽器中的正確頁面
- 定位頁面上的目標元素/區域
- 擷取僅該區域的聚焦、裁切螢幕截圖
嚴格規則:禁止全螢幕截圖
絕對不要輸出未裁切的完整視窗或全頁螢幕截圖作為最終結果。 全螢幕截圖包含太多雜訊(導覽列、側邊欄、廣告、不相關的內容),不適合用作文章插圖。每張螢幕截圖都必須裁切到聚焦區域。
步驟 0:研究——在開啟瀏覽器之前尋找並驗證來源
瀏覽器是用來擷取,不是用來瀏覽的。 在 Chrome 中開啟任何內容之前,請使用基於文字的工具(WebSearch、WebFetch)來尋找候選頁面、閱讀其內容,並決定哪些頁面實際上值得截圖。
研究優先的工作流程
- WebSearch 尋找該主題的候選頁面
- WebFetch 每個候選頁面以閱讀其文字內容——檢查它是否有你需要的資訊/視覺元素
- 評估:這個頁面值得截圖嗎?它是否有清晰、聚焦的區域可以作為插圖?
- 然後才開啟瀏覽器來擷取螢幕截圖
這可以節省大量時間——大多數候選頁面不值得截圖,你可以在沒有瀏覽器導航開銷的情況下排除它們。
何時改用瀏覽器優先
在以下情況下,跳過 WebSearch/WebFetch 階段,直接前往 Chrome 瀏覽:
- 目標平台需要登入——Reddit、LinkedIn、X/Twitter 和其他社群平台通常會將內容隱藏在登入牆後。直接使用專用設定檔,以便重複使用其儲存的登入狀態。
- 使用者指定了平台且有明確的搜尋需求——例如「找一篇關於 X 的 Reddit 貼文」或「截圖一篇關於 Y 的推文」。直接在 Chrome 中前往該平台的搜尋頁面。
- WebFetch 回傳被封鎖或不完整的內容——某些網站會積極封鎖非瀏覽器請求。如果你收到 403、CAPTCHA 頁面或內容被剝離,請切換到 Chrome。
在這些情況下,Chrome 瀏覽會取代 WebSearch——導航到平台的搜尋頁面、瀏覽結果,並在決定要截圖什麼之前視覺化評估頁面。
頁面選擇策略
正確的頁面取決於文章的上下文以及主題的新近度/知名度:
| 主題類型 | 最佳尋找頁面 | 如何尋找 |
|---|---|---|
| 新模型/功能發布(< 6 個月) | 宣布該功能的官方部落格文章 | WebSearch "<model name>" site:<vendor-domain> blog |
| 已建立的產品(> 6 個月) | 產品登陸頁面或文件概覽 | WebSearch "<model name>" official page |
| 開源模型 | HuggingFace 模型卡或 GitHub 儲存庫 | 直接網址:huggingface.co/<org>/<model> |
| API 服務 | API 文件頁面 | WebSearch "<service name>" API docs |
注意:此表格列出常見的主題類型,但並非詳盡無遺。對任何主題類型應用相同的研究優先策略——為手邊的主題找到最權威且視覺上最乾淨的來源頁面。
好的螢幕截圖來源的條件
核心原則:少即是多。專注於內容,而不是瀏覽器 chrome。
好的螢幕截圖來源包含聚焦、自成一體的資訊——一段文字、一個關鍵引述、一個資料表格、一個圖表。它不應該是一個充滿按鈕、導覽、側邊欄和互動元素的繁忙頁面。
- 偏好:部落格文章中帶有清晰標題和 1-2 段文字的部分。單一圖表或圖形。帶有名稱和描述的模型卡標題。引述或關鍵發現。
- 避免:帶有 CTA 和導覽的完整登陸頁面。具有多個面板的儀表板檢視。以 UI 控制項(按鈕、下拉選單、表單)為主而非可讀內容的頁面。
- 官方部落格文章是理想的:它們有英雄圖片、突出的標題和為分享而設計的簡潔描述
- 產品登陸頁面也可以,但僅限於你裁切到英雄區塊時——忽略其餘部分
- HuggingFace 模型卡對於開源模型來說是可靠的:一致的佈局,模型名稱 + 描述始終在頂部
- API 文件是可接受的備案:顯示產品名稱和主要規格
經驗法則:如果你計劃擷取的區域包含的互動式 UI 元素(按鈕、連結、導覽項目)多於可讀的文字內容,那就是一個糟糕的裁切。尋找內容更豐富的區域,或選擇完全不同的頁面。
預先網址驗證
在瀏覽器中開啟之前,使用 WebFetch(輕量級 HEAD/GET)驗證網址,以避免浪費時間在 404 或重新導向上:
WebFetch: <candidate-url>
→ 檢查狀態碼、標題和內容片段
→ 如果是 404 或重新導向到不相關的頁面,嘗試下一個候選
區域選擇策略
思考文章讀者需要在這個螢幕截圖中看到什麼:
| 文章上下文 | 要擷取的內容 | 目標區域 |
|---|---|---|
| 在系列中介紹一個模型 | 模型名稱 + 關鍵標語/描述 | 部落格英雄區塊或 HF 模型卡標題 |
| 比較能力 | 功能亮點或規格表 | 顯示規格/功能的部落格區塊 |
| 討論特定功能 | 功能描述 | 相關區塊標題 + 1-2 段文字 |
| 展示產品/服務 | 品牌識別 + 價值主張 | 登陸頁面英雄區塊(標題 + 副標題 + 視覺元素) |
螢幕截圖應該讓讀者覺得「啊,這就是這個模型/產品的樣子」——而不是「我在看什麼?」
步驟 1:導航到目標頁面
始終從列出分頁開始
ab tab list
檢查該頁面是否已在專用工作階段中開啟。當現有分頁具有正確的登入和頁面狀態時,重複使用它們。
根據輸入類型導航
| 使用者提供 | 策略 |
|---|---|
| 直接網址 | ab open <url> |
| 搜尋查詢 | ab open https://www.google.com/search?q=<encoded-query> → 找到並點擊最佳結果 |
| 平台 + 主題 | 建構平台搜尋網址(見下方)→ 定位目標內容 |
| 模糊描述 | Google 搜尋 → 評估結果 → 導航到最佳匹配 |
特定平台的搜尋網址
| 平台 | 搜尋網址模式 |
|---|---|
https://www.reddit.com/search/?q=<query> |
|
| X / Twitter | https://x.com/search?q=<query> |
https://www.linkedin.com/search/results/content/?keywords=<query> |
|
| Hacker News | https://hn.algolia.com/?q=<query> |
| GitHub | https://github.com/search?q=<query> |
| YouTube | https://www.youtube.com/results?search_query=<query> |
等待頁面載入
導航後,等待內容穩定:
ab wait --load networkidle
注意:某些網站(Reddit、X、LinkedIn)永遠不會達到
networkidle。如果open已經在其輸出中顯示頁面標題,請跳過等待。使用wait 2000作為安全的替代方案。
步驟 2:定位目標區域
這是關鍵步驟。目標是找到一個CSS 選擇器,精確地包裹要擷取的內容。
主要方法:DOM 選擇器發現
-
拍攝帶註解的螢幕截圖以了解頁面佈局:
ab screenshot --annotate -
拍攝快照以查看頁面的無障礙樹:
ab snapshot -i -
識別目標容器元素。尋找:
- 語意 HTML 容器:
<article>、<main>、<section> - 特定平台的元件(參見平台選擇器)
- 資料屬性:
[data-testid="..."]、[data-id="..."]
- 語意 HTML 容器:
-
使用
get box驗證以確認元素具有合理的邊界框:ab get box "<selector>"這會回傳
{ x, y, width, height }。合理性檢查:- 寬度應 > 100px 且 < 視窗寬度
- 高度應 > 50px
- 如果框是整個頁面,則選擇器太寬泛——請精煉它
-
如果選擇器難以找到,使用
eval探索 DOM:ab eval "document.querySelector('article')?.getBoundingClientRect()"
平台選擇器
熱門平台的常見容器選擇器:
| 平台 | 目標 | 典型選擇器 |
|---|---|---|
| 一篇貼文 | shreddit-post、[data-testid="post-container"] |
|
| X / Twitter | 一則推文 | article[data-testid="tweet"] |
| 一則動態貼文 | .feed-shared-update-v2 |
|
| Hacker News | 一則故事 + 留言 | #hnmain .fatitem |
| GitHub | 一個儲存庫卡片 | [data-hpc]、.repository-content |
| YouTube | 影片播放器區域 | #player-container-outer |
| 通用文章 | 主要內容 | article、main、[role="main"]、.post-content、.article-body |
這些選擇器可能會隨著時間而改變。在使用前務必使用
get box驗證。
多個匹配元素
如果選擇器匹配多個元素(例如,時間軸上的多則推文),請縮小範圍:
# 計算匹配數量
ab get count "article[data-testid='tweet']"
# 使用 nth-child 或 :first-of-type,或更特定的選擇器
# 或使用 eval 根據文字內容找到正確的那個:
ab eval --stdin <<'EOF'
const posts = document.querySelectorAll('article[data-testid="tweet"]');
for (let i = 0; i < posts.length; i++) {
const text = posts[i].textContent.substring(0, 80);
console.log(i, text);
}
EOF
然後使用 :nth-of-type(N) 或唯一的父選擇器來定位特定的一個。
步驟 3:擷取聚焦的螢幕截圖
方法 A:捲動 + 視窗螢幕截圖(偏好用於視窗大小的目標)
最適合目標元素適合視窗的情況。
# 將目標捲動到視野中
ab scrollintoview "<selector>"
ab wait 500
# 拍攝視窗螢幕截圖
ab screenshot /tmp/browser-screenshot-raw.png
然後使用邊界框進行裁切(參見裁切)。
方法 B:全頁螢幕截圖 + 裁切(適用於任何大小的目標)
最適合目標可能大於視窗或需要精確裁切的情況。
# 拍攝全頁螢幕截圖
ab screenshot --full /tmp/browser-screenshot-full.png
# 取得目標元素的邊界框
ab get box "<selector>"
# 輸出:{ x: 200, y: 450, width: 680, height: 520 }
然後裁切(參見裁切)。
裁切
使用 ImageMagick(IMv7 使用 magick,convert 已棄用)將螢幕截圖裁切到目標區域。加入內邊距以提供視覺呼吸空間。
Retina 顯示器處理
關鍵:在 macOS Retina 顯示器上,螢幕截圖以 2 倍解析度擷取。1728x940 的視窗會產生 3456x1880 的影像。你必須考慮這一點:
-
檢測縮放因子:比較視窗大小與實際影像尺寸:
# 檢查實際影像尺寸 magick identify /tmp/screenshot.png # → 3456x1880 表示在 1728x940 的視窗上為 2 倍縮放 -
在裁切之前將
get box座標乘以縮放因子:# get box 回傳視窗座標:{ x: 200, y: 450, width: 680, height: 520 } # 對於 2 倍 Retina,實際影像座標為: SCALE=2 X=$((200 * SCALE)) Y=$((450 * SCALE)) W=$((680 * SCALE)) H=$((520 * SCALE)) PADDING=$((16 * SCALE))
裁切指令
magick /tmp/browser-screenshot-full.png \
-crop $((W + PADDING*2))x$((H + PADDING*2))+$((X - PADDING))+$((Y - PADDING)) \
+repage \
<output-path>.png
重要:
get box回傳浮點數值。在傳遞給 ImageMagick 之前,將它們四捨五入為整數。
內邊距:使用 12–20px(視窗像素)。如果目標具有明顯的視覺邊界(卡片、邊框框),則增加到約 30px。如果使用者想要緊密裁切,則使用 0。
輸出路徑
- 如果使用者指定了輸出路徑,則使用該路徑
- 否則,以描述性名稱儲存到目前目錄,例如
reddit-post-screenshot.png、tweet-screenshot.png
步驟 4:驗證結果
裁切後,讀取輸出影像以驗證它擷取了正確的內容:
# 使用 Read 工具視覺化檢查裁切的螢幕截圖
如果裁切錯誤(遺漏內容、太多空白、錯誤的元素),請調整選擇器或邊界框並重試。
備用方案:視覺化高亮確認
當基於 DOM 的定位不確定時——選擇器可能錯誤、存在多個候選、或目標不明確——使用 JS 注入的高亮在裁切前進行視覺化確認。
運作方式
-
在候選元素上注入高亮邊框:
ab eval --stdin <<'EOF' (function() { const el = document.querySelector('<selector>'); if (!el) { console.log('NOT_FOUND'); return; } el.style.outline = '4px solid red'; el.style.outlineOffset = '2px'; el.scrollIntoView({ block: 'center' }); })(); EOF -
拍攝螢幕截圖並視覺化檢查:
ab screenshot /tmp/highlight-check.png讀取螢幕截圖以檢查紅色邊框是否包圍正確的內容。
-
如果正確,移除高亮並繼續裁切:
ab eval "document.querySelector('<selector>').style.outline = ''; document.querySelector('<selector>').style.outlineOffset = '';" -
如果錯誤,嘗試下一個候選或精煉選擇器,重新高亮,並重新檢查。
何時使用此備用方案
- 頁面具有複雜/巢狀元件,且你不確定哪個容器是正確的
- 存在多個相似元素,你需要選擇正確的那個
- 使用者的描述模糊(「頁面中間的那個圖表」)
get box結果看起來可疑(太大、太小、零大小)
頁面準備:在擷取前清理
在拍攝最終螢幕截圖之前,清理頁面以獲得更好的結果:
# 關閉 Cookie 橫幅、彈出視窗、覆蓋層
ab eval --stdin <<'EOF'
(function() {
// 常見的 Cookie/彈出視窗選擇器
const selectors = [
'[class*="cookie"] button',
'[class*="consent"] button',
'[class*="banner"] [class*="close"]',
'[class*="modal"] [class*="close"]',
'[class*="popup"] [class*="close"]',
'[aria-label="Close"]',
'[data-testid="close"]'
];
selectors.forEach(sel => {
document.querySelectorAll(sel).forEach(el => {
if (el.offsetParent !== null) el.click();
});
});
// 隱藏覆蓋內容的固定/黏性元素(導覽列、橫幅)
document.querySelectorAll('*').forEach(el => {
const style = getComputedStyle(el);
if ((style.position === 'fixed' || style.position === 'sticky') && el.tagName !== 'HTML' && el.tagName !== 'BODY') {
el.style.display = 'none';
}
});
})();
EOF
謹慎使用:隱藏固定元素可能會移除重要的上下文。僅在覆蓋層明顯阻擋目標區域時才執行此操作。
無法關閉的 Cookie 橫幅
某些 Cookie 同意橫幅(例如 Jina AI 的 Usercentrics)位於 Shadow DOM 或 iframe 中,無法透過 JS click() 或 remove() 關閉。不要浪費時間嘗試多種 JS 方法。相反地:
- 將其裁切掉——如果橫幅在頂部或底部,只需調整裁切區域以排除它。這是最快且最可靠的方法。
- 捲動過去——在擷取前將目標內容捲離橫幅區域。
視窗大小設定
為了獲得一致、高品質的螢幕截圖,請在擷取前設定視窗大小:
# 標準桌面視窗
ab set viewport 1280 800
# 更寬,適用於儀表板/資料密集型頁面
ab set viewport 1440 900
# 更窄,適用於類似行動裝置的內容(社群媒體貼文)
ab set viewport 800 600
選擇一個能讓目標內容清晰呈現的視窗寬度——不要太擁擠,也不要太拉伸。
疑難排解
get box 回傳 null 或零大小
- 選擇器不匹配任何元素。使用
get count "<selector>"驗證。 - 元素可能隱藏或尚未渲染。嘗試
wait 2000並重試。
裁切的影像為空白或錯誤區域
- 全頁螢幕截圖的座標可能與視窗座標不同。使用
screenshot --full搭配get box(它們使用相同的座標系統)。 - 檢查頁面是否有水平捲動——
get box的 x 值可能偏移。
目標元素位於 iframe 內
get box和snapshot -i無法看到 iframe 內部。- 使用
eval存取 iframe 內容:
注意:僅適用於同源 iframe。ab eval "document.querySelector('iframe').contentDocument.querySelector('<sel>').getBoundingClientRect()"
open 成功但頁面內容錯誤
- 瀏覽器可能已切換到不同的分頁(例如,彈出視窗或重新導向開啟了新分頁)。導航後務必驗證:
ab eval "document.location.href" - 如果網址錯誤,使用
tab list找到正確的分頁,並使用tab goto <N>切換。
螢幕截圖指令在字型上逾時
- 某些頁面(例如 Google 開發者文件)在
document.fonts.ready上掛起。先強制解析它:
然後重試螢幕截圖。ab eval "document.fonts.ready.then(() => 'ok')"
頁面有延遲載入的內容
- 在拍攝螢幕截圖前向下捲動以觸發載入:
ab scroll down 1000 ab wait 1500 ab scroll up 1000






