More

    Python 使用 Selenium 函式庫進行網絡爬蟲

    selenium 函式庫 ( 模組 ) 是使用 Python 進行網路爬蟲時,必備的函式庫之一,透過 selenium 可以模擬出使用者在瀏覽器的所有操作行為 ( 點擊按鈕、輸入帳號密碼、捲動捲軸…等 ),因此除了爬蟲的應用,也常作為「自動化測試」使用的工具,在網站開發完成後,透過自動化的腳本測試所有功能是否正常,這篇教學將會介紹 selenium 函式庫的常見用法,更多用法可前往閱讀 selenium 官方文件。

    執行 selenium 會啟動 chromedriver,所以所以請使用本機環境 ( 參考:使用 Python 虛擬環境 ) 或使用 Anaconda Jupyter 進行實作 ( 參考:使用 Anaconda ) 。

    快速導覽:

    安裝 selenium 模組 

    在本機環境輸入下列指令,就能安裝 selenium 函式庫 ( 依據每個人的作業環境不同,可使用 pip 或 pip3 或 pipenv,Anaconda Jupyter 的安裝指令為 !pip )。

    pip install selenium
    

    什麼是 Selenium WebDriver 

    WebDriver 是用來執行並操作瀏覽器的 API 介面,每一個瀏覽器都會有各自對應的驅動程式 ( driver ),Selenium 會透過 WebDriver 來直接對瀏覽器進行操作,將所支援的瀏覽器進行自動化作業,就如同真的使用者在操作

    下載 WebDriver 

    不同的瀏覽器會對應不同的 driver,以下提供幾種常見的 driver ( 本篇範例使用的是 Chrome ):

    下載 Chrome driver 時請,必須下載對應的 Chrome 的版本,點擊右上角選單「說明 > 關於 Google Chrome」,可以查看版本。

    Python 教學 - Selenium 函式庫

    下載後將 driver 與執行的 Python 檔案放在同一個目錄下,就比較不需要煩惱執行時路徑的問題。

    Python 教學 - Selenium 函式庫

    import selenium 

    要使用 requests 必須先 import selenium 模組,啟用 webdriver 的功能。

    from selenium import webdriver
    

    使用 WebDriver 開啟第一個網頁 

    selenium 與 driver 都安裝與準備好之後,下方的程式碼執行後,會打開一個新的 Chrome 視窗,裡面出現指定的 Google 網頁,此時這個新的 Chrome 視窗會標明「受到自動測試軟體控制」,表示程式正在控制相關的操作。

    webdriver.Chrome(路徑) 使用相對路徑 chromedriver 和執行的程式位在同一層。

    from selenium import webdriver
    driver = webdriver.Chrome('./chromedriver')    # 指向 chromedriver 的位置
    driver.get('https://www.google.com')           # 打開瀏覽器,開啟網頁
    
    Python 教學 - Selenium 函式庫

    取得網頁元素 

    要模擬真人操作網頁的第一步,就是要知道觸碰了哪些網頁元素,首先載入 selenium 的 By 模組,接著就能使用 find_element() 搭配參數設定,取得指定的網頁元素,下方列出 find_element() 常用參數設定 ( 如果將方法的 element 改為 elements,會以串列方式回傳找到的元素 ):

    新版本 selenium 取得元素的方法有所變更,本文也一併更新,詳細的方法參考:selenium.webdriver.remote.webelement

    參數說明
    By.ID, id透過 id,尋找第一個相符的網頁元素。
    By.CLASS_NAME, class透過 class,尋找第一個相符的網頁元素。
    By.CSS_SELECTOR, css selector透過 css 選擇器,尋找第一個相符的網頁元素。
    By.NAME, name透過 name 屬性,尋找第一個相符的網頁元素。
    By.TAG_NAME, tag透過 HTML tag,尋找第一個相符的網頁元素。
    By.LINK_TEXT, text透過超連結的文字,尋找第一個相符的網頁元素
    By.PARTIAL_LINK_TEXT, text透過超連結的部分文字,尋找第一個相符的網頁元素。
    By.XPATH, xpath透過 xpath 的方式,尋找第一個相符的網頁元素。

    下方的程式會用 selenium 開啟範例網址 ( 網址連結 ),開啟後會用上述的方法,選取特定的網頁元素,接著套用點擊的方法,依序點擊各個按鈕,最後會連續打開兩次 Google 網站。

    範例網址已經有做過點擊的處理,點擊按鈕或下拉選單切換時,上方空格會顯示對應的文字。

    from selenium import webdriver
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support.select import Select   # 使用 Select 對應下拉選單
    import time
    
    driver = webdriver.Chrome('./chromedriver')
    driver.get('https://example.oxxostudio.tw/python/selenium/demo.html')  # 開啟範例網址
    a = driver.find_element(By.ID, 'a')                # 取得 id 為 a 的網頁元素 ( 按鈕 A )
    b = driver.find_element(By.CLASS_NAME, 'btn')      # 取得 class 為 btn 的網頁元素 ( 按鈕 B )
    c = driver.find_element(By.CSS_SELECTOR, '.test')  # 取得 class 為 test 的網頁元素 ( 按鈕 C )
    d = driver.find_element(By.NAME, 'dog')            # 取得屬性 name 為 dog 的網頁元素 ( 按鈕 D )
    h1 = driver.find_element(By.TAG_NAME, 'h1')        # 取得 tag h1 的網頁元素
    link1 = driver.find_element(By.LINK_TEXT, '我是超連結,點擊會開啟 Google 網站')  # 取得指定超連結文字的網頁元素
    link2 = driver.find_element(By.PARTIAL_LINK_TEXT, 'Google') # 取得超連結文字包含 Google 的網頁元素
    select = Select(driver.find_element(By.XPATH, '/html/body/select'))   # 取得 html > body > select 這個網頁元素
    
    a.click()        # 點擊 a
    print(a.text)    # 印出 a 元素的內容
    time.sleep(0.5)
    b.click()        # 點擊 b
    print(b.text)    # 印出 b 元素的內容
    time.sleep(0.5)
    c.click()        # 點擊 c
    print(c.text)    # 印出 c 元素的內容
    time.sleep(0.5)
    d.click()        # 點擊 d
    print(d.text)    # 印出 d 元素的內容
    time.sleep(0.5)
    select.select_by_index(2)  # 下拉選單選擇第三項 ( 第一項為 0 )
    time.sleep(0.5)
    h1.click()       # 點擊 h1
    time.sleep(0.5)
    link1.click()    # 點擊 link1
    time.sleep(0.5)
    link2.click()    # 點擊 link2
    print(link2.get_attribute('href'))   # 印出 link2 元素的 href 屬性
    
    Python 教學 - Selenium 函式庫
    Python 教學 - Selenium 函式庫

    操作網頁元素 

    使用 Selenium 函式庫操作網頁元素下列幾種方法:

    方法ActionChains 參數說明
    click()element按下滑鼠左鍵。
    click_and_hold()element滑鼠左鍵按著不放。
    double_click()element連續按兩下滑鼠左鍵。
    context_click()element按下滑鼠右鍵 ( 需搭配指定元素定位 )。
    drag_and_drop()source, target點擊 source 元素後,移動到 target 元素放開。
    drag_and_drop_by_offset()source, x, y點擊 source 元素後,移動到指定的座標位置放開。
    move_by_offset()x, y移動滑鼠座標到指定位置。
    move_to_element()element移動滑鼠到某個元素上。
    move_to_element_with_offset()element, x, y移動滑鼠到某個元素的相對座標位置。
    release()element放開滑鼠。
    send_keys()values送出某個鍵盤按鍵值。
    send_keys_to_element()element, values向某個元素發送鍵盤按鍵值。
    key_down()value按著鍵盤某個鍵。
    key_up()value放開鍵盤某個鍵。
    reset_actions()清除儲存的動作 ( 實測沒有作用,查訊後是 Bug )。
    pause()seconds暫停動作。
    perform()執行儲存的動作。

    要使用這些方法的方式有兩種,第一種就是「針對指定元素呼叫方法」,例如上方例子的 click() 方法,只要針對指定的元素,呼叫指定的方法,就會執行對應的動作,第二種是使用「ActionChains」,將所有需要執行的方法串成「鏈」,全部完成後執行 perform() 執行所有的過程

    下方的程式使用「針對指定元素呼叫方法」。

    from selenium import webdriver
    from selenium.webdriver.common.by import By
    from time import sleep
    
    driver = webdriver.Chrome('./chromedriver')
    driver.get('https://example.oxxostudio.tw/python/selenium/demo.html')
    a = driver.find_element(By.ID, 'a')
    add = driver.find_element(By.ID, 'add')
    a.click()     # 點擊按鈕 A,出現 a 文字
    sleep(1)
    add.click()   # 點擊 add 按鈕,出現 數字 1
    add.click()   # 點擊 add 按鈕,出現 數字 2
    sleep(1)
    add.click()   # 點擊 add 按鈕,出現 數字 3
    sleep(1)
    add.click()   # 點擊 add 按鈕,出現 數字 4
    

    下方的程式使用「ActionChains」的方式,結果與上述的執行結果相同。

    from selenium import webdriver
    from selenium.webdriver.common.by import By
    from selenium.webdriver.common.action_chains import ActionChains
    
    driver = webdriver.Chrome('./chromedriver')
    driver.get('https://example.oxxostudio.tw/python/selenium/demo.html')
    a = driver.find_element(By.ID, 'a')
    add = driver.find_element(By.ID, 'add')
    actions = ActionChains(driver)   # 使用 ActionChains 的方式
    actions.click(a).pause(1)        # 點擊按鈕 A,出現 a 文字後,暫停一秒
    actions.double_click(add).pause(1).click(add).pause(1).click(add)
    # 連點 add 按鈕,等待一秒後再次點擊,等待一秒後再次點擊
    actions.perform()  # 執行儲存的動作
    
    Python 教學 - Selenium 函式庫

    雖然「針對指定元素呼叫方法」看起來滿直覺,但相對來說能使用的方法有限 ( 只能使用 click、send_keys…等兩三種 ),使用「ActionChains」才能完整發揮所有的方法,下方的程式碼執行後,會自動在輸入框內輸入指定的文字。

    from selenium import webdriver
    from selenium.webdriver.common.by import By
    from selenium.webdriver.common.action_chains import ActionChains
    
    driver = webdriver.Chrome('./chromedriver')
    driver.get('https://example.oxxostudio.tw/python/selenium/demo.html')
    a = driver.find_element(By.ID, 'a')
    show = driver.find_element(By.ID, 'show')
    actions = ActionChains(driver)
    actions.click(show).send_keys(['1','2','3','4','5'])    # 輸入 1~5 的鍵盤值 ( 必須是字串 )
    actions.pause(1)    # 等待一秒
    actions.click(a)    # 點擊按鈕 A
    actions.pause(1)    # 等待一秒
    actions.send_keys_to_element(show, ['A','B','C','D','E'])   # # 輸入 A~E 的鍵盤值
    actions.perform()   # 送出動作
    
    Python 教學 - Selenium 函式庫

    取得網頁元素的內容 

    Selenium 不僅能模擬真人去控制網頁元素,也可以取得網頁元素的相關內容,甚至進一步執行網頁截圖並儲存的功能,常用的內容如下:

    內容說明
    text元素的內容文字。
    get_attribute元素的某個 HTML 屬性值。
    id元素的 id。
    tag_name元素的 tag 名稱。
    size元素的長寬尺寸。
    screenshot將某個元素截圖並儲存為 png。
    is_displayed()元素是否顯示在網頁上。
    is_enabled()元素是否可用。
    is_selected()元素是否被選取。
    parent元素的父元素。

    下方的程式碼執行後,會取得元素的 id、內容文字、tag 名稱、尺寸和屬性值,最後會將整張網頁截圖為 test.png。

    from selenium import webdriver
    from selenium.webdriver.common.by import By
    
    driver = webdriver.Chrome('./chromedriver')
    driver.get('https://example.oxxostudio.tw/python/selenium/demo.html')
    body = driver.find_element(By.TAG_NAME, 'body')
    a = driver.find_element(By.ID, 'a')
    b = driver.find_element(By.CLASS_NAME, 'btn')
    c = driver.find_element(By.CSS_SELECTOR, '.test')
    d = driver.find_element(By.NAME, 'dog')
    link1 = driver.find_element(By.LINK_TEXT, '我是超連結,點擊會開啟 Google 網站')
    link2 = driver.find_element(By.PARTIAL_LINK_TEXT, 'Google')
    
    print(a.id)
    print(b.text)
    print(c.tag_name)
    print(d.size)
    print(link1.get_attribute('href'))
    print(link2.get_attribute('target'))
    body.screenshot('./test.png')
    
    Python 教學 - Selenium 函式庫

    搭配 JavaScript,發揮最大效益 

    Selenium 除了內建的方法,也可以搭網頁的 JavaScript,發揮網頁控制的最大效益,下方的程式碼執行後,會先上下滾動網頁捲軸,接著彈出提示視窗,兩秒後再關閉提示視窗。

    from selenium import webdriver
    from selenium.webdriver.common.by import By
    from selenium.webdriver.common.alert import Alert
    from time import sleep
    
    driver = webdriver.Chrome('./chromedriver')
    driver.get('https://www.selenium.dev/selenium/docs/api/py/webdriver_remote/selenium.webdriver.remote.webelement.html')
    
    sleep(1)
    driver.execute_script('window.scrollTo(0, 500)')   # 捲動到 500px 位置
    sleep(1)
    driver.execute_script('window.scrollTo(0, 2500)')  # 捲動到 2500px 位置
    sleep(1)
    driver.execute_script('window.scrollTo(0, 0)')     # 捲動到 0px 位置
    
    h1 = driver.find_element(By.TAG_NAME, 'h1')
    h3 = driver.find_element(By.TAG_NAME, 'h3')
    script = '''
      let h1 = arguments[0];
      let h3 = arguments[1];
      alert(h1, h3)
    '''
    driver.execute_script(script, h1, h3)   # 執行 JavaScript,印出元素
    sleep(2)
    Alert(driver).accept()    # 點擊提示視窗的確認按鈕,關閉提示視窗
    

    參考資料 

    Selenium 函式庫不僅能應用於自動化測試,對於爬蟲的應用而言也是必備的函式庫,下方列出 Selenium 的官方文件,如果要了解更詳細的資訊可以前往閱讀:

    Source : https://steam.oxxostudio.tw/category/python/spider/selenium.html

    Recent Articles

    spot_img

    Related Stories

    Stay on op - Ge the daily news in your inbox