Browser Automation(瀏覽器自動化)
是指利用程式控制瀏覽器自動執行各種操作,如自動化測試、資料爬取、表單填寫、搶票、批次操作等。現代自動化框架不僅能模擬人類點擊、輸入、滑動等行為,還能處理複雜的
JavaScript 動態網頁、驗證碼、反爬蟲機制。
選擇合適的自動化技術時,需考慮
支援語言、瀏覽器兼容性、反偵測能力、效能
及
生態系統
等因素。下表整理了主流框架的特色與適用場景,協助你快速選型。
Browser Automation 簡史
-
1. 萌芽期(The Millenial Era, 1992–2003)
- 1992:Lynx(文字模式瀏覽器),可用腳本自動化按鍵。
-
1995–1997:Netscape Navigator(Unix)支援
netscape -remote "openURL(http://…)"控制 GUI 瀏覽器。 - 1997:Internet Explorer(Windows)COM automation object(InternetExplorer.Application),VB/VBA/WSH 可操作 DOM、事件。
- 1998:Mercury Astra QuickTest(QTP/HP UFT)、WinRunner/XRunner。
- 1999–2002:HttpUnit(headless/HTML級)、iMacros(錄製/重播)、HtmlUnit(headless Java “browser”)。
- 2001–2003:Watir(Ruby)從 IE COM/OLE 擴展,開始提供通用 API。
-
2. Selenium 崛起(Selenium Dominance Era, 2004–2017)
- 2004:Selenium 問世,開啟現代瀏覽器自動化時代。
- 2009:Selenium 與 WebDriver 合併,標準化 API。
- 2011–2017:PhantomJS(headless WebKit)填補 headless Chrome 出現前的空白。
-
3. 前 Headless 時代(Pre-Headless Era, 2011–2014)
- 2011:Chrome 推出 remote debugging,WebKit upstream 其他瀏覽器也能採用。
- 2012:WebKit Remote Debugging Protocol v1.0,CDP 雛形。
- 2013–2014:Blink 從 WebKit 分支,CDP 在 Chromium 端成形,chrome.debugger/--remote-debugging 可用。
- 2014:Chrome 推出 chrome.automation extension API(無障礙樹,獨立於 CDP)。
-
4. Headless Chrome & CDP 時代(2017–2019)
- 2017/4:Headless Chrome 發表,Puppeteer(Node.js 驅動 Chrome via CDP)問世。
- 2018/1:Puppeteer 1.0 發布。
- 2018/6:WebDriver 成為 W3C 標準,ChromeDriver 實作 WebDriver/BiDi。
- 2019:Google I/O 推廣 Puppeteer 現代化測試。
-
5. 多瀏覽器標準化時代(Multi-Browser Standardization Era,
2019–2024)
- 2019–2020:Puppeteer 核心工程師加入 Microsoft,開發 Playwright(跨瀏覽器自動化)。
- 2020/1:Playwright 0.x 公開。
- 2020/5:Playwright 1.0 發布。
- 2020/9–10:Playwright 開始多語言支援(Python 版 9/30 公布)。
- 2023:ChromeDriver 支援 WebDriver BiDi。
- 2024:Puppeteer 支援 WebDriver BiDi,Selenium 正式納入 Puppeteer。
-
6. 現代多元選擇(Modern Times: A Multitude of Choice,
2025–)
- 2025:多種高品質 driver library 可選:
- pydoll(Python-first Playwright 替代品)
- go-rod(最佳 CDP 實作)、chromedp(CDP debug 工具)
- Puppeteer(原生 Chrome 行為)、Playwright(跨瀏覽器支援)
- Selenium/Selenium Grid(成熟穩定)、Cypress(傳統 WebDriver 自動化)
- Appium(Android/iOS/macOS/Windows 系統層自動化)
Browser Automation 框架比較
| 技術方案 | 支援語言 | 瀏覽器支援 | 核心特色 | 最佳應用場景 |
|---|---|---|---|---|
| Playwright | Python, JS/TS, C#, Java | Chromium, Firefox, WebKit | WebSocket 通信、自動等待、網路攔截 | 現代化測試與爬蟲、CI/CD 整合 |
| Selenium | Python, Java, C#, 多語言 | Chrome, Firefox, Safari, Edge, IE | WebDriver + HTTP、Selenium Grid、生態成熟 | 跨瀏覽器企業級自動化、兼容舊瀏覽器 |
| NoDriver | Python (async) | Chromium | 無 WebDriver、異步 CDP 通信、高效率 | 高效反偵測爬蟲、並行多頁面抓取 |
| Pyppeteer | Python wrapper | Chromium | 輕量、DevTools Protocol、非同步支援 | JS-heavy 網站抓取、低開銷自動化 |
| undetected_chromedriver | Python | Chromium-based | WebDriver 補丁、提升避檢測能力 | 面對 Cloudflare、Akamai 等防禦機制 |
| zendriver | Python | Chromium | nodriver fork、功能一致 | 更積極維護的 undetected/nodriver 替代品 |
🔗 參考連結
- 📚 Selenium vs NoDriver vs undetected_chromedriver 比較 - Max 的分享
- 📚 Selenium vs Playwright 2024 比較 - ZenRows
- 📚 三大框架對比:Playwright vs Puppeteer vs Selenium - FireCrawl
- 📚 Playwright vs Selenium 選擇指南 - BrowserStack
- 📚 undetected-chromedriver vs Selenium Stealth – ZenRows
在 August 20 2025 時,browser-use 團隊發表了文章,說明了他們為何選擇從 Playwright 轉向 CDP。不僅是因為效能考量,還有對於細節控制的需求。browser-use 這次的技術轉變也意味著瀏覽器自動化技術正朝向更貼近底層的方向發展。極有可能會為相關瀏覽器自動化研究帶來新的啟發。
browser-use - Closer to the Metal: Leaving Playwright for CDP
-
瀏覽器自動化歷史演進:
- 1990s:Lynx(文字模式)、IE COM 物件,早期僅能簡單腳本控制。
- 2000s:Watir、QTP、Selenium 等工具出現,開始支援 GUI 操作、跨瀏覽器自動化。
- 2010s:PhantomJS(headless)、Puppeteer(Node.js 驅動 Chrome)、Playwright(多語言、多瀏覽器支援),自動化框架逐漸成熟,抽象層提升易用性。
- 2020s:多元選擇(pydoll、go-rod、chromedp、cdp-use),AI 驅動需求興起,開始追求更貼近底層的控制與效能。
-
browser-use 團隊 2025 年 8 月發表專文,深入分析
Playwright 抽象層的限制,並說明轉向直接使用 CDP(Chrome DevTools
Protocol)的原因。
- 高階框架(如 Playwright、Puppeteer)雖然 API 現代、易用,適合 QA 測試與一般自動化,但在 AI agent、批次爬蟲等高頻場景下,抽象層會造成效能瓶頸、細節控制困難。
- Playwright 架構為多語言 client 透過 Node.js server 轉發指令,導致多層 relay、狀態漂移、死鎖、異常處理不易,尤其在 tab crash、iframe、異步事件等情境。
- browser-use 推出自家 Python CDP 客戶端(cdp-use),直接根據官方 CDP spec 產生型別安全 binding,無抽象層,100% 直通底層,並採事件驅動架構(watchdog 監控),可即時處理下載、crash、DOM 變化等。
- 元素操作採「超級選擇器」(super-selector) 設計,包含 targetId、frameId、backendNodeId、座標等,解決跨 iframe/target 操作困難,提升 agent 穩定性與反應速度。
- 文章強調:自動化技術正朝向「更貼近底層、更細緻控制」發展,適合高階需求者參考。一般 QA/測試仍可用高階框架,進階 AI/爬蟲建議直接用 CDP。
Camouflage & Performance Optimization(偽裝與效能優化)
-
navigator.webdriver 隱藏:
-
原理:自動化瀏覽器會自動帶有
navigator.webdriver = true,網站可用此判斷是否為機器人。將其設為 undefined 可繞過大多數自動化偵測。 - 原因:這是最常見的自動化檢查點,必須優先隱藏。
-
原理:自動化瀏覽器會自動帶有
from playwright.sync_api import sync_playwright
with sync_playwright() as playwright:
browser = playwright.chromium.launch(headless=False)
page = browser.new_page()
# 注入 JS 隱藏 navigator.webdriver
page.add_init_script("Object.defineProperty(navigator, 'webdriver', {get: () => undefined})")
page.goto("https://tixcraft.com/")
input("按 Enter 關閉瀏覽器...")
browser.close()
-
navigator.plugins、navigator.languages 偽裝
- 原理:真實瀏覽器會有多個 plugins(如 PDF、Flash)及多語言,機器人常為空陣列或異常。偽造常見值可混淆檢查。
- 原因:部分網站會檢查 plugins/languages 來判斷是否為正常用戶。
page.add_init_script(`
Object.defineProperty(navigator, 'webdriver', {get: () => undefined});
Object.defineProperty(navigator, 'plugins', {get: () => [1,2,3]});
Object.defineProperty(navigator, 'languages', {get: () => ['zh-TW', 'zh', 'en']});
`)
-
window.chrome 物件偽裝
- 原理:Chrome 會有 window.chrome 物件,機器人常缺少。補上可避免被判斷為自動化。
- 原因:部分網站用此判斷是否為真實 Chrome。
page.add_init_script(`
Object.defineProperty(navigator, 'webdriver', {get: () => undefined});
Object.defineProperty(navigator, 'plugins', {get: () => [1,2,3]});
Object.defineProperty(navigator, 'languages', {get: () => ['zh-TW', 'zh', 'en']});
window.chrome = window.chrome || {};
window.chrome.runtime = {};
`)
-
Permissions API 偽裝
- 原理:自動化瀏覽器的權限查詢行為與真實用戶不同,覆寫 query 方法可避免異常回傳。
- 原因:網站可用權限查詢結果判斷自動化。
page.add_init_script(`
const originalQuery = window.navigator.permissions.query;
window.navigator.permissions.query = (parameters) => (
parameters.name === 'notifications' ?
Promise.resolve({ state: Notification.permission }) :
originalQuery(parameters)
);
`)
-
Canvas/WebGL/Audio 指紋偽裝
- 原理:網站可用畫布、WebGL、音訊 API 產生指紋,機器人常有固定特徵。覆寫相關方法可降低指紋辨識率。
- 原因:進階防爬網站會用這些 API 產生唯一指紋。
-
HTTP headers 偽裝
- 原理:自動化 context 常缺少 sec-ch-ua、accept-language 等 headers,或內容異常。自動推導並補齊可模擬真實瀏覽器請求。
- 原因:網站可用 headers 組合判斷是否為自動化。
context = browser.new_context(
user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
locale="zh-TW",
extra_http_headers={
"accept-language": "zh-TW,zh;q=0.9,en;q=0.8",
"sec-ch-ua": '"Chromium";v="120", "Not:A-Brand";v="99"',
"sec-ch-ua-mobile": "?0",
"sec-ch-ua-platform": '"Windows"',
}
)
-
hardwareConcurrency/deviceMemory 偽裝
- 原理:真實裝置多為 4/8/16 核心、4/8GB 記憶體,機器人常為預設值。偽造常見值可混淆檢查。
- 原因:部分網站會檢查這些屬性判斷是否為虛擬機或自動化。
page.add_init_script(`
Object.defineProperty(navigator, 'hardwareConcurrency', {get: () => 8});
Object.defineProperty(navigator, 'deviceMemory', {get: () => 8});
`)
-
Media Codecs、chrome.csi/loadTimes 偽裝
- 原理:真實 Chrome 支援多種影音格式,且有特殊 API。補上這些屬性可避免被判斷為自動化。
- 原因:進階網站會檢查這些 API 是否存在。
page.add_init_script(`// 偽裝 Media Codecs
const origCanPlayType = HTMLMediaElement.prototype.canPlayType;
HTMLMediaElement.prototype.canPlayType = function(type) {
if(type === 'video/mp4' || type === 'audio/mp3') return 'probably';
return origCanPlayType.call(this, type);
};
// 偽裝 chrome.csi/loadTimes
window.chrome = window.chrome || {};
window.chrome.csi = () => ({ startE: Date.now(), onloadT: Date.now(), pageT: Date.now(), tran: 15 });
window.chrome.loadTimes = () => ({
requestTime: Date.now()/1000,
startLoadTime: Date.now()/1000,
commitLoadTime: Date.now()/1000,
finishDocumentLoadTime: Date.now()/1000,
finishLoadTime: Date.now()/1000,
firstPaintTime: Date.now()/1000,
navigationType: 'Other',
wasFetchedViaSpdy: false,
wasNpnNegotiated: false,
npnNegotiatedProtocol: '',
wasAlternateProtocolAvailable: false,
connectionInfo: 'h2'
});
`)
-
Storage(localStorage/sessionStorage)隨機化
- 原理:自動化 context 常為乾淨狀態,真實用戶多有歷史資料。隨機填充可降低指紋重複。
- 原因:網站可用 storage 內容判斷是否為新開的自動化分頁。
page.add_init_script(`
try {
localStorage.setItem('bot_rand', Math.random().toString(36).substring(2));
sessionStorage.setItem('bot_rand', Math.random().toString(36).substring(2));
} catch(e) {}
`)
-
滑鼠/鍵盤行為偽裝
- 原理:自動化操作常無滑鼠/鍵盤事件,或事件間隔異常。隨機觸發 mousemove、keydown、focus/blur 等事件可模擬人類行為。
- 原因:網站可用行為軌跡判斷是否為機器人。
page.add_init_script(`
function randomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
setTimeout(() => {
// 多次隨機 mousemove
for (let i = 0; i < randomInt(2, 5); i++) {
const mouseEvent = new MouseEvent('mousemove', {
clientX: randomInt(0, window.innerWidth),
clientY: randomInt(0, window.innerHeight),
bubbles: true
});
document.dispatchEvent(mouseEvent);
}
// 多次隨機 keydown
const keys = ['a', 's', 'd', 'f', 'j', 'k', 'l'];
for (let i = 0; i < randomInt(1, 3); i++) {
const key = keys[randomInt(0, keys.length - 1)];
const keyEvent = new KeyboardEvent('keydown', { key: key, bubbles: true });
document.dispatchEvent(keyEvent);
}
}, 500 + Math.random() * 1000);
`)
-
Captcha/滑塊驗證偽裝
- 原理:部分網站會檢查是否有自動化腳本處理驗證。預留偽裝標記可降低被特殊驗證腳本識破。
- 原因:防止網站用 JS 偵測自動化解驗證。
page.add_init_script(`
window.__bot_captcha_placeholder = true;
Object.defineProperty(window, 'isBot', { get: () => false });
Object.defineProperty(window, 'isRobot', { get: () => false });
`)