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