爬蟲之Selenium的等待及定位

  • 2019 年 10 月 5 日
  • 筆記

爬蟲之Selenium的等待及定位

0.導語

1.selenium的三種等待方式

1.1 強制等待

1.2 隱性等待

1.3 顯性等待

2. selenium之定位以及切換frame

2.1 切frame操作

2.2 切回主文檔

2.3 嵌套frame的操作

2.4 總結

3.學習文章

0.導語

關於昨天的機器學習文章,希望能夠親自碼一下,將會學到很多東西,如果覺得很好,歡迎轉發,謝謝! 有關翻譯貢獻,可點擊公眾號右下角聯繫我,備註:翻譯,或者昨日文章的閱讀原文,pr到倉庫中來! 關於今天的爬蟲文章,則是一篇之前練習爬蟲碰到的問題解決策略,希望可以幫助大家,下面一起來看吧,歡迎留言與轉發!

1.selenium的三種等待方式

Selenium自動化處理時,這個下拉框定位不到、那個彈出框定位不到…各種定位不到,其實大多數情況下就是兩種問題:1 有frame,2 沒有加等待。瀏覽器的載入速度太慢。程式碼速度太快。這就造成了定位不準確的問題。

1.1 強制等待

# -*- coding: utf-8 -*-  from selenium import webdriver  from time import sleep    driver = webdriver.Chrome()  driver.get('https://light-city.me')    sleep(3)  # 強制等待3秒再執行下一步    print driver.current_url  driver.quit()

這種叫強制等待,不管瀏覽器是否載入完畢,程式都得等待3秒。3秒後,程式繼續執行。

1.2 隱性等待

第二種辦法叫隱形等待,implicitly_wait(xx),隱形等待表示程式碼給瀏覽器等待設定一個最長時間,不管程式碼速度多塊,都要等瀏覽器xx秒,如果瀏覽器這段時間內來了,則兩個同步運行,否則,如果瀏覽器在規定時間內沒到,則程式碼繼續運行,接著拋出異常。

# -*- coding: utf-8 -*-  from selenium import webdriver    driver = webdriver.Chrome()  driver.implicitly_wait(30)  # 隱性等待,最長等30秒  driver.get('https://light-city.me')    print driver.current_url  driver.quit()

隱形等待是設置了一個最長等待時間,如果在規定時間內網頁載入完成,則執行下一步,否則一直等到時間截至,然後執行下一步。弊端:程式會一直等待整個頁面載入完成,也就是一般情況下看到的瀏覽器標籤欄小圈不轉,才執行下一步。如果想等到我要的元素出來直接進入下一步,就需要用顯示等待了。

隱性等待對整個driver的周期都起作用,所以只要設置一次即可,整個跟sleep不一樣,不能多次使用。

1.3 顯性等待

第三種辦法就是顯性等待,WebDriverWait,配合該類的until()和until_not()方法。顯性等待表示程式每隔xx秒看一眼,如果條件成立了,則執行下一步,否則繼續等待,直到超過了設置的最長時間,然後拋出TimeoutException。

# -*- coding: utf-8 -*-  from selenium import webdriver  from selenium.webdriver.support.wait import WebDriverWait  from selenium.webdriver.support import expected_conditions as EC  from selenium.webdriver.common.by import By    driver = webdriver.Chrome()  driver.implicitly_wait(10)  # 隱性等待和顯性等待可以同時用,但要注意:等待的最長時間取兩者之中的大者  driver.get('https://xxxx.com')  locator = (By.LINK_TEXT, 'xxx') # 用By類定位    try:      WebDriverWait(driver, 20, 0.5).until(EC.presence_of_element_located(locator))      print driver.find_element_by_link_text('xxx').get_attribute('href')  finally:      driver.close()

selenium.webdriver.common.by.By支援的定位器分類

CLASS_NAME = 'class name'  CSS_SELECTOR = 'css selector'  ID = 'id'  LINK_TEXT = 'link text'  NAME = 'name'  PARTIAL_LINK_TEXT = 'partial link text'  TAG_NAME = 'tag name'  XPATH = 'xpath'

expected_conditions

selenium.webdriver.support.expected_conditions(模組)

WebDriverWait參數與方法

selenium.webdriver.support.wait.WebDriverWait(類)  __init__      driver: 傳入WebDriver實例,即我們上例中的driver      timeout: 超時時間,等待的最長時間(同時要考慮隱性等待時間)      poll_frequency: 調用until或until_not中的方法的間隔時間,默認是0.5秒      ignored_exceptions: 忽略的異常,如果在調用until或until_not的過程中拋出這個元組中的異常,      則不中斷程式碼,繼續等待,如果拋出的是這個元組外的異常,則中斷程式碼,拋出異常。默認只有NoSuchElementException。  until      method: 在等待期間,每隔一段時間調用這個傳入的方法,直到返回值不是False      message: 如果超時,拋出TimeoutException,將message傳入異常  until_not 與until相反,until是當某元素出現或什麼條件成立則繼續執行,until_not是當某元素消失或什麼條件不成立則繼續執行,參數也相同,不再贅述。

調用方法

WebDriverWait(driver, 超時時長, 調用頻率, 忽略異常).until(可執行方法, 超時時返回的資訊)

這裡需要特別注意的是until或until_not中的可執行方法method參數,很多人傳入了WebElement對象,如下:

WebDriverWait(driver, 10).until(driver.find_element_by_id('kw'))  # 錯誤

在這裡,可以用selenium提供的 expected_conditions 模組中的各種條件,也可以用WebElement的 is_displayed() 、is_enabled()、is_selected() 方法,或者用自己封裝的方法都可以。

2. selenium之定位以及切換frame

frameset不用切,frame需層層切!

frame標籤有frameset、frame、iframe三種,frameset跟其他普通標籤沒有區別,不會影響到正常的定位,而frame與iframe對selenium定位而言是一樣的,selenium有一組方法對frame進行操作。

2.1 切frame操作

switch_to.frame()

from selenium import webdriver  driver = webdriver.Firefox()  driver.switch_to.frame(0)  # 1.用frame的index來定位,第一個是0  # driver.switch_to.frame("frame1")  # 2.用id來定位  # driver.switch_to.frame("myframe")  # 3.用name來定位  # driver.switch_to.frame(driver.find_element_by_tag_name("iframe"))  # 4.用WebElement對象來定位

2.2 切回主文檔

switch_to.default_content() 如果想繼續操作主文檔的元素,則需要切回主文檔。

driver.switch_to.default_content()

2.3 嵌套frame的操作

<html>      <iframe id="frame1">          <iframe id="frame2" / >      </iframe>  </html>

從主文檔切到frame2,一層層切進去

driver.switch_to.frame("frame1")  driver.switch_to.frame("frame2")

從frame2再切回frame1

driver.switch_to.parent_frame()  # 如果當前已是主文檔,則無效果

2.4 總結

driver.switch_to.frame(reference)  driver.switch_to.parent_frame()  driver.switch_to.default_content()

3.學習文章

(1)Python selenium —— 一定要會用selenium的等待,三種等待方式解讀

https://huilansame.github.io/huilansame.github.io/archivers/sleep-implicitlywait-wait

(2)selenium之 定位以及切換frame(iframe)

(https://blog.csdn.net/huilan_same/article/details/52200586)

Tags: