Skip to content

Selenium 深入介紹:從 WebDriver session 到 Grid 的瀏覽器自動化

2026年8月22日 1 分鐘
TL;DR Selenium 透過標準化 WebDriver session 操作真實瀏覽器,適合跨瀏覽器流程、既有測試資產與遠端 Grid;它能執行 JavaScript 頁面,卻不保證繞過 CAPTCHA 或其他反自動化機制。
目錄
  1. WebDriver 架構:程式不直接控制瀏覽器
  2. 建立 session:最小可執行 Python 範例
  3. 定位與等待:可靠度就在這一層
  4. 遠端 session 與 Grid:把瀏覽器變成可排程資源
  5. 容器部署:固定瀏覽器環境,不要固定 latest
  6. 用於爬蟲:Selenium 能做什麼,不能承諾什麼
  7. Selenium、Playwright、Scrapy 怎麼選
  8. 整體來說
  9. 參考資料

🌏 English version

Selenium 是瀏覽器自動化工具,不是爬蟲框架,也不是反偵測套件。程式透過 WebDriver 啟動真實瀏覽器、導覽頁面、操作表單並讀取 DOM。這讓它能處理必須執行 JavaScript 或完成互動後才出現的內容;代價是每個工作都要負擔瀏覽器的 CPU、記憶體與 session 管理。

本文按一次瀏覽器工作的生命週期往下走:命令怎麼進入瀏覽器、元素怎麼定位與等待、session 怎麼關閉、工作怎麼交給 Grid,最後才判斷它是否適合你的擷取任務。

WebDriver 架構:程式不直接控制瀏覽器

Selenium client library 把 Python 的 get()find_element()click() 等呼叫轉成 WebDriver 命令。依 Selenium 的元件說明,driver 負責控制實際瀏覽器,命令與回應都經過它;瀏覽器可與程式位於同一台機器,也可以在遠端 Grid Node 上。

Python 程式
    │  WebDriver commands

Selenium client ──► browser driver ──► Chrome / Firefox / Edge
                         ▲                    │
                         └──── response ──────┘

這個邊界很重要。Selenium 的價值不是「幫你下載 HTML」,而是把不同瀏覽器的原生控制介面收斂成同一套 WebDriver API。若頁面不用執行 JavaScript,直接發 HTTP request 通常更簡單;若流程必須點選、輸入、切換視窗或維持登入狀態,瀏覽器才值得進場。

建立 session:最小可執行 Python 範例

先在虛擬環境安裝 Python binding:

python -m venv .venv
source .venv/bin/activate
python -m pip install selenium

以下範例開啟 Selenium 官方測試頁、填入文字、送出表單,等結果出現後印出訊息。它使用 Selenium Manager 處理本機 driver;官方的自動 driver 管理文件說明,binding 在找不到可用 driver 時會呼叫 Selenium Manager。

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait

options = webdriver.ChromeOptions()
options.add_argument("--headless=new")

driver = webdriver.Chrome(options=options)
try:
    driver.get("https://www.selenium.dev/selenium/web/web-form.html")
    driver.find_element(By.NAME, "my-text").send_keys("Selenium")
    driver.find_element(By.CSS_SELECTOR, "button").click()

    message = WebDriverWait(driver, 10).until(
        EC.visibility_of_element_located((By.ID, "message"))
    )
    print(message.text)
finally:
    driver.quit()

webdriver.Chrome() 建立一個 driver session;options 描述想要的瀏覽器能力。quit() 則結束整個 session 與其視窗。把它放在 finally,即使定位或網路失敗也能回收程序。若工作需要登入,可在同一個 session 內沿用 cookie 與頁面狀態;不要把「永久不關的瀏覽器」當成狀態資料庫,應另外保存可重建的工作進度。

定位與等待:可靠度就在這一層

WebDriver 支援 ID、name、class name、CSS selector、XPath、link text 等定位策略。選擇器應優先靠穩定且有語意的屬性,例如固定 ID、表單 name 或團隊約定的 data-* 屬性。一路寫到 div:nth-child(7) 的 selector 只是把網頁排版當 API,前端稍微調整就會失效。

找到元素不代表元素已經能互動。Selenium 的等待策略文件指出,導覽完成只代表對應的 document ready state 已達條件,JavaScript 仍可能在之後改寫頁面。固定 sleep() 不是同步機制:設太短會偶發失敗,設太長則每次都浪費時間。

可預期的做法是 explicit wait:等待「結果文字可見」「按鈕可點」或「資料列數達到條件」,而不是猜頁面需要幾秒。Implicit wait 是整個 session 的全域元素查找等待;官方明確警告不要混用 implicit 與 explicit waits,因為實際逾時可能變得難以預測。上面的範例只使用 explicit wait。

另一個常見問題是 stale element:畫面重新渲染後,先前拿到的 element reference 可能已不再對應目前 DOM。與其長期保存元素物件,不如保存 locator,互動前重新查找。

遠端 session 與 Grid:把瀏覽器變成可排程資源

本機 driver 適合單人開發;要跨機器、跨平台或平行執行,則把相同程式指向 Remote WebDriver。Selenium Grid 的 Router 接收新 session,New Session Queue 暫存請求,Distributor 依 capabilities 配對可用 slot,Node 實際執行瀏覽器,Session Map 則記錄 session ID 位於哪個 Node。

client


Router ──► New Session Queue ──► Distributor ──► Node slot
  │                                      │
  └──────── Session Map ◄────────────────┘

Grid 解決的是瀏覽器容量與路由,不會自動讓你的爬取邏輯具備冪等性。工作佇列仍要記錄 URL、重試次數、輸出狀態與去重鍵;一個 session 失聯時,應能從工作邊界重跑,而不是依賴瀏覽器記憶接續。

小型環境可以先用 standalone 模式。官方 Grid 入門將本機預設入口放在 http://localhost:4444,並提醒 Grid 必須以防火牆保護,不能直接暴露在公開網路。正式環境還要限制可連線來源、隔離內網存取,並避免把憑證烘進映像檔。

容器部署:固定瀏覽器環境,不要固定 latest

SeleniumHQ 維護的 docker-selenium 提供 standalone、Hub 與 browser Node 映像。最小啟動方式如下;實際部署請從 release 清單挑明確版本標籤,不要把 latest 當成可重現設定。

docker run --rm -p 4444:4444 \
  --shm-size="2g" \
  selenium/standalone-chrome:<tag>

程式端只要換成 remote driver:

from selenium import webdriver

options = webdriver.ChromeOptions()
driver = webdriver.Remote(
    command_executor="http://localhost:4444",
    options=options,
)
try:
    driver.get("https://example.com")
    print(driver.title)
finally:
    driver.quit()

容器能固定瀏覽器與系統相依套件,卻不會替你決定容量。每個瀏覽器都是真實程序;應以自己的頁面、併發量與記憶體尖峰做壓力測試,再設定 Node slot 與工作佇列的上限。

用於爬蟲:Selenium 能做什麼,不能承諾什麼

Selenium 適合「資料藏在瀏覽器工作流程裡」的任務:登入後查詢、點擊載入更多、經過前端計算才生成的內容,或必須驗證真實使用者路徑的工作。擷取時仍應把輸出轉成明確 schema,保存來源 URL 與觀察時間,並讓寫入可重試。

它不適合把大量靜態頁面逐頁塞進瀏覽器。那會用最昂貴的執行方式完成 HTTP client 本來就能做的事。也不要把 headless browser 誤認成「自然就是人類流量」。Selenium 是自動化介面,不保證繞過反爬蟲;網站仍可依流量模式、帳號行為、網路來源、瀏覽器特徵或挑戰頁拒絕請求。

尤其不要設計成自動解 CAPTCHA。Selenium 的測試實務直接把 CAPTCHA 列為不建議自動化的項目,因為它的目的就是阻止自動化。遇到阻擋時,正確動作是降低速率、檢查 robots.txt 與服務條款、尋找官方 API 或取得網站授權;不是把偽裝能力當成 Selenium 的功能。

Selenium、Playwright、Scrapy 怎麼選

工具核心抽象優先選它的情況主要取捨
Selenium標準化 WebDriver session既有 Selenium 資產、跨語言/跨瀏覽器組合、需要 Grid等待與 session 生命週期要明確管理
Playwrightbrowser、context、page 與 locator新建以互動流程為主的自動化,希望 action 前有內建檢查自己管理它安裝的瀏覽器版本與框架慣例
Scrapyrequest/response、scheduler、pipeline大量 HTTP 抓取、佇列、去重與資料管線是主體不會自動提供完整瀏覽器互動

差異最明顯的是等待模型。Playwright auto-wait會在 click 前檢查元素是否唯一、可見、穩定、可接收事件且啟用;Selenium 則讓你以 explicit wait 描述所需狀態。若團隊已累積 WebDriver page objects、語言 binding 或 Grid 維運經驗,Selenium 的相容性通常比重寫更有價值。若是全新的瀏覽器互動專案,Playwright 較強的 locator 與 auto-wait 預設值得優先評估。

Scrapy 解的是另一層問題。它的官方架構說明包含 scheduler、downloader middleware、spider 與 item pipeline,適合把大量 URL 變成可控的資料流。實務上可以讓 Scrapy 負責廣度與資料管線,只把少數必須執行瀏覽器流程的工作送到 Selenium;不要讓所有請求無條件升級成瀏覽器 session。

整體來說

Selenium 最值得選的理由,是標準 WebDriver、生態系與遠端 Grid,不是「比較像真人」。先用 HTTP 工具處理能直接取得的內容;確定資料必須經過瀏覽器互動,再以 Selenium 建立短而可回收的 session、穩定 locator、explicit wait 與可重試的工作邊界。這樣它是可靠的瀏覽器執行層;把它當反爬繞過器,則從一開始就選錯抽象。

參考資料