Docker Selenium 使用紀錄

前言

利用本篇紀錄使用 Docker Selenium 的過程。

什麼是 Docker Selenium

Docker Selenium 是一個提供不同類型 driver 的 Docker image 的開源專案,目前掛在 Selenium 下面,看起來有常態性的維護。

為何需要 Docker Selenium

使用 Selenium 時進行資料蒐集工作時,需要指定 driver ,例如 Chrome 或是 Firefox,但如果跟 OS 上安裝的 browser 版本不同時,Selenium 就無法運作,Docker Selenium 解決了這項工作痛點。

專案提供了兩種常見的使用方式, standaloneHub and Nodestandalone 只跑一個獨立的 driver, 而 Hub and Node 則有多個,方便不同瀏覽器間的自動化測試。

如何使用 Docker Selenium

如專案名稱所寫,要使用 Docker,沒碰過 Docker 的人可以看看這篇瞭解一下。

要單跑一個 driver,可以用專案提供的範例

docker run -d -p 4444:4444 --shm-size="2g" selenium/standalone-chrome:4.19.1-20240402

像 M1 Mac 用 arm 架構,雖然上面也指令也跑得起來,但看不到運行的 log,需要用不同 image,可以參考這邊的範例

docker run --rm -it -p 4444:4444 -p 5900:5900 -p 7900:7900 --shm-size 2g seleniarm/standalone-chromium:latest

跑起來後,可以去 http://localhost:4444/ui/ 確認,應該會有類似後台的畫面就是成功囉。

Python 與 Selenium

一般情況下,在使用 selenium 時的 code 會像下方範例。

from selenium import webdriver
from selenium.webdriver.chrome.options import Options


url = 'https://google.com'

options = Options()
options.add_argument('--headless')
driver = webdriver.Chrome(options=options)
driver.get(url)

而如果是用 Docker Selenium 跑起來的 driver ,則需要稍微修改程式碼,將 Chrome 改為使用 Remote

參數 command_executor 就是指定剛用 Docker 跑起來的 driver。

...

driver = webdriver.Remote(
    command_executor='http://localhost:4444/wd/hub',
    options=options
)

...

實務上碰到的問題

當想在 server 上用 selenium 進行資料蒐集時,使用 docker selenium 的情況下,會需要從一個 container 去連到這個 driver,也就是 container 間的互連(driver 本身也是一個 container)。

此時需要用 Docker network 來完成,舉例如下

  1. 先建立一個 network

    docker network create local-demo
    
  2. 此時,在跑 driver 的 docker 指令中指定 network

    docker run --network=local-demo --name=selenium-chrome-driver --shm-size 2g seleniarm/standalone-chromium:latest
    
  3. 接著假設你的專案是只有一個簡單的檔案 main.py,因為要連到另一個 container 的關係,要將 command_executor 的 url 換成 driver 的 container 名稱,也就是 selenium-chrome-driver

    # ./main.py
    
    from selenium import webdriver
    from selenium.webdriver.chrome.options import Options
    
    
    url = 'https://google.com'
    
    options = Options()
    options.add_argument('--headless')
    driver = webdriver.Remote(
        command_executor='http://selenium-chrome-driver:4444/wd/hub',
        options=options
    )
    
    driver.get(url)
    
    print('success')
    
    driver.quit()
    
  4. 而整個專案是用 docker-compose.yaml 定義的,類似這樣,記得指定networks,讓兩個 container 間可以互通。

    version: "3"
    
    services:
        worker:
            build:
                context: .
                dockerfile: Dockerfile
            container_name: demo-selenium
            command: "python main.py"
            networks:
                - local-demo # <-- add this
    
        networks: # <-- add this
            local-demo:
                external: true
    
  5. 此時把專案跑起來,可以成功使用 driver 完成工作。

    docker-compose up -d --build
    
Tags:
# python
# selenium
# docker
# crawl