###### tags: `爬蟲與自動化`
# Selenium
[中文文檔](https://selenium-python-zh.readthedocs.io/en/latest/installation.html)
[官方文檔](https://www.selenium.dev/selenium/docs/api/py/api.html)
#### 安裝 Selenium 自動化套件
```
pip install Selenium
```
#### 安裝瀏覽器控制器
1.先確認自己的google chrome版本
在 Chrome 上輸入 `chrome://settings/help`
![](https://i.imgur.com/rpzBAv3.png)
2.到官網下載控制器
[官方網址](https://googlechromelabs.github.io/chrome-for-testing/)
3. 選擇穩定版
![image](https://hackmd.io/_uploads/ByarUSQeyx.png)
4.複製自己的版本的下載網址
![image](https://hackmd.io/_uploads/ryjOIBQxJg.png)
5.在瀏覽器貼上網址後就會自動下載了
6.解壓縮檔案到跟py檔同目錄的地方
![](https://i.imgur.com/nsGDGZL.png)
![](https://i.imgur.com/MzD2EX1.png)
#### 匯入套件的函式
```
from selenium import webdriver # 匯入webdriver套件控制瀏覽器
from selenium.webdriver.chrome.options import Options # 匯入chrome選項的套件 用於控制chrome畫面大小、禁用談窗等等
from selenium.webdriver.common.by import By #定位元素
from selenium.webdriver.common.keys import Keys #輸入
```
#### ChromeOptions
```
chrome_opt = Options() # 設定chrome options 參數
```
```
chrome_opt.add_argument("start-maximized") # 開啟視窗最大化
```
```
chrome_opt.add_argument("--incognito") # 設置隱身模式,可以避免個人化廣告,加速網頁瀏覽
```
```
chrome_opt.add_argument("--headless") # 無頭模式
```
```
chrome_opt.add_argument("disable-extensions") # 禁用 Chrome 瀏覽器上的現有擴展
```
```
chrome_opt.add_argument("disable-popup-blocking") # 禁用 Chrome 瀏覽器上顯示的彈出窗口
```
```
chrome_opt.add_argument("make-default-browser") # 使 Chrome 成為默認瀏覽器
```
```
chrome_opt.add_argument("--version") # 輸出chrome瀏覽器版本
```
```
chrome_opt.add_experimental_option('useAutomationExtension', False)
chrome_opt.add_experimental_option("excludeSwitches", ['enable-automation'])
# 阻止Chrome顯示“Chrome正在由自動化軟件控制”的通知
chrome_opt.add_argument("disable-infobars") # 適用於老版本的 Chrome
```
```
driver = webdriver.Chrome(options = chrome_opt) # 將options放入參數框裡
```
#### 開啟\關閉瀏覽器
```
driver = webdriver.Chrome()
```
```
driver.quit() # 退出驅動程序並關閉每個關聯的窗口
```
```
driver.close()
```
#### 開啟頁面
```
driver.get('https://www.google.com.tw/')
```
#### 重新刷新頁面
```
driver.refresh( )
```
#### 視窗最大化\最小化\指定視窗大小
```
driver.maxmize_window()
driver.fullscreen_window( )
```
```
driver.minmize_window()
```
```
driver.set_window_size(480, 800)
```
#### 獲取當前網頁原始碼
```
html = driver.page_source
```
#### 獲取當前頁面URL
```
driver.current_url
---
```
#### find_element 定位元素
1. CLASS_NAME= 'class name'
1. CSS_SELECTOR= 'css selector'
1. ID= 'id'
1. LINK_TEXT= 'link text'
1. NAME= 'name'
1. PARTIAL_LINK_TEXT= 'partial link text'
1. TAG_NAME= 'tag name'
1. XPATH= 'xpath'
```
elem = driver.find_element(By.ID,'CustID')
elem = driver.find_element(By.XPATH,'CustXPATH')
```
註: ~~find_element_by_id~~ / ~~find_elements_by_name~~ 已被棄用
---
#### 網頁元素
單擊元素
```
elem.click()
```
模擬輸入元素
```
elem.send_keys()
```
清除文本
```
elem.clear()
```
元素的大小
```
elem.size
```
元素的文本
```
elem.text
```
元素的網址
```
elem.get_attribute('href')
```
將當前元素的屏幕截圖保存到 PNG 圖像文件
```
element.screenshot('/Screenshots/foo.png')
```
以 base64 編碼字符串形式獲取當前元素的屏幕截圖
```
img_b64 = element.screenshot_as_base64
```
獲取當前元素的屏幕截圖作為二進制數據
```
element_png = element.screenshot_as_png
```
解除元素被隱藏
```
hidden_element = driver.find_element(By.XPATH,'/html/body/div[4]/div[5]/div/form/div[2]/div[5]/div[1]')
driver.execute_script("arguments[0].style.display = '';", hidden_element)
```
元素不可點擊時
```
element = driver.find_element(By.ID,'pref1')
driver.execute_script("arguments[0].click();", element)
```
---
#### 獲取頁面標題
```
driver.title
```
#### 獲取cookie
```
driver.get_cookie('my_cookie')
```
#### 獲取一組cookie字典
```
driver.get_cookies()
```
#### 添加cookie
```
driver.add_cookie({'name' : 'foo', 'value' : 'bar'})
```
#### 刪除所有cookie
```
driver.delete_all_cookies(name)
```
#### 在瀏覽器歷史返回
```
driver.back()
```
#### 在瀏覽器歷史向前
```
driver.forward()
```
#### 同步執行javascript
```
driver.execute_script('document.title')
```
#### 異步執行javascript
```
driver.execute_async_script('document.title')
```
#### 以 base64 編碼字符串形式獲取當前窗口的屏幕截圖
```
driver.get_screenshot_as_base64()
```
#### 將當前窗口的屏幕截圖保存為 PNG 圖像文件
```
driver.get_screenshot_as_file('/Screenshots/foo.png')
```
#### 以二進制數據形式獲取當前窗口的屏幕截圖
```
get_screenshot_as_png( )
```
#### 將當前窗口的屏幕截圖保存為 PNG 圖像文件
```
driver.save_screenshot('/Screenshots/foo.png')
```
#### 獲取當前窗口的 x,y 位置
```
driver.get_window_position()
driver.set_window_position(0,0) # 設置當前窗口的 x,y 位置
```
#### 獲取窗口的 x、y 坐標以及當前窗口的高度和寬度
```
driver.get_window_rect()
driver.set_window_rect(x=10, y=10, width=100, height=200) # 設置窗口的 x、y 坐標以及當前窗口的高度和寬度
```
#### 獲取當前窗口的寬度和高度
```
driver.get_window_size()
driver.set_window_size(800,600) # 設置當前窗口的寬度和高度
```
#### 設置粘性超時以隱式等待找到一個元素(s)
```
driver.implicitly_wait(30)
```
#### 設置等待頁面加載完成的時間
```
driver.set_page_load_timeout(30)
```
#### 設置腳本在運行期間應等待的時間量
```
driver.set_script_timeout(30)
```
####
---
#### switch_to 家族
對子視窗操作
iframe\frame
```
driver.switch_to.frame(frame的定位)
```
```
driver.switch_to.default_content() #切換到預設 frame
```
```
driver.switch_to.parent_frame() #切換到父級 frame
```
#### 下載音檔或影片
建立一個虛擬的 javascript 按鍵, 下載 url 的媒體內容
```
開啟新分頁-音檔或影片的 url
driver.execute_script("window.open('https://www.railway.gov.tw/tra-tip-web/tip/player/audio?')")
driver.switch_to.window(driver.window_handles[1])
# 建立虛擬按鈕
driver.execute_script('''
// Javascript Code to create the anchor tag and download the file
let aLink = document.createElement("a");
let videoSrc = document.querySelector("video").firstChild.src;
aLink.href = videoSrc;
aLink.download = "";
aLink.click();
aLink.remove();
''')
```
#### 彈出對話方塊alert切換
```
alert = driver.switch_to.alert # 切換到當前頁面上的警告框
alert.text # 返回彈框文字資訊
alert.accept() # 接受彈框,確認
alert.dismiss() # 取消彈框
alert.send_keys(keysToSend) # 傳送文字至彈框
```
#### 多視窗切換與分頁切換
```
windows = driver.current_window_handle # 獲取當前的視窗控制
windows = driver.window_handles # 獲取當前會話下的所有視窗控制
windows = driver.switch_to.window(windows[1]) # 切換視窗
windows = driver.switch_to.window([windows[0]]) # 切回原視窗
driver.switch_to.window(driver.window_handles[-1])# 切換分頁
```
#### 獲取當前焦點元素(光標是否在元素上)
```
elem = switch_to.active_element
elem.send_keys('name')
```
#### 反爬方法
* 通過設置 user-agent 來模擬真實瀏覽器
* 設置 WebDriver 的其他頭信息
* 使用設置 headless 選項,這樣瀏覽器就不會顯示在螢幕上
* 通過代理伺服器進行瀏覽
1.通過設置 user-agent 來模擬真實瀏覽器
```python=
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
capabilities = DesiredCapabilities().CHROME
capabilities["pageLoadStrategy"] = "normal"
user_agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36"
capabilities["userAgent"] = user_agent
```
```python
driver = webdriver.Chrome(desired_capabilities=capabilities)
```
可以獲取自己電腦上當前瀏覽器的user-agent來模擬, 也可以去網路上尋找一些常用瀏覽器的user-agent
2.設置 WebDriver 的其他headers信息
```python=
from selenium.webdriver.chrome.options import Options
options = Options()
```
```python=
options.add_argument("--disable-extensions")
options.add_argument("--disable-gpu")
options.add_argument("--no-sandbox")
options.add_argument("start-maximized")
options.add_argument("disable-infobars")
options.add_argument("--disable-dev-shm-usage")
options.add_argument("--remote-debugging-port=9222")
#設置 headers 信息
options.add_argument("--headers='Content-Type: text/html; charset=UTF-8'")
options.add_argument("--headers='Content-Encoding: gzip'")
```
```python
driver = webdriver.Chrome(chrome_options=options)
```
3.使用設置 headless 選項
```python
options.add_argument("--headless")
```
> 注意,在 headless mode 下, 某些瀏覽器特性可能無法使用, 如需要模擬用戶的互動(例如點擊、滾動等),需要對 headless mode 設置進行特殊處理
其中一種常見的限制是無法模擬用戶的互動(例如點擊、滾動等)。在這種情況下,您可以使用 Selenium 的 ActionChains 類別來模擬這些互動。
```python=
from selenium.webdriver.common.action_chains import ActionChains
actions = ActionChains(driver)
actions.move_to_element(element).perform()
```
另外,在 headless mode 下有些頁面或元素可能會有顯示上的問題,需要特別設置才能正確顯示,例如: 使用額外的瀏覽器設置,或是透過 DevTools 來測試。
如果無法獲得期望的結果,或是有顯示上的問題,可能需要使用非 headless 模式來解決問題.
4.通過代理伺服器進行瀏覽
```python=
from selenium.webdriver.chrome.options import Options
options = Options()
```
接著使用這個
```
options.add_argument("--proxy-server=http://proxy.example.com:8080")
```
或是
```
options.add_argument("--proxy-server=socks5://127.0.0.1:8080")
```
設置代理伺服器後, 您可以瀏覽網頁,透過代理伺服器瀏覽網站, 避免被網站阻擋, 不過要注意使用代理伺服器可能會降低速度或影響到瀏覽網站的結果。
另外請確認代理伺服器是否可用, 並且是否有使用權限
---
#### 特殊鍵
```
from selenium.webdriver.common.keys import Keys
elem.send_keys(Keys.ENTER)
```
ADD= u'\ue025'
ALT= u'\ue00a'
ARROW_DOWN= u'\ue015'
ARROW_LEFT= u'\ue012'
ARROW_RIGHT= u'\ue014'
ARROW_UP= u'\ue013'
BACKSPACE= u'\ue003'
BACK_SPACE= u'\ue003'
CANCEL= u'\ue001'
CLEAR= u'\ue005'
COMMAND= u'\ue03d'
CONTROL= u'\ue009'
DECIMAL= u'\ue028'
DELETE= u'\ue017'
DIVIDE= u'\ue029'
DOWN= u'\ue015'
END= u'\ue010'
ENTER= u'\ue007'
EQUALS= u'\ue019'
ESCAPE= u'\ue00c'
F1= u'\ue031'
F10= u'\ue03a'
F11= u'\ue03b'
F12= u'\ue03c'
F2= u'\ue032'
F3= u'\ue033'
F4= u'\ue034'
F5= u'\ue035'
F6= u'\ue036'
F7= u'\ue037'
F8= u'\ue038'
F9= u'\ue039'
HELP= u'\ue002'
HOME= u'\ue011'
INSERT= u'\ue016'
LEFT= u'\ue012'
LEFT_ALT= u'\ue00a'
LEFT_CONTROL= u'\ue009'
LEFT_SHIFT= u'\ue008'
META= u'\ue03d'
MULTIPLY= u'\ue024'
NULL= u'\ue000'
NUMPAD0= u'\ue01a'
NUMPAD1= u'\ue01b'
NUMPAD2= u'\ue01c'
NUMPAD3= u'\ue01d'
NUMPAD4= u'\ue01e'
NUMPAD5= u'\ue01f'
NUMPAD6= u'\ue020'
NUMPAD7= u'\ue021'
NUMPAD8= u'\ue022'
NUMPAD9= u'\ue023'
PAGE_DOWN= u'\ue00f'
PAGE_UP= u'\ue00e'
PAUSE= u'\ue00b'
RETURN= u'\ue006'
RIGHT= u'\ue014'
SEMICOLON= u'\ue018'
SEPARATOR= u'\ue026'
SHIFT= u'\ue008'
SPACE= u'\ue00d'
SUBTRACT= u'\ue027'
TAB= u'\ue004'
UP= u'\ue013'