Browser Automation(瀏覽器自動化) 是指利用程式控制瀏覽器自動執行各種操作,如自動化測試、資料爬取、表單填寫、搶票、批次操作等。現代自動化框架不僅能模擬人類點擊、輸入、滑動等行為,還能處理複雜的 JavaScript 動態網頁、驗證碼、反爬蟲機制。
選擇合適的自動化技術時,需考慮 支援語言、瀏覽器兼容性、反偵測能力、效能 及 生態系統 等因素。下表整理了主流框架的特色與適用場景,協助你快速選型。
🧩 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
🦾 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 });
`)
-
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 });
`)