爬蟲之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)