美文网首页python学习程序员首页投稿(暂停使用,暂停投稿)
利用 Python + Selenium 实现对页面的指定元素截

利用 Python + Selenium 实现对页面的指定元素截

作者: 斯科特安 | 来源:发表于2016-08-09 00:21 被阅读20608次

    斯科特安的时间

    对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 自动化快速截图](http://codingpy.com/article/take-screenshot-of-web-page-using-selenium/)
    
    我们先在首页上执行一段 JavaScript 脚本,将页面的滚动条拖到最下方,然后再拖回顶部,最后才截图。这样可以解决像上面那种按需加载图片的情况。
    
    from selenium import webdriver
    import time
    
    def take_screenshot(url, save_fn="capture.png"):
        browser = webdriver.Firefox() # Get local session of firefox
        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")
    
    
    

    不同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 自动化快速截图

    相关文章

      网友评论

      • 千里馬:看了这篇文章收获挺多,但我碰在工作中碰到个问题不知能否解决?我需要截图的网站为:http://sgxxxt.mohurd.gov.cn/Public/AccidentList.aspx 但我无论用PJ截图还是浏览器截图,都只能截到60%~70%的位置。可能图片太长,但截的大小也才2M不到。如果采用文中方法二,也得是先截全图再裁剪。可能这就是某种坑吧,希望得到解答
      • 々喥:解决图片加载不完整的问题的实现方法,我使用的是python2.7,selenium3.0.2, FF47.0.1,Chrome51, IE11,发现使用楼主的方法IE可以截全屏图(部分页面还是未加载出来),但是FF和Chrome只能截第一屏的图,不知道什么原因导致?另外把启动浏览器的语句换成启动PhantomJS,可以正常截全屏而且页面内容能够完全显示。
        一整包辣条::flushed: 文章中说了火狐和谷歌的只能截取一个页面的啊,PJ才能截取真个网页的

      本文标题:利用 Python + Selenium 实现对页面的指定元素截

      本文链接:https://www.haomeiwen.com/subject/ksnrsttx.html