成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

爬蟲 + 自動化利器 selenium 之自學(xué)成才篇(二)

AWang / 2754人閱讀

摘要:耗時代碼運行到這句之后觸發(fā)隱式等待,在輪詢檢查后仍然沒有定位到元素,拋出異常。耗時值得一提的是,對于定位不到元素的時候,從耗時方面隱式等待和強制等待沒什么區(qū)別。

? 系列內(nèi)容 ?
爬蟲+自動化利器 selenium 之自學(xué)成才篇(一)
主要內(nèi)容:selenium 簡介、selenium 安裝、安裝瀏覽器驅(qū)動、8 種方式定位頁面元素、瀏覽器控制、鼠標(biāo)控制、鍵盤控制

爬蟲+自動化利器 selenium 之自學(xué)成才篇(二)
主要內(nèi)容:三種等待方式(顯式等待、隱式等待、強制等待)、一組元素的定位方式、切換操作(窗口切換、表單切換)、彈窗處理等。

爬蟲+自動化利器 selenium 之自學(xué)成才篇(三)
主要內(nèi)容:文件上傳 & 下載、cookie 操作、調(diào)用 JavaScript(滑動滾動條)、關(guān)閉操作、頁面截圖等。



設(shè)置元素等待

很多頁面都使用 ajax 技術(shù),頁面的元素不是同時被加載出來的,為了防止定位這些尚在加載的元素報錯,可以設(shè)置元素等來增加腳本的穩(wěn)定性。webdriver 中的等待分為 顯式等待 和 隱式等待。

顯式等待

顯式等待:設(shè)置一個超時時間,每個一段時間就去檢測一次該元素是否存在,如果存在則執(zhí)行后續(xù)內(nèi)容,如果超過最大時間(超時時間)則拋出超時異常(TimeoutException)。顯示等待需要使用 WebDriverWait,同時配合 untilnot until 。下面詳細(xì)講解一下。

WebDriverWait(driver, timeout, poll_frequency=0.5, ignored_exceptions=None)

  • driver:瀏覽器驅(qū)動
  • timeout:超時時間,單位秒
  • poll_frequency:每次檢測的間隔時間,默認(rèn)為0.5秒
  • ignored_exceptions:指定忽略的異常,如果在調(diào)用 untiluntil_not 的過程中拋出指定忽略的異常,則不中斷代碼,默認(rèn)忽略的只有 NoSuchElementException 。

until(method, message=’ ‘)
until_not(method, message=’ ")

  • method:指定預(yù)期條件的判斷方法,在等待期間,每隔一段時間調(diào)用該方法,判斷元素是否存在,直到元素出現(xiàn)。until_not 正好相反,當(dāng)元素消失或指定條件不成立,則繼續(xù)執(zhí)行后續(xù)代碼
  • message: 如果超時,拋出 TimeoutException ,并顯示 message 中的內(nèi)容

method 中的預(yù)期條件判斷方法是由 expected_conditions 提供,下面列舉常用方法。

先定義一個定位器

from selenium.webdriver.common.by import Byfrom selenium import webdriverdriver = webdriver.Chrome()locator = (By.ID, "kw")element = driver.find_element_by_id("kw")
方法描述
title_is(‘百度一下’)判斷當(dāng)前頁面的 title 是否等于預(yù)期
title_contains(‘百度’)判斷當(dāng)前頁面的 title 是否包含預(yù)期字符串
presence_of_element_located(locator)判斷元素是否被加到了 dom 樹里,并不代表該元素一定可見
visibility_of_element_located(locator)判斷元素是否可見,可見代表元素非隱藏,并且元素的寬和高都不等于0
visibility_of(element)跟上一個方法作用相同,但傳入?yún)?shù)為 element
text_to_be_present_in_element(locator , ‘百度’)判斷元素中的 text 是否包含了預(yù)期的字符串
text_to_be_present_in_element_value(locator , ‘某值’)判斷元素中的 value 屬性是否包含了預(yù)期的字符串
frame_to_be_available_and_switch_to_it(locator)判斷該 frame 是否可以 switch 進(jìn)去,True 則 switch 進(jìn)去,反之 False
invisibility_of_element_located(locator)判斷元素中是否不存在于 dom 樹或不可見
element_to_be_clickable(locator)判斷元素中是否可見并且是可點擊的
staleness_of(element)等待元素從 dom 樹中移除
element_to_be_selected(element)判斷元素是否被選中,一般用在下拉列表
element_selection_state_to_be(element, True)判斷元素的選中狀態(tài)是否符合預(yù)期,參數(shù) element,第二個參數(shù)為 True/False
element_located_selection_state_to_be(locator, True)跟上一個方法作用相同,但傳入?yún)?shù)為 locator
alert_is_present()判斷頁面上是否存在 alert

下面寫一個簡單的例子,這里定位一個頁面不存在的元素,拋出的異常信息正是我們指定的內(nèi)容。

from selenium import webdriverfrom selenium.webdriver.support.ui import WebDriverWaitfrom selenium.webdriver.support import expected_conditions as ECfrom selenium.webdriver.common.by import Bydriver = webdriver.Chrome()element = WebDriverWait(driver, 5, 0.5).until(            EC.presence_of_element_located((By.ID, "kw")),                                           message="超時啦!")

隱式等待

隱式等待也是指定一個超時時間,如果超出這個時間指定元素還沒有被加載出來,就會拋出 NoSuchElementException 異常。
除了拋出的異常不同外,還有一點,隱式等待是全局性的,即運行過程中,如果元素可以定位到,它不會影響代碼運行,但如果定位不到,則它會以輪詢的方式不斷地訪問元素直到元素被找到,若超過指定時間,則拋出異常。

使用 implicitly_wait() 來實現(xiàn)隱式等待,使用難度相對于顯式等待要簡單很多。
示例:打開個人主頁,設(shè)置一個隱式等待時間 5s,通過 id 定位一個不存在的元素,最后打印 拋出的異常 與 運行時間。

from selenium import webdriverfrom time import timedriver = webdriver.Chrome()driver.get("https://blog.csdn.net/qq_43965708")start = time()driver.implicitly_wait(5)try:    driver.find_element_by_id("kw")except Exception as e:    print(e)    print(f"耗時:{time()-start}")


代碼運行到 driver.find_element_by_id("kw") 這句之后觸發(fā)隱式等待,在輪詢檢查 5s 后仍然沒有定位到元素,拋出異常。

強制等待

使用 time.sleep() 強制等待,設(shè)置固定的休眠時間,對于代碼的運行效率會有影響。以上面的例子作為參照,將 隱式等待 改為 強制等待。

from selenium import webdriverfrom time import time, sleepdriver = webdriver.Chrome()driver.get("https://blog.csdn.net/qq_43965708")start = time()sleep(5)try:    driver.find_element_by_id("kw")except Exception as e:    print(e)    print(f"耗時:{time()-start}")


值得一提的是,對于定位不到元素的時候,從耗時方面隱式等待和強制等待沒什么區(qū)別。但如果元素經(jīng)過 2s 后被加載出來,這時隱式等待就會繼續(xù)執(zhí)行下面的代碼,但 sleep還要繼續(xù)等待 3s。


定位一組元素

上篇講述了定位一個元素的 8 種方法,定位一組元素使用的方法只需要將 element 改為 elements 即可,它的使用場景一般是為了批量操作元素。

  • find_elements_by_id()
  • find_elements_by_name()
  • find_elements_by_class_name()
  • find_elements_by_tag_name()
  • find_elements_by_xpath()
  • find_elements_by_css_selector()
  • find_elements_by_link_text()
  • find_elements_by_partial_link_text()

這里以 CSDN 首頁的一個 博客專家欄 為例。

下面使用 find_elements_by_xpath 來定位三位專家的名稱。

這是專家名稱部分的頁面代碼,不知各位有沒有想到如何通過 xpath 定位這一組專家的名稱呢?

from selenium import webdriver# 設(shè)置無頭瀏覽器option = webdriver.ChromeOptions()option.add_argument("--headless")driver = webdriver.Chrome(options=option)driver.get("https://blog.csdn.net/")p_list = driver.find_elements_by_xpath("http://p[@class="name"]")name = [p.text for p in p_list]name


切換操作

窗口切換

selenium 操作頁面的時候,可能會因為點擊某個鏈接而跳轉(zhuǎn)到一個新的頁面(打開了一個新標(biāo)簽頁),這時候 selenium 實際還是處于上一個頁面的,需要我們進(jìn)行切換才能夠定位最新頁面上的元素。

窗口切換需要使用 switch_to.windows() 方法。

首先我們先看看下面的代碼。

代碼流程:先進(jìn)入 【CSDN首頁】,保存當(dāng)前頁面的句柄,然后再點擊左側(cè) 【CSDN官方博客】跳轉(zhuǎn)進(jìn)入新的標(biāo)簽頁,再次保存頁面的句柄,我們驗證一下 selenium 會不會自動定位到新打開的窗口。

from selenium import webdriverhandles = []driver = webdriver.Chrome()driver.get("https://blog.csdn.net/")# 設(shè)置隱式等待driver.implicitly_wait(3)# 獲取當(dāng)前窗口的句柄handles.append(driver.current_window_handle)# 點擊 python,進(jìn)入分類頁面driver.find_element_by_xpath("http://*[@id="mainContent"]/aside/div[1]/div").click()# 獲取當(dāng)前窗口的句柄handles.append(driver.current_window_handle)print(handles)# 獲取當(dāng)前所有窗口的句柄print(driver.window_handles)


可以看到第一個列表 handle 是相同的,說明 selenium 實際操作的還是 CSDN首頁 ,并未切換到新頁面。
下面使用 switch_to.windows() 進(jìn)行切換。

from selenium import webdriverhandles = []driver = webdriver.Chrome()driver.get("https://blog.csdn.net/")# 設(shè)置隱式等待driver.implicitly_wait(3)# 獲取當(dāng)前窗口的句柄handles.append(driver.current_window_handle)# 點擊 python,進(jìn)入分類頁面driver.find_element_by_xpath("http://*[@id="mainContent"]/aside/div[1]/div").click()# 切換窗口driver.switch_to.window(driver.window_handles[-1])# 獲取當(dāng)前窗口的句柄handles.append(driver.current_window_handle)print(handles)print(driver.window_handles)


上面代碼在點擊跳轉(zhuǎn)后,使用 switch_to 切換窗口,window_handles 返回的 handle 列表是按照頁面出現(xiàn)時間進(jìn)行排序的,最新打開的頁面肯定是最后一個,這樣用 driver.window_handles[-1] + switch_to 即可跳轉(zhuǎn)到最新打開的頁面了。

那如果打開的窗口有多個,如何跳轉(zhuǎn)到之前打開的窗口,如果確實有這個需求,那么打開窗口是就需要記錄每一個窗口的 key(別名) 與 value(handle),保存到字典中,后續(xù)根據(jù) key 來取 handle 。

表單切換

很多頁面也會用帶 frame/iframe 表單嵌套,對于這種內(nèi)嵌的頁面 selenium 是無法直接定位的,需要使用 switch_to.frame() 方法將當(dāng)前操作的對象切換成 frame/iframe 內(nèi)嵌的頁面。

switch_to.frame() 默認(rèn)可以用的 idname 屬性直接定位,但如果 iframe 沒有 idname ,這時就需要使用 xpath 進(jìn)行定位。下面先寫一個包含 iframe 的頁面做測試用。

DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <meta http-equiv="X-UA-Compatible" content="IE=edge">    <meta name="viewport" content="width=device-width, initial-scale=1.0">    <title>Documenttitle>    <style>        div p {            color: #red;            animation: change 2s infinite;        }        @keyframes change {            from {                color: red;            }            to {                color: blue;            }        }    style>head><body>    <div>        <p>公眾號:Python新視野p>        <p>CSDN:Dream丶Killerp>        <p>微信:python-sunp>    div>    <iframe src="https://blog.csdn.net/qq_43965708" width="400" height="200">iframe>body>html>

現(xiàn)在我們定位紅框中的 CSDN 按鈕,可以跳轉(zhuǎn)到 CSDN 首頁。

from selenium import webdriverfrom pathlib import Pathdriver = webdriver.Chrome()# 讀取本地html文件driver.get("file:///" + str(Path(Path.cwd(), "iframe測試.html")))# 1.通過id定位driver.switch_to.frame("CSDN_info")# 2.通過name定位# driver.switch_to.frame("Dream丶Killer")# 通過xpath定位# 3.iframe_label = driver.find_element_by_xpath("/html/body/iframe")# driver.switch_to.frame(iframe_label)driver.find_element_by_xpath("http://*[@id="csdn-toolbar"]/div/div/div[1]/div/a/img").click()

這里列舉了三種定位方式,都可以定位 iframe 。


彈窗處理

JavaScript 有三種彈窗 alert(確認(rèn))、confirm(確認(rèn)、取消)、prompt(文本框、確認(rèn)、取消)。

處理方式:先定位(switch_to.alert自動獲取當(dāng)前彈窗),再使用 text、acceptdismiss、send_keys 等方法進(jìn)行操作

方法描述
text獲取彈窗中的文字
accept接受(確認(rèn))彈窗內(nèi)容
dismiss解除(取消)彈窗
send_keys發(fā)送文本至警告框

這里寫一個簡單的測試頁面,其中包含三個按鈕,分別對應(yīng)三個彈窗。

DOCTYPE html><html lang="en"><head>head><body>    <button id="alert">alertbutton>    <button id="confirm">confirmbutton>    <button id="prompt">promptbutton>    <script type="text/javascript">        const dom1 = document.getElementById("alert")        dom1.addEventListener("click", function(){           alert("alert hello")        })                const dom2 = document.getElementById("confirm")        dom2.addEventListener("click", function(){            confirm("confirm hello")        })                const dom3 = document.getElementById("prompt")        dom3.addEventListener("click", function(){            prompt("prompt hello")        })    script>body>html>


下面使用上面的方法進(jìn)行測試。為了防止彈窗操作過快,每次操作彈窗,都使用 sleep 強制等待一段時間。

from selenium import webdriverfrom pathlib import Pathfrom time import sleepdriver = webdriver.Firefox()driver.get("file:///" + str(Path(Path.cwd(), "彈窗.html")))sleep(2)# 點擊alert按鈕driver.find_element_by_xpath("http://*[@id="alert"]").click()sleep(1)alert = driver.switch_to.alert# 打印alert彈窗的文本print(alert.text)# 確認(rèn)alert.accept()sleep(2)# 點擊confirm按鈕driver.find_element_by_xpath("http://*[@id="confirm"]").click()sleep(1)confirm = driver.switch_to.alertprint(confirm.text)# 取消confirm.dismiss()sleep(2)# 點擊confirm按鈕driver.find_element_by_xpath("http://*[@id="prompt"]").click()sleep(1)prompt = driver.switch_to.alertprint(prompt.text)# 向prompt的輸入框中傳入文本prompt.send_keys("Dream丶Killer")sleep(2)prompt.accept()"""輸出alert helloconfirm helloprompt hello"""

注:細(xì)心地讀者應(yīng)該會發(fā)現(xiàn)這次操作的瀏覽器是 Firefox ,為什么不用 Chrome 呢?原因是測試時發(fā)現(xiàn)執(zhí)行 promptsend_keys 時,不能將文本填入輸入框。嘗試了各種方法并查看源碼后確認(rèn)不是代碼的問題,之后通過其他渠道得知原因可能是 Chrome 的版本與 selenium 版本的問題,但也沒有很方便的解決方案,因此沒有繼續(xù)深究,改用 Firefox 可成功運行。這里記錄一下我的 Chrome 版本,如果有大佬懂得如何在 Chrome 上解決這個問題,請在評論區(qū)指導(dǎo)一下,提前感謝!
selenium:3.141.0
Chrome:94.0.4606.71

未完待續(xù)~


??往期精彩,不容錯過??

總結(jié)篇
??兩萬字,50個pandas高頻操作【圖文并茂,值得收藏】??
??吐血總結(jié)《Mysql從入門到入魔》,圖文并茂(建議收藏)??


工具篇
??Python實用小工具之制作酷炫二維碼(有界面、附源碼)??
??Python實用工具之制作證件照(有界面、附源碼)??
??女朋友桌面文件雜亂無章?氣得我用Python給她做了一個文件整理工具??

更多有趣的文章及干貨,盡在

? ? ?

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/122012.html

相關(guān)文章

  • ??爬蟲+動化利器 selenium 自學(xué)成才(一)??

    文章目錄 selenium 簡介selenium安裝安裝瀏覽器驅(qū)動確定瀏覽器版本下載驅(qū)動 定位頁面元素打開指定頁面id 定位name 定位class 定位tag 定位xpath 定位css 定位link 定位partial_link 定位 瀏覽器控制修改瀏覽器窗口大小瀏覽器前進(jìn)&后退瀏覽器刷新瀏覽器窗口切換常見操作 鼠標(biāo)控制單擊左鍵單擊右鍵雙擊拖動鼠標(biāo)懸停 鍵盤控制 seleni...

    james 評論0 收藏0
  • 零基礎(chǔ)如何學(xué)爬蟲技術(shù)

    摘要:楚江數(shù)據(jù)是專業(yè)的互聯(lián)網(wǎng)數(shù)據(jù)技術(shù)服務(wù),現(xiàn)整理出零基礎(chǔ)如何學(xué)爬蟲技術(shù)以供學(xué)習(xí),。本文來源知乎作者路人甲鏈接楚江數(shù)據(jù)提供網(wǎng)站數(shù)據(jù)采集和爬蟲軟件定制開發(fā)服務(wù),服務(wù)范圍涵蓋社交網(wǎng)絡(luò)電子商務(wù)分類信息學(xué)術(shù)研究等。 楚江數(shù)據(jù)是專業(yè)的互聯(lián)網(wǎng)數(shù)據(jù)技術(shù)服務(wù),現(xiàn)整理出零基礎(chǔ)如何學(xué)爬蟲技術(shù)以供學(xué)習(xí),http://www.chujiangdata.com。 第一:Python爬蟲學(xué)習(xí)系列教程(來源于某博主:htt...

    KunMinX 評論0 收藏0
  • 首次公開,整理12年積累的博客收藏夾,零距離展示《收藏夾吃灰》系列博客

    摘要:時間永遠(yuǎn)都過得那么快,一晃從年注冊,到現(xiàn)在已經(jīng)過去了年那些被我藏在收藏夾吃灰的文章,已經(jīng)太多了,是時候把他們整理一下了。那是因為收藏夾太亂,橡皮擦給設(shè)置私密了,不收拾不好看呀。 ...

    Harriet666 評論0 收藏0
  • 軟件測試江湖()神兵利器

    摘要:軟件測試江湖二神兵利器篇在上一篇文章中我們介紹了江湖上流傳的各種軟件測試的武功秘籍和心法,相信看過的小伙伴內(nèi)力得到了很大的提升。功能測試篇功能測試,是軟件測試?yán)锏娜腴T級心法,自然也有與之相對應(yīng)的兵器來發(fā)揮心法的最大功力。 軟件測試江湖(二)神兵利器篇 在上一篇文章中我們介紹了江湖上流傳的各種軟件測試的武功秘籍和心法,相信看過的小伙伴內(nèi)力得到了很大的提升。如果沒有,一定是你看的姿勢不對,...

    _Suqin 評論0 收藏0
  • 軟件測試江湖()神兵利器

    摘要:軟件測試江湖二神兵利器篇在上一篇文章中我們介紹了江湖上流傳的各種軟件測試的武功秘籍和心法,相信看過的小伙伴內(nèi)力得到了很大的提升。功能測試篇功能測試,是軟件測試?yán)锏娜腴T級心法,自然也有與之相對應(yīng)的兵器來發(fā)揮心法的最大功力。 軟件測試江湖(二)神兵利器篇 在上一篇文章中我們介紹了江湖上流傳的各種軟件測試的武功秘籍和心法,相信看過的小伙伴內(nèi)力得到了很大的提升。如果沒有,一定是你看的姿勢不對,...

    fai1017 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<