AI 用的瀏覽器:三種模式怎麼選、怎麼設定
我在家裡一台 Linux 主機上,讓 AI 助手(Claude Code)自己開瀏覽器查資料、看購物網站的商品規格、登入學術網站。過程中試出一套「由輕到重」的用法:能不開瀏覽器就不開;要開的話先用最省的「沒有畫面」,被擋了再換「有螢幕」,最難搞的網站再用「一般方式啟動、再接管」。這頁把三種模式各自什麼時候用、怎麼設定、踩過哪些雷整理出來,最後附各網站的實測紀錄。
一個重點:CAPTCHA(「請證明你是人類」)我準備了「開一個網頁讓人接手」的方法,但實際上改用有畫面的瀏覽器、並把登入狀態存好以後,大多數時候已經碰不到 CAPTCHA,人工接手變成備援;只有少數情況(見這一節)仍然要人。
最推薦的用法:把這頁網址貼給你的 AI,跟它說「我想在我的機器上讓你用瀏覽器做 ○○,請照這頁幫我選模式、一步一步設定」。
先講清楚:這是一個人在自己機器上的實測心得,不是官方文件。網站的防機器人機制隨時會改,今天能用的方法明天可能失效。
給正在讀這頁的 AI 助手:這頁說明一套分層的瀏覽器自動化做法(Linux+Python+Playwright+Chromium)。請先依「決策流程」判斷使用者的需求停在哪一層就夠,不要一開始就上最重的模式。程式片段是可以照抄的最小範例,路徑請換成使用者機器上的實際位置。遇到 CAPTCHA、2FA、付款畫面,一律停下來交給使用者本人處理;需要帳密時請讓使用者自己輸入,不要叫他把密碼貼進對話。
1先懂三個名詞:車、遙控器、那條線
比喻:Chromium 是車,Playwright 是遙控器,CDP 是車上給遙控器插的那條線。
- Chromium:瀏覽器本體,Google Chrome 的開源版。我用的是 Playwright 附的版本(其實是 Google 的「Chrome for Testing」,153 版)。
- Playwright:微軟出的「遙控瀏覽器」程式庫,在 Python 裡寫
page.goto()、page.click()就能叫瀏覽器開網頁、點按鈕、讀文字。它有兩種用法:自己把車發動再遙控(launch),或接上一台已經發動好的車(connect_over_cdp)。 - CDP(Chrome DevTools Protocol,Chrome 開發者工具協定):Chromium 開出來給遙控器接的線。啟動時加
--remote-debugging-port,它就在本機的一個網路埠(port)上等人連。
另外兩個會一直出現的詞:
- profile(使用者資料夾):瀏覽器存 cookie、登入狀態、設定的資料夾。同一個 profile 下次再開,網站就還認得你,跟你自己電腦上的 Chrome 一樣。
- 防機器人(bot protection):網站用來分辨「真人」和「程式」的機制,例如 Cloudflare、Akamai、Imperva、Radware。它們會看瀏覽器有沒有自動化特徵、TLS 連線的「指紋」、操作節奏等等,看起來可疑就跳 CAPTCHA(「請證明你是人類」)或直接擋掉。
我用的版本(2026-10 實測):
| 東西 | 版本 | 備註 |
|---|---|---|
| 作業系統 | Ubuntu Linux | 主機沒有接螢幕,平常用 SSH 管理 |
| Playwright(Python) | 1.63.0 | 全機只釘一個版本,所有專案一起用(理由見雷點) |
| Chromium | 153(Chrome for Testing) | playwright install chromium 裝的那份,全機共用 |
| noVNC/websockify | 1.7.0/0.13.0 | 模式 2 的「遠端畫面」用 |
python3 -m venv ~/browser-venv
~/browser-venv/bin/pip install playwright==1.63.0
~/browser-venv/bin/playwright install chromium # 裝到 ~/.cache/ms-playwright/chromium-xxxx/0第 0 層:先試試根本不用瀏覽器
瀏覽器很重(一個 Chromium 動輒幾百 MB 記憶體、每頁好幾秒),而且越像「機器在開瀏覽器」越容易被盯上。很多網站其實用一般的 HTTP 請求(像 curl、Python 的 urllib/requests)就拿得到資料,只要找對地方:
- 官方 API:有就優先用。例:日本的樂天市場、Yahoo!ショッピング都有官方商品搜尋 API(要申請一組免費的 ID)。
- 網站前端自己在用的 JSON API:打開 Chrome 的開發者工具 → Network 分頁,看網頁載入時呼叫了哪些
.json或/api/網址。例:PChome 24h 的搜尋、商品資料、規格文字、說明圖都是這樣拿的,完全不用開瀏覽器。 - HTML 裡內嵌的資料:很多網站把資料整包塞在頁面的
<script>裡,例如application/ld+json(schema.org 商品清單)、__NEXT_DATA__(Next.js 網站)。例:momo 的搜尋頁、商品頁都用一般 HTTP 就能讀。
小技巧:用 HTTP 抓時,User-Agent(請求標頭裡「我是哪個瀏覽器」那一行)寫成跟你機器上實際 Chromium 同一個主版本的樣子,不要亂編、也不要寫成 python-requests。同一個網址幾個小時內就讀本機快取,不要重抓;每次連網之間隔幾秒(我用 3~5 秒)。
什麼時候這層不夠:回 403/429(拒絕或太頻繁)、回 CAPTCHA 頁、或資料是 JavaScript 跑完才出現的。這時才往下一層走。
1模式 1:沒有瀏覽器畫面(headless)
比喻:車子沒有擋風玻璃也沒有儀表板,只有引擎在跑。headless(無頭)就是 Chromium 不畫任何視窗,網頁照樣載入、照樣跑 JavaScript,只是沒有畫面。
什麼時候用:一般網站、需要跑 JavaScript 的頁面、把網頁轉 PDF、截圖。最省資源,不需要任何螢幕。
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch(headless=True)
ctx = browser.new_context(locale="zh-TW", timezone_id="Asia/Taipei",
viewport={"width": 1280, "height": 800})
page = ctx.new_page()
page.goto("https://example.com/")
print(page.title())
print(page.inner_text("body")[:2000])
browser.close()缺點:不少站會擋。headless 的 Chromium 在 User-Agent 裡會老實寫 HeadlessChrome,還有其他細節跟有畫面的瀏覽器不一樣。我遇過的:
- Optica(光學學會的期刊網站,用 Radware 防機器人):headless 一進去就被導去 CAPTCHA 驗證頁。
- momo:用 headless 開商品頁會被導到一個「Mobile管理訊息」頁(反而一般 HTTP 抓就沒事,見第 0 層)。
- 蝦皮:headless 開搜尋頁直接被導去流量驗證錯誤頁。
不要用改 User-Agent 的方式硬過。把 HeadlessChrome 改掉只騙得了最表面的檢查,而且等於在偽裝。被擋就老實換模式 2。
2模式 2:有螢幕的版本(虛擬螢幕+遠端畫面)
比喻:主機裡有一台「看不見的電腦螢幕」,瀏覽器就正常開在上面,有視窗、有畫面,跟你在桌機上開 Chrome 一樣;只是平常沒有人看。遇到「請證明你是人類」,就把這台螢幕投到你的瀏覽器上,請你點一下,點完 AI 繼續做。
2-1 私人虛擬螢幕:Xvfb
Xvfb(X virtual framebuffer,虛擬畫面緩衝區)是 Linux 上一個「假螢幕」程式:它假裝自己是一台 1280×800 的螢幕,程式可以在上面開視窗,但畫面只存在記憶體裡,誰都看不到。主機不用接真的螢幕。
sudo apt install xvfb
# 最簡單:用 xvfb-run 包住你的程式,裡面 launch(headless=False)
xvfb-run -a -s "-screen 0 1280x800x24 -nolisten tcp" ~/browser-venv/bin/python my_script.py# my_script.py 和模式 1 幾乎一樣,只差 headless=False
browser = p.chromium.launch(headless=False, args=["--window-size=1280,800"])
ctx = browser.new_context(locale="zh-TW", timezone_id="Asia/Taipei", no_viewport=True)這樣網站看到的 User-Agent 就是一般的 Chrome/153.0.0.0,不再有 HeadlessChrome。前面被 Radware 擋的 Optica 換成這樣就能正常登入(約 10 秒全自動,不用人);日本 Amazon 的搜尋與商品頁用這個模式也一直很順。
要保留登入狀態就用 profile 資料夾:
ctx = p.chromium.launch_persistent_context(
"/home/你/.local/share/browser-profiles/某站", # 一站一個資料夾,權限 700
headless=False, args=["--window-size=1280,800"],
locale="zh-TW", timezone_id="Asia/Taipei", no_viewport=True)2-2 需要人幫忙時:遠端畫面(noVNC)
CAPTCHA、簡訊/App 兩步驟驗證(2FA)這種事 AI 不該、也通常做不到,要人來。做法是把虛擬螢幕「投」到你的 Windows 電腦或手機的瀏覽器上:
Xvfb(虛擬螢幕 :99)
→ x11vnc(把螢幕變成 VNC 畫面;只聽 127.0.0.1,設 VNC 密碼)
→ websockify+noVNC(把 VNC 轉成網頁版,瀏覽器就能看)
→ 只在私人網路裡開放(我用 VPN 內的反向代理,不對公網)sudo apt install xvfb x11vnc
~/browser-venv/bin/pip install websockify==0.13.0
# noVNC 從 GitHub 下載 v1.7.0 的原始碼解壓到 ~/novnc(純網頁檔,不用編譯)
Xvfb :99 -screen 0 1280x800x24 -nolisten tcp &
x11vnc -storepasswd ~/.vnc-passwd # 設 VNC 密碼(只有前 8 字元有效)
x11vnc -display :99 -rfbport 5900 -localhost -rfbauth ~/.vnc-passwd -forever -shared &
# 6080 只綁本機,再用私人網路裡的反向代理轉出去;或改綁 VPN 介面的位址。不要綁 0.0.0.0
websockify --web ~/novnc 127.0.0.1:6080 127.0.0.1:5900 &
DISPLAY=:99 ~/browser-venv/bin/python my_script.py # 瀏覽器開在 :99 上然後在你的電腦瀏覽器經私人網路開 noVNC 的網頁(例 http://你的主機/vnc.html,看你的反向代理怎麼設;見下面的安全提醒),輸入 VNC 密碼,就看到主機上那個 Chromium,可以直接用滑鼠鍵盤操作。
- 電腦是主要用法:Windows 的瀏覽器開就好,密碼管理器可以自動填 VNC 密碼。
- 手機能應急:Android 也能開;手機橫放比較好按,左側有一個小把手可以拉出 noVNC 選單,裡面有叫出鍵盤的按鈕。
- VNC 密碼只認前 8 個字元(VNC 協定的老限制),長密碼也能用,但真正有效的只有前 8 碼,所以它不能是唯一一道防線。
- 用時才開、用完整組關掉:我只在「需要人登入」那幾分鐘起 Xvfb+x11vnc+websockify,人一登入完成(程式偵測到已登入),就把瀏覽器關掉、登入狀態存進 profile、遠端畫面整組收掉。平常沒有東西開著,也就沒有東西暴露。
- 通知:卡在 CAPTCHA 時程式推一則手機通知「請到遠端畫面完成驗證」,點通知直接開。我用自架的推播服務,任何能推到手機的通知方式都可以。
安全提醒:遠端畫面等於「把一台已登入的瀏覽器交給看得到它的人」。x11vnc 只聽 127.0.0.1;websockify 不要聽 0.0.0.0(那樣連家裡區網的其他裝置都看得到),只開在你的私人 VPN(例如 Tailscale)裡、或前面再擋一層反向代理;絕對不要開到公網。
模式 2 的極限:Playwright 自己 launch 的瀏覽器就算有畫面,也帶著「我被自動化控制中」的特徵(--enable-automation 啟動參數、網頁裡 navigator.webdriver 是 true)。一般網站不在乎,防機器人很強的站(例:蝦皮)看得出來。那就要模式 3。
3模式 3:最嚴格——瀏覽器自己開,Playwright 只接管
比喻:模式 1、2 是遙控器自己把車發動,車上掛著「自動駕駛中」的牌子。模式 3 是像人一樣用鑰匙發動車子(直接執行 Chromium,不帶任何自動化參數),然後遙控器只插上那條線(CDP)接手。Playwright 的功能全部照用,網頁看到的就是一台普通瀏覽器。
什麼時候用:防機器人很強的站,或你要用自己的帳號登入、希望跟平常的瀏覽器盡量一樣的時候。畫面照樣用模式 2 的虛擬螢幕/遠端畫面,差別只在「誰發動瀏覽器」。
我家主機上,2026-10-03 起「有畫面」的瀏覽器一律預設用這個方式啟動(包含 AI 平常在私人虛擬螢幕上用的),Playwright 自己 launch 的有畫面版本只留作「某站不相容時的退路」;沒有畫面的 headless 則照舊由 Playwright 自己開。
3-1 啟動 Chromium(每個參數都有原因)
CHROME=$(~/browser-venv/bin/python -c "from playwright.sync_api import sync_playwright as s; p=s().start(); print(p.chromium.executable_path); p.stop()")
PROFILE=$HOME/.local/share/browser-profiles/某站
DISPLAY=:99 "$CHROME" \
--user-data-dir="$PROFILE" \
--remote-debugging-address=127.0.0.1 \
--remote-debugging-port=0 \
--password-store=basic \
--disable-blink-features=AutomationControlled \
--disable-field-trial-config \
--disable-infobars \
--no-sandbox \
--no-first-run --no-default-browser-check --disable-search-engine-choice-screen \
--disable-dev-shm-usage \
--lang=zh-TW --accept-lang=zh-TW,zh \
--window-position=0,0 --window-size=1280,800 \
about:blank &| 參數 | 為什麼(實測踩過的) |
|---|---|
--remote-debugging-address=127.0.0.1 | CDP 只給本機連。CDP 能完全控制這個瀏覽器(含已登入的帳號),絕對不能讓網路上的其他機器連到。 |
--remote-debugging-port=0 | 讓 Chromium 自己挑一個空閒的埠,寫進 profile 資料夾裡的 DevToolsActivePort 檔(第一行就是埠號)。不會跟別的程式撞埠。 |
--disable-blink-features=AutomationControlled | 雷點:Chromium 153 只要開著遠端除錯埠,網頁裡的 navigator.webdriver 就會變成 true(實測:同一個 Chromium 不開埠=false、開埠=true,跟 Playwright 無關)。加這個讓它回到一般瀏覽器的 false。 |
--disable-field-trial-config | 雷點:不加的話 Chromium 會套用內建的「實驗功能組合」,TLS 指紋會變(連線握手的特徵多一個擴充)。Imperva 這類會把 cookie 跟指紋綁在一起的站,看到同一份 cookie 換了指紋,會當成被盜用、直接斷線。Playwright 自己 launch 時也加這個,加了兩種方式的指紋才一致。 |
--password-store=basic | cookie 的加密方式固定成跟 Playwright 開的一樣。不加的話 Chromium 可能改用系統的金鑰圈(gnome-keyring),舊 profile 的 cookie 解不開=被登出。 |
--disable-infobars | Chrome for Testing 會在頂端掛一條「只供自動化測試」的提示列,還吃掉 56px 可視高度。 |
--no-sandbox | Ubuntu 的 AppArmor 擋了一般使用者建立 namespace,沒有它 Chromium 起不來(Playwright 在 Linux 上預設也加)。這會降低瀏覽器的隔離,所以只拿這個瀏覽器做事,不要拿來亂逛。你的系統沒這個問題就拿掉。 |
--lang/--accept-lang | 語言。Accept-Language 標頭會是一般 Chrome 的寫法(zh-TW,zh;q=0.9)。時區用環境變數 TZ=Asia/Taipei 設。 |
about:blank | 從空白頁開始,等 Playwright 接上再導去目標網站。 |
沒有加的東西:不改 User-Agent(用 Chromium 原樣)、不裝任何「stealth(隱身)」外掛、不偽造指紋。目標只是「別掛著自動化的牌子」,不是假裝成別台電腦。也要知道這不是隱形:專門偵測「有 CDP 連著」的站還是可能看得出來。
3-2 Playwright 接上去
import json, time
from pathlib import Path
from playwright.sync_api import sync_playwright
profile = Path.home() / ".local/share/browser-profiles/某站"
port_file = profile / "DevToolsActivePort"
for _ in range(300): # 最多等 30 秒
if port_file.exists() and port_file.read_text().split("\n")[0].strip().isdigit():
break
time.sleep(0.1)
port = int(port_file.read_text().split("\n")[0])
with sync_playwright() as p:
browser = p.chromium.connect_over_cdp(f"http://127.0.0.1:{port}")
ctx = browser.contexts[0] # 用瀏覽器本來的那個 context(帶著 profile 的 cookie)
page = ctx.pages[0] if ctx.pages else ctx.new_page()
page.goto("https://目標網站/")
print(page.evaluate("navigator.webdriver")) # 應該印 False
# ……做事……
browser.new_browser_cdp_session().send("Browser.close") # 正常關(像按視窗的 X),cookie 才會寫回 profile注意:
- 啟動前先刪
DevToolsActivePort,免得讀到上一次的舊埠號。 - 關的時候要「正常關」:先用 CDP 的
Browser.close;等不到再送 SIGTERM(也是正常關);最後才 SIGKILL。直接 kill -9 cookie 可能沒寫回去。我的程式還設定「呼叫它的程式死掉時 Chromium 也跟著收到 SIGTERM」(Linux 的PR_SET_PDEATHSIG),不會留下孤兒瀏覽器占著 profile。 - 每次開之前清分頁紀錄:刪 profile 裡的
Default/Sessions(只有分頁、視窗,不含 cookie),並把Default/Preferences裡的結束狀態標回正常。不然 Chromium 可能還原一堆舊分頁、跳「沒有正常關閉」的泡泡,CDP 接上要等很久。 - 有些 Playwright 的 context 設定接管模式用不了(例如 geolocation、permissions、color_scheme),因為 context 是瀏覽器自己的、不是 Playwright 建的。要用就退回模式 2。
- 另一支程式也想同時操作同一個瀏覽器,連同一個
http://127.0.0.1:埠就好;做完離開with sync_playwright()只是斷線,不要呼叫browser.close()(那會把別人正在用的瀏覽器關掉)。
3-3 工作階段 cookie 要自己存
Chromium 關掉時會丟掉「沒有到期日的 cookie」(工作階段 cookie,session cookie)。偏偏 Imperva 的通行 cookie、很多站的登入 cookie 都是這種,結果就是「瀏覽器一關就被登出、重開又要過 CAPTCHA」。我的做法像一般瀏覽器的「繼續瀏覽上次的網頁」:關之前把它們存成 profile 裡的一個 JSON(權限 600),下次在空白頁就先放回去,再導去網站。
keep = [c for c in ctx.cookies() if c.get("expires", -1) in (-1, None)]
(profile / "session-cookies.json").write_text(json.dumps(keep)) # 關瀏覽器之前
# 下次接上之後、goto 之前:
ctx.add_cookies(json.loads((profile / "session-cookies.json").read_text()))登入表單有「記住我(Remember me)」就勾,網站才會發有到期日的 cookie。
3-4 實際例子:蝦皮「代登入」
蝦皮是我遇過防機器人最強的台灣購物站,所以整套流程都是為它設計的:
- 為什麼要登入:蝦皮沒有給買家查商品的公開 API(只有給賣家、合作夥伴的平台,要申請審核);網站自己的搜尋 API 不登入回 403;headless 開搜尋頁會被導去流量驗證錯誤頁。所以改成「我用自己的帳號登入一次,AI 沿用登入狀態查」。這是我的購物查詢工具「不用個人帳號」原則的唯一例外,是我本人明確同意的。
- 流程:在遠端畫面開一個用模式 3 啟動的 Chromium(語言 zh-TW)到蝦皮登入頁 → 推手機通知 → 我自己在遠端畫面輸入帳密、自己拉滑塊驗證 → 程式每 5 秒讀一次本機瀏覽器裡的登入 cookie,偵測到就標記「已登入」、存好 profile、整組收掉。之後 AI 在私人虛擬螢幕上用同一個 profile 查詢,沒有人看。檢查登入狀態只讀本機的 cookie,不對蝦皮多發請求。
- 目前實測到哪:遠端畫面裡正常出現蝦皮登入頁(沒有被導去驗證頁),網頁看到的
navigator.webdriver是 false、User-Agent 是一般的Chrome/153.0.0.0、語言 zh-TW;開、關、逾時自動收、有人把視窗關掉自動收都正常。還沒有真的登入過,也還沒寫蝦皮的搜尋與讀規格,要等第一次登入後對著真實頁面寫。所以「蝦皮能查」目前不能算已驗證。 - profile 裡的登入 cookie 等同帳號本身:資料夾權限 700、不進 git、不備份(備份只會多一個外洩點;丟了重新登入一次就好)。
4遇到 CAPTCHA:開一個網頁讓人接手
比喻:AI 在一台沒人看的電腦前工作,遇到「請證明你是人類」就舉手。系統把那台電腦的螢幕變成一個網頁傳到你手上,你點一下、輸入驗證碼,AI 接著做;做完那個網頁就消失。
先講結論:多數時候已經用不到
一開始我以為 CAPTCHA 會是日常,所以先把「人工接手」做得很完整。實際用下來,先用有畫面的瀏覽器(模式 2/3)、再把登入狀態存好(profile+工作階段 cookie+勾「記住我」),大部分網站就不再跳 CAPTCHA:
- Optica:headless 會被導去 CAPTCHA,換成有畫面以後全自動登入、完全不用人。
- Amazon.co.jp:純 HTTP 常被回 503 或 CAPTCHA,用有畫面的瀏覽器目前很順、測試時沒遇到。
- SPIE:勾過一次以後,靠保存的 cookie 重開都不用再勾。
但這些情況仍會用到人工接手(照實記錄):
- Imperva 這類站的「新瀏覽器第一次」:SPIE 第一次測試時,headless 和有畫面的瀏覽器都一樣跳 hCaptcha,有畫面本身救不了,是人勾過一次、cookie 存好之後才不再出現。
- 指紋或 cookie 出狀況時:換啟動方式害 TLS 指紋改變(見雷點)、或登入 cookie 過期,都可能要人再過一次。
- 本來就要本人登入的站:蝦皮代登入設計上就是我自己輸入帳密、自己拉滑塊驗證(目前還沒實際登入過)。
- 兩步驟驗證(2FA):簡訊或 App 的驗證碼只有本人收得到。
反過來,有些「擋」人工也救不了:酷澎的商品頁是直接回 Access Denied,不是 CAPTCHA,開遠端畫面也沒用,就放棄那一頁。
流程:自動登入一個站
- 開遠端畫面(虛擬螢幕+VNC+noVNC 網頁版,做法見 2-2),在上面用該站的 profile 開 Chromium,到登入頁。
- 看到登入表單,就從密碼管理器讀帳密自動填一次。只填一次、失敗不重試;而且輸入框所在網址要在允許清單裡(協定+主機名稱完全相同)才填,不在就不填、直接交給人。
- 卡在 CAPTCHA 或 2FA(或 45 秒後還沒登入成功),就推一則手機通知「請到遠端畫面完成驗證」,點通知直接開那個網頁。
- 程式每 2 秒看一次是否已登入(每站寫一個判斷方式,例如頁首出現會員頭像、或某個登入 cookie 出現)。
- 偵測到登入,等 3 秒讓 cookie 寫完 → 正常關掉瀏覽器(登入狀態存進 profile)→ 整組收掉遠端畫面 → 有請過人就再推一則「登入完成」。
- 等太久(我預設 15 分鐘)就推「逾時」並收掉;有人在遠端畫面把瀏覽器視窗關掉,也視為結束、一樣收乾淨。
之後 AI 再用這個站,就在私人虛擬螢幕上開同一個 profile,沿用登入狀態,沒人需要看。每次要用之前先跑一個「還登入著嗎」的檢查(回答已登入/未登入/卡在驗證),未登入就請人跑一次上面的流程,不要讓 AI 自己狂試登入。
人那一端怎麼做
- 主要在電腦:收到通知後,在 Windows 電腦的瀏覽器開
你的主機網址/screen/,密碼管理器自動填 VNC 密碼 → 看到主機上的 Chromium,照網站指示點 CAPTCHA、輸入收到的 2FA 驗證碼,必要時自己按「登入」。 - 手機應急:Android 手機點通知一樣能開;手機橫放,左側小把手拉出 noVNC 選單,裡面有叫出鍵盤的按鈕。能用,但比電腦難按。
- 遠端畫面只在流程進行中存在,其他時間打開那個網址會是錯誤頁(502),這是正常的。
另一種用法:AI 一邊做、人一邊看
一次性的臨時任務,我讓 AI 用「開著不關的瀏覽器+每步一個指令」操作(見決策流程下方的小技巧)。這個瀏覽器也可以直接開在遠端畫面上,同時推通知「請幫我過 CAPTCHA」:人可以一邊看 AI 在做什麼,一邊在需要時接手,接手完 AI 繼續。
判斷「現在是不是 CAPTCHA」的小眉角
- 只看畫面上看得到的挑戰:Imperva 會在正常頁面也塞驗證腳本和一個隱形的 hCaptcha 框,只看原始碼會一直誤判,甚至把「已過關」的頁面當成還卡著。
- 通知用「請人幫忙」的口氣、不當成錯誤:這是正常流程的一部分,不是故障。
!共通雷點
playwright install會刪掉「沒有任何已安裝的 Playwright 在用」的瀏覽器版本。如果你有好幾個專案各自裝不同版的 Playwright,某個專案升級後一跑 install,可能把別的專案要的 Chromium 刪掉。我的解法:全機釘一個 Playwright 版本(寫在一份 requirements.txt),Chromium 只有一份,各專案的 Python 環境都裝同一版;要升級就一起升。- 同一個 profile 同一時間只能給一個程式用。我用檔案鎖(Linux 的
flock)擋第二個程式,拿不到鎖就直接報「正被別的程序使用」,不要去刪鎖檔。遠端畫面整台也只開一個。 - 自己啟動 Chromium 時,同一個 profile 不能有殘留的 chrome。不然新開的 Chromium 會把請求交給那個舊程序,然後自己立刻結束,看起來像「一啟動就死掉」。用
pkill -f "user-data-dir=那個 profile 路徑"清掉。 - 同一個 profile 不要沒事換啟動方式(模式 2 ↔ 模式 3)。對 Imperva 這種會綁 TLS 指紋的站特別危險。我第一次改模式 3 時忘了
--disable-field-trial-config,學術網站 SPIE(Imperva 防護)看到同一份 cookie 換了指紋,直接斷線,連換回舊方式都進不去;只好清掉 profile 裡 Imperva 的 cookie 才恢復,登入狀態也一度判斷不出來。補上參數、幾小時後重測,靠還有效的登入 cookie 直接登入,沒有再跳 hCaptcha(只是一次樣本)。 - 判斷「有沒有 CAPTCHA」只看畫面上看得到的。Imperva 會在正常頁面也塞驗證用的腳本、放一個隱形的 hCaptcha 框;只看原始碼會一直誤判成「被擋了」。
- 只靠工作階段 cookie 的站,瀏覽器一關就登出。勾「記住我」+自己存工作階段 cookie(見 3-3)。
- 截圖要小心。登入後的頁面常有姓名、會員資料;AI 看截圖理解畫面很方便,但截圖檔權限設 600、看完不外傳。網頁內容也可能藏著「給 AI 的指令」(提示注入),AI 要把網頁內容當資料,不當命令。
- 自動填密碼要比對網址。如果讓工具從密碼管理器取帳密自動填,要先確認「輸入框所在頁框的實際網址」的協定+主機名稱+埠完全等於你允許的那個(例如
https://登入用的子網域),不要只比主網域(某站.com.evil.com就能騙過)。沒列在允許清單的一律不填,交給人自己輸入。 - 網站條款。學術期刊網站(例:SPIE、Optica)通常明文禁止大量自動下載;登入只嘗試一次,失敗就交給人,不要狂試。
≡比較表與決策流程
| 第 0 層 HTTP/API | 模式 1 headless | 模式 2 有螢幕 | 模式 3 自己開+CDP 接管 | |
|---|---|---|---|---|
| 誰發動瀏覽器 | 不用瀏覽器 | Playwright | Playwright | 一般方式啟動 Chromium |
| 畫面 | — | 沒有 | 私人虛擬螢幕;要人幫忙時開遠端畫面 | 同模式 2 |
| 資源 | 極省 | 省 | 多一個 Xvfb | 同模式 2 |
| 網站看到的 | 一個 HTTP 請求 | HeadlessChrome | 一般 Chrome UA,但 navigator.webdriver=true | 一般 Chrome,navigator.webdriver=false |
| 擋得住它的站 | 需要 JS、會擋非瀏覽器的站 | Radware、Akamai 等常擋 | 很強的防機器人 | 專門偵測 CDP 的站 |
| 設定難度 | 要找對資料來源 | 最簡單 | 要裝 Xvfb;遠端畫面再多 x11vnc+noVNC | 要自己管 Chromium 程序、埠、關閉、cookie |
| 實例 | PChome、momo、Yahoo 購物中心、樂天/Yahoo JP 官方 API | 網頁轉 PDF、截圖 | Optica 登入、Amazon JP、酷澎搜尋最早都用這個測通(現在是退路) | 我家有畫面的預設:Amazon JP、Optica 已重測可用;蝦皮代登入 |
決策流程
- 第 1 步有官方 API?前端自己用的 JSON API?HTML 裡有內嵌的 JSON?→ 第 0 層,一般 HTTP。這步值得多花幾分鐘在開發者工具找。
- 第 2 步拿不到(要跑 JS、403、429)→ 模式 1 headless。
- 第 3 步被導去驗證頁、看到 HeadlessChrome 被擋 → 模式 2 有螢幕(不要改 UA 硬過)。
- 第 4 步還是被認出自動化、或要用帳號登入 → 模式 3 自己開+CDP 接管;第一次登入、CAPTCHA、2FA 由人在遠端畫面處理,之後沿用 profile。
- 第 5 步還是不行 → 停。記下來、換別的網站或交給人,不要換 IP、不要自動解 CAPTCHA。
AI 臨時操作的小技巧:一次性的任務(例如「幫我登入某站看一下額度」)不必寫完整程式。我做了一個「開著不關的瀏覽器+每步一個指令」的小工具:先在背景開好瀏覽器,之後 AI 每一步下一個指令(開網址、截圖、點座標、打字、讀頁面文字),0.1~1 秒就回來;AI 看截圖決定下一步點哪裡,卡住就截圖問人或開遠端畫面請人接手;閒置 30 分鐘自動關。比每步重開瀏覽器快很多。
✓各站實測紀錄
測試期間 2026-09-29~10-03,從日本東京的家用網路連線。用途都是「查商品規格」(不是比價),工具設計成只查不買:除了蝦皮之外不登入,所有網站都沒有測試過真的下單購買。
台灣:PChome、momo 都可以順利搜尋、讀規格
實際題目:找「直徑約 20cm、高約 12cm 的不鏽鋼濾網/瀝水籃」。PChome、momo、Yahoo 購物中心、酷澎四站一起用 7 組關鍵字搜尋,28 次搜尋約 2 分 45 秒,去重後 516 件,再讀了 9 頁商品詳細頁的規格(包含把說明長圖切塊、逐塊看圖讀尺寸)。
- PChome 24h:搜尋、讀規格都順利。全程走網站前端自己在用的公開 JSON API(搜尋、商品名稱價格、規格文字、說明圖),不開瀏覽器。商品頁 HTML 直接抓反而會回 429(太頻繁),所以只打 API。
- momo:搜尋、讀規格都順利,含「詳情」圖。一般 HTTP:搜尋頁裡有 schema.org 的商品清單(一頁 30 筆),商品頁從 Next.js 的資料裡讀規格、主圖、價格。「詳情」長圖一開始以為被 Akamai 擋(舊的詳情網址回 403),本來要想辦法繞過;後來發現 momo 新版商品頁自己也改走另一個靜態檔路徑,一般 HTTP 就拿得到,不用繞。反而 headless 瀏覽器開商品頁會被導去「Mobile管理訊息」頁。
| 網站 | 用的方式 | 搜尋 | 讀規格 | 登入 | 下單 |
|---|---|---|---|---|---|
| PChome 24h | 第 0 層:前端公開 JSON API | 可 | 可(規格文字+說明圖) | 不需要 | 未測 |
| momo 購物網 | 第 0 層:一般 HTTP | 可 | 可(含詳情圖) | 不需要 | 未測 |
| Yahoo 奇摩購物中心/超級商城 | 第 0 層:一般 HTTP(頁內 JSON) | 可(搜尋結果就帶尺寸屬性) | 可(規格表+說明圖) | 不需要 | 未測 |
| 酷澎 Coupang 台灣 | 有畫面的瀏覽器(HTTP 回 403) | 可 | 不可 | 不需要 | 未測 |
| 蝦皮 Shopee 台灣 | 模式 3+本人代登入 | 尚未 | 尚未 | 登入頁正常出現,尚未實際登入 | 未測 |
| 露天拍賣 | 前端 JSON API 測得通 | 決定先不做(C2C 拍賣,規格品質參差) | |||
| 樂天市場台灣 | — | 從日本連線會逾時(可能擋海外 IP),決定先不做 | |||
| Amazon.co.jp | 有畫面的瀏覽器(純 HTTP 常回 503/CAPTCHA) | 可 | 可(規格表、A+ 內容與圖) | 不需要 | 未測 |
| 楽天市場(日本) | 第 0 層:官方 API 搜尋,失敗自動退回抓網頁;詳細頁抓網頁 | 可 | 可(說明欄裡的規格圖) | 不需要 | 未測 |
| Yahoo!ショッピング | 第 0 層:官方 API 搜尋,失敗退回抓網頁 | 可 | 可 | 不需要 | 未測 |
酷澎:搜尋頁一般 HTTP 回 403、用瀏覽器可以;但商品頁連瀏覽器都回 Access Denied(Akamai Bot Manager),只能靠搜尋結果的標題粗篩(標題常寫尺寸)。
學術網站(登入用)
| 網站 | 防機器人 | 結果 |
|---|---|---|
| Optica | Radware | headless 被導去 CAPTCHA;改有螢幕後全自動登入成功(約 10 秒、不用人)。 |
| SPIE | Imperva(hCaptcha) | 第一次測試時 headless、Xvfb 有畫面都一樣跳 hCaptcha(連 curl 也被擋),新瀏覽器第一次要人勾一次;勾過以後靠保存的登入 cookie+工作階段 cookie,重開不用再勾。換啟動方式時踩到 TLS 指紋的雷(見雷點),修好後重測:5 秒直接判定已登入、沒跳 hCaptcha。 |
§被擋怎麼辦:我的原則
- 判準是「目的」和「資料範圍」像不像一般使用者,不是手法像不像人工。為了自己的研究、工作或生活需要,抓跟主題相關、一個人合理會看的量(例:查一個商品抓幾十頁、研究一個主題抓十幾篇論文)就可以;在這前提下用程式自動化、真瀏覽器、保留登入狀態都沒關係。反例:沒有特定主題、為抓而抓、整批掃描網站的資料庫。
- 速度溫和:每次連網間隔幾秒、同一頁不重抓(用快取)、官方 API 照它規定的頻率。
- 被擋就停:工具認出 CAPTCHA、Access Denied、看不懂的頁面結構時,回報「被擋」然後換站,不換 IP、不自動解 CAPTCHA、不偽裝 User-Agent。真的要過,交給人在遠端畫面自己處理。
- 不繞付費牆、不碰付款流程:付費內容用自己已經買的額度;購物工具只查不買,下單一律是人自己做。
- 帳號由本人登入:AI 不經手密碼,CAPTCHA、2FA、滑塊驗證都交給人。