摘要:然而讓蟲(chóng)師們垂涎的并不是以上的種種,而是其通過(guò)驅(qū)動(dòng)瀏覽器獲得的解析的能力。所以說(shuō)這貨在動(dòng)態(tài)爬取方面簡(jiǎn)直是掛逼級(jí)別的存在,相較于手動(dòng)分析更簡(jiǎn)單易用,節(jié)省分析打碼時(shí)間。一旦設(shè)置了隱式等待時(shí)間,它的作用范圍就是對(duì)象實(shí)例的整個(gè)生命周期。
selenium——自動(dòng)化測(cè)試工具,專(zhuān)門(mén)為Web應(yīng)用程序編寫(xiě)的一個(gè)驗(yàn)收測(cè)試工具,測(cè)試其兼容性,功能什么的。然而讓蟲(chóng)師們垂涎的并不是以上的種種,而是其通過(guò)驅(qū)動(dòng)瀏覽器獲得的解析JavaScript的能力。所以說(shuō)這貨在動(dòng)態(tài)爬取方面簡(jiǎn)直是掛逼級(jí)別的存在,相較于手動(dòng)分析更簡(jiǎn)單易用,節(jié)省分析打碼時(shí)間。
雖然selenium因其“超能力”被不少人吹上天了,但是認(rèn)清利弊,根據(jù)需求來(lái)選擇爬蟲(chóng)工具,還是挺重要的,所以這里簡(jiǎn)單說(shuō)下以供參考:
selenium無(wú)腦解決動(dòng)態(tài)難題
selenium更耐網(wǎng)頁(yè)變動(dòng)
selenium極大提升開(kāi)發(fā)效率,但極大降低爬取效率(規(guī)模一大就明顯了)。
selenium更占用資源(cpu,內(nèi)存,網(wǎng)絡(luò))
理由:打開(kāi)一個(gè)/多個(gè)瀏覽器,瀏覽器里還有n個(gè)窗口.....
下面不多說(shuō),進(jìn)入正題
本體直接pip安裝pip install selenium
驅(qū)動(dòng)按需選擇:
chrome (內(nèi)核版本要對(duì)應(yīng),詳看其中的notes.txt)
firefox (相信各位的英文實(shí)力)
IE (很少用吧)
下載好后把解壓得到的驅(qū)動(dòng)放到設(shè)置了環(huán)境變量的路徑下就行了,如果你的python設(shè)置了環(huán)境變量,應(yīng)該丟到python目錄下就行了。
簡(jiǎn)單嘗試照例貼上文檔,2.53舊版中文,想學(xué)更多就給我啃
選好瀏覽器就創(chuàng)建實(shí)例,之后的操作都在這個(gè)實(shí)例之上,并介紹一些有用的option,本文以Chrome為例。
from selenium import webdriver #其他瀏覽器把Chrome換名就行 #option = webdriver.ChromeOptions() #option.set_headless() 設(shè)置無(wú)頭瀏覽器,就是隱藏界面后臺(tái)運(yùn)行 driver = webdriver.Chrome() #創(chuàng)建driver實(shí)例 #driver = webdriver.Chrome(chrome_options=option) 創(chuàng)建實(shí)例并載入option url = "**********" driver.get(url) #driver.maximize_window() 最大化窗口 #driver.set_window_size(width,height) 設(shè)置窗口大小 print(driver.page_source) #打印網(wǎng)頁(yè)源碼 driver.quit() # 關(guān)閉瀏覽器
對(duì)付低級(jí)的動(dòng)態(tài)網(wǎng)頁(yè)(ajax較少)就是這么簡(jiǎn)單,基本不用考慮動(dòng)態(tài)問(wèn)題,徒手?jǐn)]動(dòng)態(tài)的人表示羨慕。然而更多時(shí)候并不像這樣簡(jiǎn)單,直接套用的話很容易導(dǎo)致源碼所見(jiàn)非所得,而且很多爬蟲(chóng)并沒(méi)有簡(jiǎn)單到拿個(gè)源碼就走的程度,它還要交互,模擬點(diǎn)擊滾動(dòng)等等。所以還請(qǐng)往下看,不要看到這就投入實(shí)戰(zhàn)啦
定位selenium提供多種方法對(duì)元素進(jìn)行定位,返回WebElement對(duì)象,而上面提到的driver就相當(dāng)于最大的WebElement對(duì)象
#以下都是單次定位,返回第一個(gè)定位到的。如果想多次定位,給element加個(gè)s就行,返回的是符合元素的列表 element = driver.find_element_by_id() # 通過(guò)標(biāo)簽的id定位,接收id屬性值 driver.find_element_by_name() # 通過(guò)標(biāo)簽的name定位,接收name屬性值 driver.find_element_by_xpath() # 通過(guò)xpath定位,接收xpath表達(dá)式 driver.find_element_by_link_text() # 通過(guò)標(biāo)簽的完全文本定位,接收完整的文本 driver.find_element_by_partial_link_text() # 通過(guò)標(biāo)簽的部分文本定位,接收部分文本 driver.find_element_by_tag_name() # 通過(guò)標(biāo)簽名定位,接收標(biāo)簽名 driver.find_element_by_class_name() # 通過(guò)標(biāo)簽的class定位,接收class屬性值 driver.find_element_by_css_selector() # 通過(guò)css選擇器定位,接收其語(yǔ)法 #返回的WebElement對(duì)象可以繼續(xù)往下定位
xpath和css就不展開(kāi)講了,能實(shí)現(xiàn)精確定位,一定要學(xué)其中一個(gè),不知道的小伙伴們上網(wǎng)自學(xué)吧,不難
除了上面這些公有的方法,還有2個(gè)私有的方法來(lái)幫助頁(yè)面對(duì)象的定位。 這兩個(gè)方法就是 find_element 和 find_elements,需要導(dǎo)入By類(lèi)輔助,接收一個(gè)By類(lèi)屬性及其對(duì)應(yīng)語(yǔ)法/值
from selenium.webdriver.common.by import By driver.find_element(By.XPATH,"http://a[text()="dark"]") driver.find_elements(By.XPATH,"http://a[text()="dark"]") """By類(lèi)有以下屬性 ID = "id" XPATH = "xpath" LINK_TEXT = "link text" PARTIAL_LINK_TEXT = "partial link text" NAME = "name" TAG_NAME = "tag_name" CLASS_NAME = "class name" CSS_SELECTOR = "css selector" """frame切換
很多人在用selenium會(huì)遇到所見(jiàn)非所得,或者定位頁(yè)面元素的時(shí)候會(huì)定位不到的問(wèn)題,這種情況很有可能是frame在搞鬼,必須切換到相應(yīng)frame中再進(jìn)行定位。如果遇到以上問(wèn)題,第一時(shí)間F12看下你所要的信息是否在frame標(biāo)簽里面。
frame標(biāo)簽有frameset、frame、iframe三種,frameset跟其他普通標(biāo)簽沒(méi)有區(qū)別,不會(huì)影響到正常的定位,而frame與iframe對(duì)selenium定位而言是一樣的。
selenium提供了4種方法定位iframe并切換進(jìn)去:
#對(duì)于 driver.switch_to_frame(0) # 用frame的index來(lái)定位,第一個(gè)是0,以此類(lèi)推 driver.switch_to_frame("frame1") # 用id來(lái)定位 driver.switch_to_frame("dark") # 用name來(lái)定位 driver.switch_to_frame(driver.find_element_by_tag_name("iframe")) # 用WebElement對(duì)象來(lái)定位
通常通過(guò)id和name就能實(shí)現(xiàn),無(wú)此屬性時(shí)可以通過(guò)WebElement對(duì)象,即用find_element系列方法所取得的對(duì)象來(lái)定位。如果你確定每個(gè)目標(biāo)frame都是固定第幾個(gè),那也可以用index定位
切到frame中之后,就不能繼續(xù)操作主文檔的元素了,這時(shí)如果想操作主文檔內(nèi)容,則需切回主文檔。
driver.switch_to_default_content()
嵌套frame的切換
如果frame里包著frame而你要的frame是后者,那么需要一層一層切換進(jìn)去,切換方法四選一
driver.switch_to_frame("frame1") driver.switch_to_frame("frame2")
如果想回去上一個(gè)父frame,用driver.switch_to.parent_frame()
window 切換有時(shí)候點(diǎn)開(kāi)一個(gè)鏈接就會(huì)彈出一個(gè)新窗口,如果要對(duì)其操作就要切換過(guò)去,方法和frame的切換差不多,但只接收window_handle(相當(dāng)于窗口的名字)來(lái)進(jìn)行切換。driver.switch_to_window("windowName")
切換前最好保存之前的handle和所有的handles以便于來(lái)回切換。
current_window = driver.current_window_handle # 獲取當(dāng)前窗口handle name all_windows = driver.window_handles # 獲取所有窗口handle name # 如果window不是當(dāng)前window,則切換到該window,即切換到新窗口 for window in all_windows: if window != current_window: driver.switch_to_window(window) #.... driver.switch_to_window(current_window) # 返回之前的窗口 driver.close() # 窗口的關(guān)閉用close()頁(yè)面交互
常用的頁(yè)面交互有點(diǎn)擊,輸入文本等。交互的原則是先定位,后交互,比如你F12找到了某個(gè)文本框或某個(gè)可點(diǎn)擊項(xiàng)的標(biāo)簽,那就先定位到那,再用以下的交互方法
from selenium.webdriver.common.keys import Keys # 首先定位到某個(gè)文本框或某個(gè)可點(diǎn)擊項(xiàng)(如超鏈接,按鈕), element = driver.find_element_by_xpath("http://a[text()="dark"]") element.send_keys("some text") # 往文本框輸入文本 #element.send_keys("some text", Keys.ARROW_DOWN) 可以使用 Keys 類(lèi)來(lái)模擬輸入方向鍵 element.clear() # 清空文本框 #element.click() 如果此元素可點(diǎn)擊,可用click()方法
要注意的一點(diǎn)是,不是定位到就必定能交互,有時(shí)候目標(biāo)會(huì)被網(wǎng)頁(yè)彈出來(lái)的東西覆蓋,導(dǎo)致無(wú)法交互,所以要確保頁(yè)面干凈無(wú)覆蓋
上下拉滾動(dòng)selenium可以執(zhí)行js,下拉滾動(dòng)可以通過(guò)此實(shí)現(xiàn),因此就算不懂js也可以記一些有用的js代碼
#driver.execute_script("js_str") driver.execute_script("window.scrollTo(0,10000)") # 移動(dòng)到指定坐標(biāo) driver.execute_script("window.scrollBy(0,10000)") # 相對(duì)當(dāng)前坐標(biāo)移動(dòng) driver.execute_script("window.scrollTo(0, document.body.scrollHeight)") # 相對(duì)當(dāng)前坐標(biāo)移動(dòng)等待
現(xiàn)在不少web都都有使用ajax技術(shù),即異步加載,有時(shí)候你要的東西都還沒(méi)加載到你就去定位了,就會(huì)拋出異常。為了避免此等血淋淋的慘狀,必須要待其加載一段時(shí)間后再進(jìn)行后面的操作。這里付一張不等待就獲取page_source的后果
最粗暴的方法就是使用time.sleep(),這很笨,因?yàn)槟氵€要設(shè)置合適的時(shí)間,而不同網(wǎng)站加載的速度有異,容易造成時(shí)間的浪費(fèi)。所以最好還是使用selenium提供的兩種等待方法
顯式Wiats顯式Wiats允許你設(shè)置一個(gè)加載時(shí)間的上限和一個(gè)條件,每隔0.5s就判斷一下所設(shè)條件,條件成立就繼續(xù)執(zhí)行下面的代碼,如果過(guò)了時(shí)間上限還是沒(méi)有成立,默認(rèn)拋出NoSuchElementException 異常。這種相對(duì)智能的等待方法能最大化地節(jié)省時(shí)間,應(yīng)該優(yōu)先選擇使用
selenium提供了多種expected_conditions(EC)來(lái)設(shè)置條件,但是要注意有定位時(shí)EC的方法接收的是定位信息的元組(locator_tuple)而不是兩個(gè)參數(shù),正確用法如 EC.presence_of_element_located((By.ID,"dark"))
這個(gè)條件檢測(cè)是否有id="dark"的元素
selenium提供的EC有以下方法,意思如其名,這里注釋一些易搞錯(cuò)的,選擇使用
title_is(str)
title_contains(str)
presence_of_element_located(locator_tuple)
visibility_of_element_located(locator_tuple) # 判斷某個(gè)元素是否可見(jiàn)
visibility_of(WebElement) # 同上,傳參不同
presence_of_all_elements_located(locator_tuple)
text_to_be_present_in_element(str) # 判斷某個(gè)元素中的text是否包含了指定字符串
text_to_be_present_in_element_value(str) # 判斷某個(gè)元素中的value屬性是否包含了預(yù)期的字符串
frame_to_be_available_and_switch_to_it
invisibility_of_element_located(locator_tuple)
element_to_be_clickable(locator_tuple)
staleness_of(WebElement) # 等待某個(gè)元素從的移除
element_to_be_selected(WebElement)
element_located_to_be_selected(locator_tuple)
element_selection_state_to_be(WebElement)
element_located_selection_state_to_be(locator_tuple)
alert_is_present() # 判斷頁(yè)面上是否存在alert
使用上通常搭配try語(yǔ)句
from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait # 導(dǎo)入顯式等待 from selenium.webdriver.support import expected_conditions as EC # 導(dǎo)入EC from selenium.common.exceptions import NoSuchElementException # WebDriverWait(driver,time).until(EC) 顯式waits try: element = WebDriverWait(driver,10).until(EC.presence_of_element_located((By.ID,"myDynamicElement"))) except NoSuchElementException: #..... finally: driver.quit()隱式等待
隱式等待是在嘗試定位某個(gè)元素的時(shí)候,如果沒(méi)能成功,就等待固定長(zhǎng)度的時(shí)間,默認(rèn)0秒。一旦設(shè)置了隱式等待時(shí)間,它的作用范圍就是Webdriver對(duì)象實(shí)例的整個(gè)生命周期。driver.implicitly_wait(10)
最后補(bǔ)充這是用selenium幾分鐘弄出來(lái)的網(wǎng)易云音樂(lè)單曲評(píng)論爬蟲(chóng),而且還模擬了評(píng)論翻頁(yè),還截了圖。沒(méi)提取信息,提取的時(shí)候可以用BeautifulSoup或正則提取,
from selenium import webdriver import time from selenium.common.exceptions import NoSuchElementException, TimeoutException from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait driver = webdriver.Chrome() driver.maximize_window() driver.get("http://music.163.com/#/song?id=31877470") driver.switch_to_frame("contentFrame") time.sleep(5) driver.execute_script("window.scrollTo(0, document.body.scrollHeight)") driver.save_screenshot("E:/python3/gg.png") # 截圖 b = driver.find_element_by_xpath("http://a[starts-with(@class,"zbtn znxt")]") b.click() try: WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.XPATH,"http://a[@data-type="reply"]"))) print(driver.page_source) except NoSuchElementException: print("OMG") finally: driver.quit()
短短二十行就能做到這種程度(而且不少還是import的),足以見(jiàn)得selenium強(qiáng)大。如果要手動(dòng)分析,你還要分析js加密算法,寫(xiě)上n倍的代碼。兩者相比起來(lái)selenium真的很吸引人,簡(jiǎn)直是懶人救星。大家權(quán)衡利弊按需選擇吧
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/42071.html
摘要:之前提到動(dòng)態(tài)加載就兩個(gè)解決方案手動(dòng)分析和。背后有許多不為人知的交易進(jìn)行著,動(dòng)態(tài)爬取的任務(wù)就是攔截它們揭開(kāi)它們的真面目。在爬蟲(chóng)界有著霸王硬上弓的稱(chēng)號(hào),管它情不情愿,來(lái)了動(dòng)態(tài)加載也只有屈服的份了。 之前提到動(dòng)態(tài)加載就兩個(gè)解決方案——手動(dòng)分析和selenium。接下來(lái)的文章我們會(huì)來(lái)深入探討它們,本文將首先,重點(diǎn)介紹前者——手動(dòng)分析 手動(dòng)分析是一個(gè)比較有難度,比較麻煩的解決方案,但優(yōu)點(diǎn)也很明顯...
摘要:楚江數(shù)據(jù)是專(zhuān)業(yè)的互聯(lián)網(wǎng)數(shù)據(jù)技術(shù)服務(wù),現(xiàn)整理出零基礎(chǔ)如何學(xué)爬蟲(chóng)技術(shù)以供學(xué)習(xí),。本文來(lái)源知乎作者路人甲鏈接楚江數(shù)據(jù)提供網(wǎng)站數(shù)據(jù)采集和爬蟲(chóng)軟件定制開(kāi)發(fā)服務(wù),服務(wù)范圍涵蓋社交網(wǎng)絡(luò)電子商務(wù)分類(lèi)信息學(xué)術(shù)研究等。 楚江數(shù)據(jù)是專(zhuān)業(yè)的互聯(lián)網(wǎng)數(shù)據(jù)技術(shù)服務(wù),現(xiàn)整理出零基礎(chǔ)如何學(xué)爬蟲(chóng)技術(shù)以供學(xué)習(xí),http://www.chujiangdata.com。 第一:Python爬蟲(chóng)學(xué)習(xí)系列教程(來(lái)源于某博主:htt...
摘要:時(shí)間永遠(yuǎn)都過(guò)得那么快,一晃從年注冊(cè),到現(xiàn)在已經(jīng)過(guò)去了年那些被我藏在收藏夾吃灰的文章,已經(jīng)太多了,是時(shí)候把他們整理一下了。那是因?yàn)槭詹貖A太亂,橡皮擦給設(shè)置私密了,不收拾不好看呀。 ...
摘要:其次,使用后,還需要針對(duì)做特定處理??吹竭@就可以構(gòu)想一下爬蟲(chóng)的爬取邏輯了。 運(yùn)行環(huán)境 我的運(yùn)行環(huán)境如下: 系統(tǒng)版本 Windows10。 Python版本 Python3.5,推薦使用Anaconda 這個(gè)科學(xué)計(jì)算版本,主要是因?yàn)樗詭б粋€(gè)包管理工具,可以解決有些包安裝錯(cuò)誤的問(wèn)題。去Anaconda官網(wǎng),選擇Python3.5版本,然后下載安裝。 IDE 我使用的是PyCharm,是專(zhuān)...
閱讀 1685·2021-11-17 09:33
閱讀 3547·2021-11-16 11:40
閱讀 3066·2019-08-30 11:23
閱讀 1059·2019-08-29 16:36
閱讀 2477·2019-08-29 13:23
閱讀 1751·2019-08-29 12:59
閱讀 1555·2019-08-29 12:42
閱讀 1992·2019-08-28 18:22