使用python实现对元素的长截图功能


Posted in Python onNovember 14, 2019

一.目标

浏览网页的时候,看见哪个元素,就能截取哪个元素当图片,不管那个元素有多长

使用python实现对元素的长截图功能 

二.所用工具和第三方库

python ,PIL,selenium

pycharm

三.代码部分

长截图整体思路:

1.获取元素

2.移动,截图,移动,截图,直到抵达元素的底部

3.把截图按照元素所在位置切割,在所有图片中只保留该元素

4.拼接

如果driver在环境变量中,那么不用指定路径

b=webdriver.Chrome(executable_path=r"C:\Users\Desktop\chromedriver.exe")#指定一下driver
b.get("https://www.w3school.com.cn/html/html_links.asp")
b.maximize_window()#最大化窗口

打开网站

使用python实现对元素的长截图功能 

我们可以看见一个ID为maincontent的元素,宽度为850PX,长度为3828PX,这个长度必须使用才能长截图才能完整截下来

el=b.find_element_by_id("maincontent")#找到元素

我们还需要一个重要的参数,就是你电脑一次能截取多高的像素

先用下图代码获取一个图片

#fp为存放图片的地址
b.get_screenshot_as_file(fp)

使用python实现对元素的长截图功能 

也就是说用我电脑上截图的默认高度为614像素

所以我设置一个变量:

sc_hight=614

然后设置一下其他变量

count = int(el.size["height"] / sc_hight) # 元素的高度除以你每次截多少就是次数
  start_higth = el.location["y"] # 元素的初始高度
  max_px = start_higth + (count - 1) * sc_hight # for循环中最大的px
  last_px = el.size["height"] + start_higth - sc_hight # 元素最底部的位置
  surplus_px = last_px - max_px # 剩余的边的高度
  img_path = [] # 用来存放图片地址

注释:

1.count为元素的高度/每次截取的高度,比如这次实例中元素高度为3828PX,我每次截614px,需要6.2次,int之后变成6,也就是截6次,还剩一点,那一点后面再说

2.start_higth为初始高度,这个没有什么可说的

3.max_px为循环结束后,到达的高度

4.last_px为元素最底部的高度

5.surplus_px就是移动6次后,还没有截取的高度

屏幕每次移动,移动sc_hight个像素,初始位置为(0,元素的Y值)

for i in range(0, count):
    js = "scrollTo(0,%s)" % (start_higth + i * sc_hight) # 用于移动滑轮,每次移动614px,初始值是元素的初始高度
    b.execute_script(js) # 执行js
    time.sleep(0.5)
    fp = r"C:\Users\wdj\Desktop\%s.png" % i # 图片地址,运行的话,改一下
    b.get_screenshot_as_file(fp) # 屏幕截图,这里是截取是完整的网页图片,你可以打断点看一下图片
    img = Image.open(fp=fp)
    img2 = img.crop((el.location["x"], 0, el.size["width"] + el.location["x"], sc_hight)) # 剪切图片
    img2.save(fp) # 保存图片,覆盖完整的网页图片
    img_path.append(fp) # 添加图片路径
    time.sleep(0.5)
    print(js)
  else:
    js = "scrollTo(0,%s)" % last_px # 滚动到最后一个位置
    b.execute_script(js)
    fp = r"C:\Users\wdj\Desktop\last.png"
    b.get_screenshot_as_file(fp)
    img = Image.open(fp=fp)
    print((el.location["x"], sc_hight - surplus_px, el.size["width"] + el.location["x"], sc_hight))
    img2 = img.crop((el.location["x"], sc_hight - surplus_px, el.size["width"] + el.location["x"], sc_hight))
    img2.save(fp)
    img_path.append(fp)
    print(js)

上面是把该元素的在页面都截完,并且剪切,把图片保存的路径放入img_path

最后一步:把所有截图都贴到新创建的图片中

new_img = Image.new("RGB", (el.size["width"], el.size["height"])) # 创建一个新图片,大小为元素的大小
  k = 0
  for i in img_path:
    tem_img = Image.open(i)
    new_img.paste(tem_img, (0, sc_hight * k)) # 把图片贴上去,间隔一个截图的距离
    k += 1
  else:
    new_img.save(r"C:\Users\wdj\Desktop\test.png") # 保存

运行效果图:

使用python实现对元素的长截图功能 

说明完整的截取下来了

补充优化:

如果是个小元素怎么办,不用长截图就能截取的那种

因为很简单我就直接贴代码了

start_higth = el.location["y"]
  js = "scrollTo(0,%s)" % (start_higth)
  b.execute_script(js) # 执行js
  time.sleep(0.5)
  fp = r"C:\Users\wdj\Desktop\test.png" # 图片地址,运行的话,改一下
  b.get_screenshot_as_file(fp)
  img = Image.open(fp=fp)
  img2 = img.crop((el.location["x"], 0, el.size["width"] + el.location["x"], el.size["height"])) # 剪切图片
  img2.save(fp)

效果如下:

使用python实现对元素的长截图功能 

完整代码:

from selenium import webdriver
from PIL import Image
import time
def short_sc(el,b):
  start_higth = el.location["y"]
  js = "scrollTo(0,%s)" % (start_higth)
  b.execute_script(js) # 执行js
  time.sleep(0.5)
  fp = r"C:\Users\wdj\Desktop\test.png" # 图片地址,运行的话,改一下
  b.get_screenshot_as_file(fp)
  img = Image.open(fp=fp)
  img2 = img.crop((el.location["x"], 0, el.size["width"] + el.location["x"], el.size["height"])) # 剪切图片
  img2.save(fp)
def long_sc(el,b):
  count = int(el.size["height"] / sc_hight) # 元素的高度除以你每次截多少就是次数
  start_higth = el.location["y"] # 元素的初始高度
  max_px = start_higth + (count - 1) * sc_hight # for循环中最大的px
  last_px = el.size["height"] + start_higth - sc_hight # 元素最底部的位置
  surplus_px = last_px - max_px # 剩余的边的高度
  img_path = [] # 用来存放图片地址
  for i in range(0, count):
    js = "scrollTo(0,%s)" % (start_higth + i * sc_hight) # 用于移动滑轮,每次移动614px,初始值是元素的初始高度
    b.execute_script(js) # 执行js
    time.sleep(0.5)
    fp = r"C:\Users\wdj\Desktop\%s.png" % i # 图片地址,运行的话,改一下
    b.get_screenshot_as_file(fp) # 屏幕截图,这里是截取是完整的网页图片,你可以打断点看一下图片
    img = Image.open(fp=fp)
    img2 = img.crop((el.location["x"], 0, el.size["width"] + el.location["x"], sc_hight)) # 剪切图片
    img2.save(fp) # 保存图片,覆盖完整的网页图片
    img_path.append(fp) # 添加图片路径
    time.sleep(0.5)
    print(js)
  else:
    js = "scrollTo(0,%s)" % last_px # 滚动到最后一个位置
    b.execute_script(js)
    fp = r"C:\Users\wdj\Desktop\last.png"
    b.get_screenshot_as_file(fp)
    img = Image.open(fp=fp)
    print((el.location["x"], sc_hight - surplus_px, el.size["width"] + el.location["x"], sc_hight))
    img2 = img.crop((el.location["x"], sc_hight - surplus_px, el.size["width"] + el.location["x"], sc_hight))
    img2.save(fp)
    img_path.append(fp)
    print(js)
  new_img = Image.new("RGB", (el.size["width"], el.size["height"])) # 创建一个新图片,大小为元素的大小
  k = 0
  for i in img_path:
    tem_img = Image.open(i)
    new_img.paste(tem_img, (0, sc_hight * k)) # 把图片贴上去,间隔一个截图的距离
    k += 1
  else:
    new_img.save(r"C:\Users\wdj\Desktop\test.png") # 保存
b=webdriver.Chrome(executable_path=r"C:\Users\wdj\Desktop\chromedriver.exe")#指定一下driver
b.get("https://www.w3school.com.cn/html/html_links.asp")
b.maximize_window()#最大化窗口
# b.get_screenshot_as_file(fp)
sc_hight=614#你屏幕截图默认的大小,可以去截一张,去画图里面看看是多少像素,我这里是614像素
# b.switch_to.frame(b.find_element_by_xpath('//*[@id="intro"]/iframe'))
el=b.find_element_by_id("maincontent")#找到元素
if el.size["height"]>sc_hight:
  long_sc(el,b)
else:
  short_sc(el,b)

完整代码

PS:

有些特殊情况,比如截取的元素在iframe中,直接用driver.switch_to.frame(iframe元素)即可

或者不是iframe,但是元素有overflow属性,直接用JS把他的overflow去掉就行

Python 相关文章推荐
判断python字典中key是否存在的两种方法
Aug 10 Python
Python中super函数用法实例分析
Mar 18 Python
python里 super类的工作原理详解
Jun 19 Python
django 配置阿里云OSS存储media文件的例子
Aug 20 Python
python 实现dict转json并保存文件
Dec 05 Python
Python模块相关知识点小结
Mar 09 Python
关于win10在tensorflow的安装及在pycharm中运行步骤详解
Mar 16 Python
django使用F方法更新一个对象多个对象字段的实现
Mar 28 Python
Python第三方包之DingDingBot钉钉机器人
Apr 09 Python
Python json格式化打印实现过程解析
Jul 21 Python
如何解决python多种版本冲突问题
Oct 13 Python
Python用户自定义异常的实现
Dec 25 Python
Pycharm创建项目时如何自动添加头部信息
Nov 14 #Python
python3实现单目标粒子群算法
Nov 14 #Python
python socket 聊天室实例代码详解
Nov 14 #Python
python中dict()的高级用法实现
Nov 13 #Python
python实现的多任务版udp聊天器功能案例
Nov 13 #Python
利用python实现PSO算法优化二元函数
Nov 13 #Python
使用python制作一个解压缩软件
Nov 13 #Python
You might like
玩家交还《星际争霸》原始码光盘 暴雪报以厚礼
2017/05/05 星际争霸
smarty中先strip_tags过滤html标签后truncate截取文章运用
2010/10/25 PHP
php生成zip压缩文件的方法详解
2013/06/09 PHP
php读取csv数据保存到数组的方法
2015/01/03 PHP
PHP中如何防止外部恶意提交调用ajax接口
2016/04/11 PHP
PHPExcel实现表格导出功能示例【带有多个工作sheet】
2018/06/13 PHP
js 匿名调用实现代码
2009/06/19 Javascript
javascript的onchange事件与jQuery的change()方法比较
2009/09/28 Javascript
一些常用的JavaScript函数(json)附详细说明
2011/05/25 Javascript
jQuery.Validate验证库的使用介绍
2013/04/26 Javascript
jQuery.fn和jQuery.prototype区别介绍
2013/10/05 Javascript
详解JavaScript中的4种类型识别方法
2015/09/14 Javascript
JS Attribute属性操作详解
2016/05/19 Javascript
基于jQuery实现表格的查看修改删除
2016/08/01 Javascript
jQuery日程管理插件fullcalendar使用详解
2017/01/07 Javascript
vue2.0使用swiper组件实现轮播效果
2017/11/27 Javascript
JavaScript实现二叉树定义、遍历及查找的方法详解
2017/12/20 Javascript
Vuejs+vue-router打包+Nginx配置的实例
2018/09/20 Javascript
微信小程序中为什么使用var that=this
2019/08/27 Javascript
如何换个角度使用VUE过滤器详解
2019/09/11 Javascript
基于layui轮播图满屏是高度自适应的解决方法
2019/09/16 Javascript
微信小程序picker组件两列关联使用方式
2020/10/27 Javascript
python中matplotlib的颜色及线条控制的示例
2018/03/16 Python
TensorFlow实现指数衰减学习率的方法
2020/02/05 Python
python 用opencv实现图像修复和图像金字塔
2020/11/27 Python
Python项目打包成二进制的方法
2020/12/30 Python
HTML5移动端手机网站开发流程
2016/04/25 HTML / CSS
HTML5实现文件断点续传的方法
2017/01/04 HTML / CSS
世界上最全面的草药补充剂和顶级品牌维生素网站:HerbsPro
2019/01/20 全球购物
英国领先的在线高尔夫商店:Gamola Golf
2019/11/16 全球购物
工商管理毕业生推荐信
2013/12/24 职场文书
体育专业个人求职信范文
2013/12/27 职场文书
乡镇党委书记第三阶段个人整改措施
2014/09/16 职场文书
2014国庆黄金周超市促销活动方案
2014/09/21 职场文书
研究生导师评语
2014/12/31 职场文书
Nginx域名转发使用场景代码实例
2021/03/31 Servers