利用 Python + Selenium 實現對頁面的指定元素截圖(可截長圖元素)

來源:互聯網
上載者:User

標籤:sleep   特定   screens   一點   利用   col   function   out   obj   

對WebElement

WebDriver.Chrome內建的方法只能對當前視窗截屏,且不能指定特定元素。若是需要截取特定元素或是視窗超過了一屏,就只能另闢蹊徑了。

WebDriver.PhantomJS內建的方法支援對整個網頁截屏。

下面提供幾種思路。

方式一

針對WebDriver.Chrome

通過WebDriver的js指令碼注入功能,曲線救國。

  1. 注入第三方html轉canvas的js庫(見下方推薦)

  2. 擷取元素html源碼

  3. 將html轉換為canvas

  4. 下載canvas

優點: 截取長圖容易實現

缺點: 載入第三方庫耗費時間,轉換原理請參考這篇文章:

將 DOM 對象繪製到 canvas 中

方式二

針對WebDriver.Chrome

截取全圖,自行裁剪、拼接

  1. 擷取元素位置、大小

  2. 擷取視窗大小

  3. 截取包含元素的視窗

  4. 進行相應的裁剪和拼接。

具體演算法思路很清晰,但需要注意的細節較多。這裡就不在贅述。範例程式碼請移步:

[Github]PythonSpiderLibs

優點: 不需太多js工作,python+少量js代碼即可完成

缺點: 拼接等工作會被WebDriver的實現差異、圖片載入速度等因素影響,需多加註意。 在保證品質的情況下,速度較慢

方式三

針對WebDriver.PhantomJS

由於介面實現的差異,PhantomJS相比於Chrome,可以截取到整個網頁。所以擷取指定元素的也就簡單很多

  1. 截取網頁全圖

  2. 裁剪指定元素

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 的介面差異

抓知乎時的坑,

  1. Chrome用WebElement.text可以正常得到值,用PhantomJS只能用 WebElement.get_attribute(‘innerHTML‘)

  2. WebDriver.Chrome只能截當前螢幕地區。WebDriver.PhantomJS可以擷取整個頁面的長圖。

其它還有一些坑等待發現

推薦
  1. html2canvas庫

  2. 將 DOM 對象繪製到 canvas 中

  3. 利用 Python + Selenium 自動化快速

利用 Python + Selenium 實現對頁面的指定元素(可截長圖元素)

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.