Selenium 4 的使用
Tags: selenium, python
Published: 2023-01-28 08:28:57

[Selenium 4](https://www.selenium.dev/documentation/webdriver/getting_started/upgrade_to_selenium_4/) 和 [Selenium 3](https://www.selenium.dev/documentation/legacy/selenium_3/) 主要有兩大差異, 以下分別說明。

## WebDriver

從 Selenium 4.6 開始, 已經內建 [Selenium manager](https://www.selenium.dev/documentation/webdriver/getting_started/install_drivers/#1-selenium-manager-beta), 它會在 PATH 指定的路徑下找不到 WebDriver 的執行檔時自動配置 WebDriver, 完全不需要自己下載檔案以及設定 PATH, 以下以 Firefox 為例：

```python
>>> from selenium import webdriver
>>> driver = webdriver.Firefox()
```

即可自動配置 WebDriver 並開啟安裝的 Firefox 瀏覽器。

使用 Selenium manager 是最簡單方便的作法, 但如果你被迫使用較舊的版本, 必須自行下載安裝 WebDriver, 也要注意在建立 webdriver 物件時, 如果你的 WebDriver 執行檔並不在 [PATH 指定的路徑](https://www.selenium.dev/documentation/webdriver/getting_started/install_drivers/#3-the-path-environment-variable)下, 過去用來指定路徑的 `executable_path` 參數已經被棄用, 要改用 [Service 物件](https://www.selenium.dev/documentation/webdriver/getting_started/install_drivers/#4-hard-coded-location)。

不過自己要管理 WebDriver 執行檔其實有點麻煩, 不但要設定路徑, 還要跟著瀏覽器版本更新檔案, 比較簡單的方式是使用 [`webdriver-manager`](https://www.selenium.dev/documentation/webdriver/getting_started/install_drivers/#2-driver-management-software)

```
pip install webdriver-manager
```

安裝後即可如下建立 webdriver 物件, 此處以 Windows 內建的 Edge 瀏覽器為例：

```python
>>> from selenium import webdriver
>>> from webdriver_manager.microsoft import EdgeChromiumDriverManager
>>> from selenium.webdriver.edge.service import Service
>>> driver = webdriver.Edge(
...     service=Service(EdgeChromiumDriverManager().install()))
```

這個 webdriver-manager 套件也可以用在 [Selenium 3](https://github.com/SergeyPirogov/webdriver_manager#use-with-firefox) 上, 以 Firefox 為例：

```python
>>> from selenium import webdriver
>>> from webdriver_manager.firefox import GeckoDriverManager
>>> driver = webdriver.Firefox(executable_path=GeckoD
... riverManager().install())
```

如果你的瀏覽器並不是安裝在預設的路徑上, 就必須自行在建立 webdriver 物件時以對應瀏覽器的 [Option 物件](https://www.selenium.dev/documentation/webdriver/drivers/options/)指定瀏覽器執行檔的路徑。例如我有一個可攜式的 Chrome 位於 d:\\apps\\PortableApps\\GoogleChromePortable\\App\\Chrome-bin\\chrome.exe, 就可以透過以下方式建立 webdriver 物件：

```python
>>> from selenium.webdriver.chrome.options import Options
>>> o = Options()
>>> o.binary_location = "d:\\apps\\PortableApps\\GoogleChromePortable\\App\\Chrome-bin\\chrome.exe"
>>> driver = webdriver.Chrome(options=o)
```

## 取得元素

Selenium 4 不提供 `find_element_by_XXX` 的方法, 只提供取得第一個元素 [`find_element`](https://www.selenium.dev/documentation/webdriver/elements/finders/#first-matching-element) 或是所有元素的 [`find_elements`](https://www.selenium.dev/documentation/webdriver/elements/finders/#all-matching-elements) 方法, 可以搭配 [`By`](https://www.selenium.dev/documentation/webdriver/elements/locators/) 類別指定找尋元素的依據。

此處以 https://www.w3schools.com/html/html_tables.asp 為例：

![](https://i.imgur.com/84f39QJ.png)

```python
>>> driver.get("https://www.w3schools.com/html/html_tables.asp")
```

其中的表格 id 為 "customers", 若要取得格中的第一個儲存格, 可以這樣做：

```python
>>> from selenium.webdriver.common.by import By
>>> td = driver.find_element(By.CSS_SELECTOR, "#customers td")
>>> td.text
'Alfreds Futterkiste'
```

或是也可以分段先取得表格元素, 再取出表格中的所有儲存格, 然後再取出其中的第一個儲存格：

```python
>>> tab = driver.find_element(By.ID, "customers")
>>> tds = tab.find_elements(By.TAG_NAME, "td")
>>> len(tds)
18

>>> tds[0].text
'Alfreds Futterkiste'
```