javascript
driver.get调用iframe中的页面_【5分钟玩转Lighthouse】爬取JavaScript动态渲染页面
0x00 背景概述
通過【技術干貨 007 | Scrapy爬蟲初探】教程,大家應該已經對如何編寫爬蟲有了一定的認識。但對于較為復雜的網站設計,比如網站頁面使用了JavaScript動態渲染,入門級的爬蟲就不太適用。
本文針對JavaScript動態渲染頁面,使用selenium+scrapy,爬取levels.fyi中微軟公司員工的信息和薪酬(示例頁面),目的在于講述JavaScript頁面如何進行爬取,并將程序部署在騰訊云輕量服務器Lighthouse中。
0x01 服務器準備
輕量應用服務器(Lighthouse)是一種易于使用和管理、適合承載輕量級業務負載的云服務器,能幫助中小企業及開發者在云端快速構建網站、博客、電商、論壇等各類應用以及開發測試環境,并提供應用部署、配置和管理的全流程一站式服務。
這里我們先選擇LAMP鏡像,選擇套餐后進行支付,就擁有了屬于你的Lighthouse鏡像! (購買傳送門->)
0x02 頁面分析
levels.fyi中進入開發者模式,可以看到待爬取的元素其實是一個iframe,數據由script腳本生成:
我們需要獲取tbody下的每一個tr,并選擇我們需要的數據
我們直接使用Request獲取tbody,會發現該元素下并沒有任何數據:
t_body = response.css("table#compTable tbody").extract()print(t_body)下面,我們講解下如何成功的獲取javaScript生成的tbody數據
0x03 Selenium獲取
Selenium是一個web自動化工具,運行在瀏覽器中,使用腳本模擬用戶對瀏覽器進行操作。在本例中,本質上是使用Selenium等待javascript加載完成后,再獲取數據。Selenium的安裝和配置非常簡單,腳本編寫也非常容易。而缺點在于,相比起其他爬取方式,Selenium的爬取速度相對較慢。
Selenium安裝:pip install selenium
瀏覽器驅動下載:使用Selenium需要下載瀏覽器驅動,推薦下載Chrome版本,下載完成后mac可以直接放在/usr/local/bin,Windows需要在腳本里配置下路徑或者配置環境變量
建立scrapy項目,新建MicrosoftSpider,并進行簡單的配置,方法與【技術干貨 007 | Scrapy爬蟲初探】一樣。
獲取driver對象:
driver = webdriver.Chrome()使用WebDriverWait,等待頁面加載完成。在這里,我們設置超時時間為5秒:
wait = WebDriverWait(self.driver, 5) wait.until(lambda driver: driver.find_element_by_xpath('//*[@id="compTable"]/tbody/tr[1]')) # 等待第一行內容加載完成wait結束后,獲取一下tbody中的第一行數據試試
tr1 = self.driver.find_element_by_xpath('//*[@id="compTable"]/tbody/tr[1]').text # 每一行信息 print(tr1)我們已經成功獲取到第一行數據了!在上述代碼中,我們使用了find_element_by_xpath函數。這個函數是Selenium中獲取元素的函數,返回的是WebElement類型,可以通過text獲取元素的文本
接下來,我們使用同樣的方法,獲取‘下一頁’按鈕,并點擊該按鈕:
wait = WebDriverWait(self.driver, 1) wait.until(lambda driver: driver.find_element_by_css_selector('li.page-item.page-next')) # 等待內容加載完成 next_page = self.driver.find_element_by_css_selector('li.page-item.page-next a') next_page.click() # 模擬點擊下一頁next_page同樣是WebElement類型。可以看到,WebElement除了text等基本屬性外,還具有click這樣的動作。實際上,這也是WebElement最常使用的方式。
其余方法可見WebElement API文檔。
現在已經獲取了所有關鍵的元素了!接下來,就是爬取每一行的元素,并進行循環點擊!
0x04 爬蟲的路上總是充滿坎坷
Selenium的教程到這里其實已經結束了,但是如果有同學去嘗試爬取網站的活,會發現各種各樣神奇的bug。
這些bug并非程序的問題,而是因為有著五花八門的網站。這些網站的設計者們腦海里可能有個哪吒在鬧海,讓你根本想不明白他在想什么。在這里也分享一下在爬取示例網站時的趣事。
JavaScript嵌套
如下圖,當你點擊iframe的一行時,會出來一個新的iframe,數據同樣是由JavaScript生成的。獲取新的iframe數據并不難,wait+find就可以得到。難點在于,當每一行都點擊的時候,你要如何把新出現的iframe和他所屬的iframe關聯起來呢?畢竟,像下圖一樣,每個新出現的iframe的class都是"detail-view"。
最開始我嘗試兩個map,然后join,但是很難保證join后的結果是正確的。后來我發現了新的Iframe的特點:當再次點擊該行數據時,新的Iframe會被關閉。這樣,就有了取巧的辦法:在循環爬取數據的時候,每次生成新的iFrame,并爬取數據后,再次調用click,把Iframe關閉。這樣,就可以保證每次根據'detail-view'獲取元素的時候,就只有唯一的一個Iframe。
這個解決辦法看起來毫無技術含量,并且增加了爬取的總耗時:增加了一個click動作的耗時。但是就像在開頭說的一樣:寫爬蟲的時候,總是“不擇手段”的。當你可以很快的想到一個解決爬蟲問題的方法,并且很容易實現時,你就可以大膽的使用他,哪怕它并不是最優的解決辦法。畢竟,在你費腦筋想到更好的解決辦法時,使用“笨”辦法爬取的數據可能已經到手了。
爬取中斷
如果你嘗試爬取示例網站的時候,你會發現,爬蟲在爬取到1000余條的時候,會被中斷,同時提示:元素‘page-link’無法被點擊,也就是點擊不了‘下一頁’按鈕。
最開始的時候,我以為是那一頁數據缺少了‘下一頁’按鈕的href,畢竟,類似按鈕缺少href,鏈接突然變成text這樣的事情實在是太普遍了。但是,在我找到該頁數據的時候,我發現并不是這樣的。該頁數據看起來非常的正常,‘下一頁’按鈕也是具有href,可以被正常點擊的。但是在我重復爬取了多次后,在爬取到該頁數據時爬蟲均會中斷,同時提示我元素‘page-link’無法被點擊。這個問題困擾了我很久,直到我發現:
這是個可以和網站客服人員聯系的按鈕,在第125頁的時候,他神奇的出現在了‘下一頁’按鈕的上方,遮擋住了‘下一頁’按鈕,導致模擬器無法點擊到‘下一頁’按鈕。這個問題也是讓人有些哭笑不得。
如何解決呢?辦法其實非常的簡單,把模擬器的窗口調大。因為‘聊天按鈕‘的位置是依據當前窗口大小,也就是相對位置,而’下一頁‘按鈕不一樣。這樣,就可以保證讓兩個按鈕分開:
數據也就可以正常爬取了。
之所以寫出這兩個例子,是因為這兩個解決方法其實都屬于‘怪邏輯’:一個莫名其妙的點擊,和一個莫名其妙的調大窗口。如果你僅僅去看代碼,你不會明白這兩行代碼的意義在哪里。但是對于這個網站而言,這兩行又是必需的。就像文章開頭提到的‘不擇手段’,在解決問題的時候,換一種角度去思考,可能會比從正面解決要容易得多。
0x05 參考資料
示例代碼github地址
更多騰訊云服務器技術干貨、優惠活動、交流社區,敬請關注「騰訊云服務器」微信公眾號(TencentCVM)
總結
以上是生活随笔為你收集整理的driver.get调用iframe中的页面_【5分钟玩转Lighthouse】爬取JavaScript动态渲染页面的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python生成随机数方法_Python
- 下一篇: QT QNetworkInterface