对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. 裁剪指定元素

  1. driver = webdriver.Chrome()
  2. driver.get('http://stackoverflow.com/')
  3. driver.save_screenshot('screenshot.png')
  4.  
  5. left = element.location['x']
  6. top = element.location['y']
  7. right = element.location['x'] + element.size['width']
  8. bottom = element.location['y'] + element.size['height']
  9.  
  10. im = Image.open('screenshot.png')
  11. im = im.crop((left, top, right, bottom))
  12. im.save('screenshot.png')

优点: 实现简单

缺点: 对于高度太高的页面会导致文件过大,处理会有问题,我测试的最大图片尺寸是12.8M。

解决图片加载不完整的问题

参考: 利用 Python + Selenium 自动化快速截图

我们先在首页上执行一段 JavaScript 脚本,将页面的滚动条拖到最下方,然后再拖回顶部,最后才截图。这样可以解决像上面那种按需加载图片的情况。

  1. # -*- coding: utf-8 -*-
  2.  
  3. from selenium import webdriver
  4. import time
  5.  
  6. def take_screenshot(url, save_fn="capture.png"):
  7. # browser = webdriver.Firefox() # Get local session of firefox
  8. #谷歌浏览器截取当前窗口网页
  9. chromedriver = r"C:\soft\chromedriver2.31_win32\chromedriver.exe"
  10. browser = webdriver.Chrome(chromedriver)
  11. #phantomjs截取整张网页
  12. # browser = webdriver.PhantomJS()
  13. browser.set_window_size(1200, 900)
  14. browser.get(url) # Load page
  15. #将页面的滚动条拖到最下方,然后再拖回顶部
  16. browser.execute_script("""
  17. (function () {
  18. var y = 0;
  19. var step = 100;
  20. window.scroll(0, 0);
  21.  
  22. function f() {
  23. if (y < document.body.scrollHeight) {
  24. y += step;
  25. window.scroll(0, y);
  26. setTimeout(f, 100);
  27. } else {
  28. window.scroll(0, 0);
  29. document.title += "scroll-done";
  30. }
  31. }
  32.  
  33. setTimeout(f, 1000);
  34. })();
  35. """)
  36.  
  37. for i in xrange(30):
  38. if "scroll-done" in browser.title:
  39. break
  40. time.sleep(10)
  41.  
  42. browser.save_screenshot(save_fn)
  43. browser.close()
  44.  
  45. if __name__ == "__main__":
  46.  
  47. take_screenshot("http://codingpy.com")

如何截取某个网页元素

有时候我们只想截取某个网页元素的图片呢?比如说会动态变化的验证码。本来 Selenium 也提供了对元素截图的支持,只要在选中的元素上调用其 screenshot() 方法即可。

但是在实际使用时却遇到了 Unrecognized command 这个异常,经过一段时间检索也没有找到解决办法。所以,只能曲线救国,利用 Selenium 执行JS代码,将页面上不需要的元素一一删除,只保留我们希望留下的元素,然后再利用上面的窗口截屏功能。

例如,如果我们只截取编程派网站右侧的二维码,可以执行这样一段JQuery代码:

  1. $('#main').siblings().remove();
  2. $('#aside__wrapper').siblings().remove();
  3. $('.ui.sticky').siblings().remove();
  4. $('.follow-me').siblings().remove();
  5. $('img.ui.image').siblings().remove();

代码执行完毕之后,就只剩下二维码的图片了。然后我们再截屏。不过这样有一点不好,就是截屏图片的下方会有大量空白内容。

  • 代码
  1. # -*- coding: utf-8 -*-
  2.  
  3. from selenium import webdriver
  4. import time
  5.  
  6. def take_screenshot(url, save_fn="capture.png"):
  7. # browser = webdriver.Firefox() # Get local session of firefox
  8. chromedriver = r"C:\soft\chromedriver2.31_win32\chromedriver.exe"
  9. browser = webdriver.Chrome(chromedriver)
  10. # browser = webdriver.PhantomJS()
  11. browser.set_window_size(1200, 900)
  12. browser.get(url) # Load page
  13. #将页面的滚动条拖到最下方,然后再拖回顶部
  14. # browser.execute_script("""
  15. # (function () {
  16. # var y = 0;
  17. # var step = 100;
  18. # window.scroll(0, 0);
  19. #
  20. # function f() {
  21. # if (y < document.body.scrollHeight) {
  22. # y += step;
  23. # window.scroll(0, y);
  24. # setTimeout(f, 100);
  25. # } else {
  26. # window.scroll(0, 0);
  27. # document.title += "scroll-done";
  28. # }
  29. # }
  30. #
  31. # setTimeout(f, 1000);
  32. # })();
  33. # """)
  34. #
  35. # for i in xrange(30):
  36. # if "scroll-done" in browser.title:
  37. # break
  38. # time.sleep(10)
  39.  
  40. #只截取编程派网站右侧的二维码,可以执行这样一段JQuery代码:siblings().remove()移除兄弟姐妹元素
  41. browser.execute_script("""
  42. $('#main').siblings().remove();
  43. $('#aside__wrapper').siblings().remove();
  44. $('.ui.sticky').siblings().remove();
  45. $('.follow-me').siblings().remove();
  46. $('img.ui.image').siblings().remove();
  47. """)
  48.  
  49. browser.save_screenshot(save_fn)
  50. browser.close()
  51.  
  52. if __name__ == "__main__":
  53.  
  54. 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 实现对页面的指定元素截图(可截长图元素)的更多相关文章

  1. Python + Selenium 实现对页面的指定元素截图(可截长图元素)【转载】

    先在首页上执行一段 JavaScript 脚本,将页面的滚动条拖到最下方,然后再拖回顶部,最后才截图.这样可以解决那种按需加载图片的情况 以下代码为转载别处博客改造后的,有chrome和ff两种浏览器 ...

  2. Python+Selenium自动化-定位页面元素的八种方法

    Python+Selenium自动化-定位页面元素的八种方法   本篇文字主要学习selenium定位页面元素的集中方法,以百度首页为例子. 0.元素定位方法主要有: id定位:find_elemen ...

  3. Python+Selenium自动化-获取页面信息

    Python+Selenium自动化-获取页面信息   1.获取页面title title:获取当前页面的标题显示的字段 from selenium import webdriver import t ...

  4. selenium截屏操作(也支持截长图)

    1.常用的可能是谷歌和火狐做自动化在抛异常的时候可以截屏保存 from selenium import webdriver br=webdriver.Chrome() br.maximize_wind ...

  5. 利用python+selenium在pycharm下进行页面登陆的半自动测试

    很久没有写了,现在正式入职,准备好好干,加油! 我的第一个较正式的测试代码: from selenium import webdriverimport unittestimport sysimport ...

  6. 在CentOS下利用Python+selenium获取腾讯首页的今日话题。

    1.安装依赖包 yum install wget firefox gcc zlib zlib-devel Xvfb 2.安装setuptools 官网地址:https://pypi.python.or ...

  7. Python+selenium点击网页上指定坐标

    from selenium import webdriver from selenium.webdriver.common.action_chains import ActionChains dr = ...

  8. python selenium 多个页面对象类使用同一个webdriver(即只打开一个浏览器窗口)

    1 class BasePage(): 2 """selenium基类""" 3 4 def __init__(self, driver=N ...

  9. [Chrome Headless + Python] 截长图 (Take Full-page Screenshot)

    # -*- coding: utf-8 -*- import time import os from selenium import webdriver from selenium.webdriver ...

随机推荐

  1. MR for Baum-Welch algorithm

    The Baum-Welch algorithm is commonly used for training a Hidden Markov Model because of its superior ...

  2. windows c/c++ 代码运行时间,毫秒级

    #pragma once /* //计算代码段运行时间的类 // */ #include <iostream> #ifndef ComputeTime_h #define ComputeT ...

  3. RecyclerView 与 Scrollview 搭配使用的两个坑

    RecyclerView & Scrollview & wrap_content RecyclerView wrap_content 用android.support.v4.widge ...

  4. Ubuntu 14.04 32位 JDK+ADT Bundle+NDK安装

    1. 安装JDK tar或GUI解压jdk-8u25-linux-i586.tar.gz 编辑/etc/environment文件 CLASSPATH="/home/zhouwei/jdk1 ...

  5. 修改input属性placeholder的样式

    <!doctype html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  6. iOS 博客资源精选

    摘要:记录一些网上非常牛的人写的博文.收藏起来. 以备日后需要时学习备用. 1:iOS中UIWebView的Javascript与Objective-C通信 http://imchao.net/201 ...

  7. javaScript(1)---概述

    javaScript(1)---概述 学习要点: 1.什么是JavaScript 2.JavaScript特点 3.JavaScript历史 4.JavaScript核心 JavaScript诞生于1 ...

  8. ]Java 5|6 并发包介绍

    ava.util.concurrent 包含许多线程安全.测试良好.高性能的并发构建块.不客气地说,创建 java.util.concurrent 的目的就是要实现 Collection 框架对数据结 ...

  9. 数据库中row_number()、rank()、dense_rank() 的区别

    row_number的用途非常广泛,排序最好用它,它会为查询出来的每一行记录生成一个序号,依次排序且不会重复,注意使用row_number函数时必须要用over子句选择对某一列进行排序才能生成序号. ...

  10. Ocelot中文文档-负载均衡

    Ocelot能通过可用的下游服务对每个ReRoute进行负载平衡. 这意味着您可以扩展您的下游服务,并且Ocelot可以有效地使用它们. 可用的负载均衡器的类型是: LeastConnection - ...