標籤:sleep 特定 screens 一點 利用 col function out obj
對WebElement
WebDriver.Chrome內建的方法只能對當前視窗截屏,且不能指定特定元素。若是需要截取特定元素或是視窗超過了一屏,就只能另闢蹊徑了。
WebDriver.PhantomJS內建的方法支援對整個網頁截屏。
下面提供幾種思路。
方式一
針對WebDriver.Chrome
通過WebDriver的js指令碼注入功能,曲線救國。
注入第三方html轉canvas的js庫(見下方推薦)
擷取元素html源碼
將html轉換為canvas
下載canvas
優點: 截取長圖容易實現
缺點: 載入第三方庫耗費時間,轉換原理請參考這篇文章:
將 DOM 對象繪製到 canvas 中
方式二
針對WebDriver.Chrome
截取全圖,自行裁剪、拼接
擷取元素位置、大小
擷取視窗大小
截取包含元素的視窗
進行相應的裁剪和拼接。
具體演算法思路很清晰,但需要注意的細節較多。這裡就不在贅述。範例程式碼請移步:
[Github]PythonSpiderLibs
優點: 不需太多js工作,python+少量js代碼即可完成
缺點: 拼接等工作會被WebDriver的實現差異、圖片載入速度等因素影響,需多加註意。 在保證品質的情況下,速度較慢
方式三
針對WebDriver.PhantomJS
由於介面實現的差異,PhantomJS相比於Chrome,可以截取到整個網頁。所以擷取指定元素的也就簡單很多
截取網頁全圖
裁剪指定元素
driver = webdriver.Chrome()driver.get(‘http://stackoverflow.com/‘)driver.save_screenshot(‘screenshot.png‘)left = element.location[‘x‘]top = element.location[‘y‘]right = element.location[‘x‘] + element.size[‘width‘]bottom = element.location[‘y‘] + element.size[‘height‘]im = Image.open(‘screenshot.png‘) im = im.crop((left, top, right, bottom))im.save(‘screenshot.png‘)
優點: 實現簡單
缺點: 對於高度太高的頁面會導致檔案過大,處理會有問題,我測試的最大圖片尺寸是12.8M。
解決圖片載入不完整的問題
參考: 利用 Python + Selenium 自動化快速
我們先在首頁上執行一段 JavaScript 指令碼,將頁面的捲軸拖到最下方,然後再拖回頂部,最後才。這樣可以解決像上面那種按需載入圖片的情況。
# -*- coding: utf-8 -*-from selenium import webdriverimport timedef take_screenshot(url, save_fn="capture.png"): # browser = webdriver.Firefox() # Get local session of firefox #Google瀏覽器截取當前視窗網頁 chromedriver = r"C:\soft\chromedriver2.31_win32\chromedriver.exe" browser = webdriver.Chrome(chromedriver) #phantomjs截取整張網頁 # browser = webdriver.PhantomJS() browser.set_window_size(1200, 900) browser.get(url) # Load page #將頁面的捲軸拖到最下方,然後再拖回頂部 browser.execute_script(""" (function () { var y = 0; var step = 100; window.scroll(0, 0); function f() { if (y < document.body.scrollHeight) { y += step; window.scroll(0, y); setTimeout(f, 100); } else { window.scroll(0, 0); document.title += "scroll-done"; } } setTimeout(f, 1000); })(); """) for i in xrange(30): if "scroll-done" in browser.title: break time.sleep(10) browser.save_screenshot(save_fn) browser.close()if __name__ == "__main__": take_screenshot("http://codingpy.com")
如何截取某個網頁元素
有時候我們只想截取某個網頁元素的圖片呢?比如說會動態變化的驗證碼。本來 Selenium 也提供了對元素的支援,只要在選中的元素上調用其 screenshot() 方法即可。
但是在實際使用時卻遇到了 Unrecognized command 這個異常,經過一段時間檢索也沒有找到解決辦法。所以,只能曲線救國,利用 Selenium 執行JS代碼,將頁面上不需要的元素一一刪除,只保留我們希望留下的元素,然後再利用上面的視窗截屏功能。
例如,如果我們只截取編程派網站右側的二維碼,可以執行這樣一段JQuery代碼:
$(‘#main‘).siblings().remove();$(‘#aside__wrapper‘).siblings().remove();$(‘.ui.sticky‘).siblings().remove();$(‘.follow-me‘).siblings().remove();$(‘img.ui.image‘).siblings().remove();
代碼執行完畢之後,就只剩下二維碼的圖片了。然後我們再截屏。不過這樣有一點不好,就是截屏圖片的下方會有大量空白內容。
# -*- coding: utf-8 -*-from selenium import webdriverimport timedef take_screenshot(url, save_fn="capture.png"): # browser = webdriver.Firefox() # Get local session of firefox chromedriver = r"C:\soft\chromedriver2.31_win32\chromedriver.exe" browser = webdriver.Chrome(chromedriver) # browser = webdriver.PhantomJS() browser.set_window_size(1200, 900) browser.get(url) # Load page #將頁面的捲軸拖到最下方,然後再拖回頂部 # browser.execute_script(""" # (function () { # var y = 0; # var step = 100; # window.scroll(0, 0); # # function f() { # if (y < document.body.scrollHeight) { # y += step; # window.scroll(0, y); # setTimeout(f, 100); # } else { # window.scroll(0, 0); # document.title += "scroll-done"; # } # } # # setTimeout(f, 1000); # })(); # """) # # for i in xrange(30): # if "scroll-done" in browser.title: # break # time.sleep(10) #只截取編程派網站右側的二維碼,可以執行這樣一段JQuery代碼:siblings().remove()移除兄弟姐妹元素 browser.execute_script(""" $(‘#main‘).siblings().remove(); $(‘#aside__wrapper‘).siblings().remove(); $(‘.ui.sticky‘).siblings().remove(); $(‘.follow-me‘).siblings().remove(); $(‘img.ui.image‘).siblings().remove(); """) browser.save_screenshot(save_fn) browser.close()if __name__ == "__main__": take_screenshot("http://codingpy.com/article/take-screenshot-of-web-page-using-selenium/")
不同wewbdriver對某些方法的實現不同
Chrome和PhantomJS 的介面差異
抓知乎時的坑,
Chrome用WebElement.text
可以正常得到值,用PhantomJS只能用 WebElement.get_attribute(‘innerHTML‘)
WebDriver.Chrome只能截當前螢幕地區。WebDriver.PhantomJS可以擷取整個頁面的長圖。
其它還有一些坑等待發現
推薦
html2canvas庫
將 DOM 對象繪製到 canvas 中
利用 Python + Selenium 自動化快速
利用 Python + Selenium 實現對頁面的指定元素(可截長圖元素)