功能来源需求。近期产品提出一个小需求,对自家的html截屏定期发送给用户,初到公司觉得小意思啊,之前做过htmltopdf的功能,然后在pdftopng不是就好了。本是其他组的活,那个组最近活比较多,本着相互帮助(zhuangbi)的原则,揽下活。想了想,应该直接html to png就搞定的,google下,果然有现成的轮子。找到一个靠谱的轮子-webkit2png,下载包,啪啪啪敲代码搞定,收工。看看图片

纳尼,我的图表怎么少了。后来问过前端的同学,他说绘制图的时候使用了echart,目前只有Google chrome支持比较好。小意思嘛,指定浏览器不就好了,但是......webkit2png -h 后,悲剧了,它不支持指定浏览器的参数哇。

后面想想,只能用chrome,那不是用Selenium(用于操纵浏览器) + ChromeDriver(chrome浏览器驱动,用于模仿浏览器) 就可以了。继续啪啪啪低头敲代码,结果还可以。

就当我要提交代码时,发现有些图表是长的,就是需要下滑才能截取整个页面,普通的截取只能截当前页。不难嘛,google截取全页面不就好了,结果再次悲剧了,chromedriver的截图只有一页,而对于iedriver和firefox来说就没有这个必要,可以截取整个页面。这这这....

难不倒我,用JS滑动+多次截屏+合并,搞定(参考代码)(这里的JS滑动你要注意是浏览器的滑动还是DIV滑动,我在这里就被坑了。如果用网上的JS滑动不能生效的话,你就得去看DOM结构了,找到那个需要滑动的DIV)

但是上述分屏合并图片代码,还有两个比较致命的问题。

第一是拼接的时候总是精确度不够。图片连接部分要么不全,要么重复。

查明是以下两个原因导致:

1.设置浏览器的高度并不是截图的高度,还需算上浏览器头部高度(宽度是一致的)

2.用selenium打开的chrome 中,总是有安全提示,也会占用一定高度 (关闭它就好了,详见源码)

第二是最后一张图片处理的问题,我需要计算出最好一张图片和前面图片重复的面积,

然后使用图片处理(PIL)对其进行裁剪后加入到前面的图片中。

裁剪高度(remain_h)的是先算出总高度(h),然后对滑动高度(slide_h)取余,即remain_h=h%slide_h。

裁剪crop(0, slide_h-remain_h, 图片长度,图片高度)。

以下是源码(需要安装Selenium+ChromeDriver+PIL)

import os
import time
from PIL import Image
from selenium import webdriverdef capture(base_url, pix_w, pix_h, filename):"""chrome截屏     base_url- 要截屏的url    pix_w- 窗口宽     pix_h- 窗口高    filename-生成截图的文件名     """try:options = webdriver.ChromeOptions()# 去除安全提示options.add_argument('disable-infobars')driver = webdriver.Chrome('/Users/apple/Downloads/chromedriver', chrome_options=options)# 算上浏览器高度driver.set_window_size(pix_w, pix_h+98)driver.get(base_url)time.sleep(5)img_list = []i = 0while True:# 滚动高度scroll_h = str(i*pix_h)js = """document.getElementsByClassName("multiscreen-detail-page")[0].scrollTop=%s""" % (scroll_h)driver.execute_script(js)# 获取滚动高度和实际高度js1 = """return document.getElementsByClassName("multiscreen-detail-page")[0].scrollHeight.toString() +',' + document.getElementsByClassName("multiscreen-detail-page")[0].scrollTop.toString()"""js1_result = driver.execute_script(js1)real_scroll_h, real_top = js1_result.split(',')[0], js1_result.split(',')[1]#real_scroll_h, real_top 是当前滚动条长度和当前滚动条的top,作为是否继续执行的依据,# 由于存在滚动条向下拉动后会加载新内容的情况,所以需要以下的判断#如果这次设置的top成功,则继续滚屏if real_top == str(i*pix_h):i += 1driver.save_screenshot('/Users/apple/static/test-'+filename + str(i)+'.png')img_list.append('/Users/apple/static/test-'+filename + str(i)+'.png')last_t = real_topelse:#如果本次设置失败,看这次的top和上一次记录的top值是否相等,# 相等则说明没有新加载内容,且已到页面底,跳出循环if real_top != last_t:if int(real_scroll_h) < pix_h:breaklast_t = real_top# breakelse:img_filename = '/Users/apple/static/test-' + filename + str(i+1)+'.png'driver.save_screenshot(img_filename)# img_list.append(img_filename)# img_list.append('/Users/apple/static/test-' + filename + str(i+1)+'.png')# 算出截取位置try:y = (i+1)*pix_h - int(real_scroll_h)# region = (0, y*2, pix_w*2, pix_h*2)region = (0, y, pix_w, pix_h)img = Image.open(img_filename)cropImg = img.crop(region)cropImg.save(img_filename)img_list.append(img_filename)# 有可能会超出范围,如果存在一个图标有下拉的情况下就不截图了(也不做处理)except Exception as e:os.remove(img_filename)print(e)breakimage_merge(img_list, "/Users/apple/static", filename+'.png')except Exception as e:raisedef image_merge(images, output_dir, output_name='merge.jpg', restriction_max_width=None, restriction_max_height=None):"""垂直合并多张图片images - 要合并的图片路径列表ouput_dir - 输出路径output_name - 输出文件名restriction_max_width - 限制合并后的图片最大宽度,如果超过将等比缩小restriction_max_height - 限制合并后的图片最大高度,如果超过将等比缩小"""# def image_resize(img, size=(1500, 1100)):def image_resize(img, size=(1960, 1080)):"""调整图片大小"""try:if img.mode not in ('L', 'RGB'):img = img.convert('RGB')img = img.resize(size)except Exception as e:passreturn imgmax_width = 0total_height = 0# 计算合成后图片的宽度(以最宽的为准)和高度for img_path in images:if os.path.exists(img_path):img = Image.open(img_path)width, height = img.sizeif width > max_width:max_width = widthtotal_height += height# 产生一张空白图new_img = Image.new('RGB', (max_width, total_height), 255)# 合并x = y = 0for img_path in images:if os.path.exists(img_path):img = Image.open(img_path)width, height = img.sizenew_img.paste(img, (x, y))y += heightif restriction_max_width and max_width >= restriction_max_width:# 如果宽带超过限制# 等比例缩小ratio = restriction_max_height / float(max_width)max_width = restriction_max_widthtotal_height = int(total_height * ratio)new_img = image_resize(new_img, size=(max_width, total_height))if restriction_max_height and total_height >= restriction_max_height:# 如果高度超过限制# 等比例缩小ratio = restriction_max_height / float(total_height)max_width = int(max_width * ratio)total_height = restriction_max_heightnew_img = image_resize(new_img, size=(max_width, total_height))if not os.path.exists(output_dir):os.makedirs(output_dir)save_path = '%s/%s' % (output_dir, output_name)new_img.save(save_path)for img_path in images:os.remove(img_path)return save_pathurl='http://www.baidu.com'
capture(url, 1920, 906, '5')# 生产环境应该是1080的,mac是980的,去除了上下边。所以应该是1920,1010.

到此,基本解决问题了,下班回家带娃,此次事件证明简单需求可能会有很多你意想不到的坑在等着你,揽活需谨慎!!!

再说句,其实这个坑算是前端埋下的(先甩个锅),因为他用了只有Chrome支持效果好的echart(虽然效果好看,可能也找不到更好的库了),才导致了这么多的事。在此,还是提醒下各位码农,在能同样实现功能的情况下,尽可能的做到兼容哇!!!

用Selenium + ChromeDriver 实现多屏滑动截取+拼接(有源码)相关推荐

  1. selenium 无头模式截屏

    原文链接: selenium 无头模式截屏 上一篇: wecode 生日贺卡 flask 服务端 下一篇: wecode 图片查看组件 截取百度首页,保存为图片 砸死ubuntu环境中,可能会出现中文 ...

  2. python测试脚本截图_Python+selenium实现截图图片并保存截取的图片

    这篇文章介绍如何利用Selenium的方法进行截图,在测试过程中,是有必要截图,特别是遇到错误的时候进行截图.在selenium for Python中主要有三个截图方法,我们挑选其中最常用的一种. ...

  3. Selenium ChromeDriver 截图标记指定元素的方法

    phantomjs 是无头浏览器的代表,可以截全屏的图,对于标记元素来说是很简单的;不过最新的 Selenium 版本表示不再支持:所以只能使用其他的代理品; 正好 chrome ,Firefox 等 ...

  4. 解决selenium + chromedriver模拟登录被淘宝反爬

    解决selenium + chromedriver模拟登录被淘宝反爬 问题 ​使用 selenium + webdriver 模拟淘宝登录时,出现滑动验证码反爬,尝试程序模拟滑动滑块,以及在程序打开的 ...

  5. ionic4中使用Swiper触屏滑动---心酸路

    心酸历程: 积分首页的轮播图,我想做得好一点,按照小谷给的原型图,找到了很不多的实例. 但是实现的过程遇到了很多问题,同时也学到了很多! 2019-7-9: 找人弄源码,想通过上次那样,在网页上找到类 ...

  6. 手机触屏滑动图片切换插件swiper.js

    今天给大家分享一款手机触屏滑动图片切换插件swiper.js是一款swiper手机触屏滑动图片幻灯片,适合各种尺寸.效果图如下: 在线预览   源码下载 实现的代码. html代码: <div ...

  7. mac 搭建python+selenium+chromedriver环境

    mac 搭建python+selenium+chromedriver环境 有关配置默认python3,请查看:https://blog.csdn.net/qq_35098526/article/det ...

  8. JS 移动端触屏滑动

    首页> 程序开发 > web前端 > JavaScript > 正文 JS案例之5--移动端触屏滑动 2014-08-15     0个评论      收藏  我要投稿 移动端 ...

  9. JS移动客户端--触屏滑动事件 banner图效果

    JS移动客户端--触屏滑动事件 移动端触屏滑动的效果其实就是图片轮播,在PC的页面上很好实现,绑定click和mouseover等事件来完成.但是在移动设备上,要实现这种轮播的效果,就需要用到核心的t ...

最新文章

  1. java遇见的问题分析
  2. 文章中嵌入代码块_如何在您的文章中嵌入多项选择测验问题
  3. 部署gogs_可以更快地查阅 Gogs 文档了!
  4. 阿里巴巴、支付宝员工都在用的知识管理工具,究竟有何特别?
  5. java根据sessionid获取session
  6. 一切问题的解决都离不开人
  7. 《深度学习》李宏毅 -- task2 回归
  8. 机器学习 Machine Learning- 吴恩达Andrew Ng 第6~10课总结
  9. netty使用(7)传输一个序列化对象
  10. java 单例模式(饿汉模式和懒汉模式)
  11. java读取邮件超大附件_javamail在收邮件时可以得到邮件大小,但是javamail在发邮件时怎么得到邮件大小?...
  12. 嗅探服务器系统,嗅探服务器
  13. matlab开始如何设置,MATLAB 2018B: 如何创建快捷方式
  14. 3D游戏开源引擎分析
  15. python制作壁纸获取器exe,壁纸采集
  16. 强烈推荐-这个方法让chrome浏览器拓展程序打包成.crx文件最快?
  17. 百度网盘Mac版如何分享链接?创建百度网盘 for Mac分享链接的方法
  18. 前端面试官常问的问题有哪些?(前端面试题总结)
  19. Java的开发环境、测试环境、生产环境、UAT环境、仿真环境
  20. Python+IDM实现百度网盘批量下载

热门文章

  1. MSP432驱动舵机串口输出角度
  2. oracle 表分区详解
  3. 快手伪原创视频热门 哪里有手机修改视频md5软件
  4. 童年经典回忆 | 从零开始带大家用Python撸一个魔塔小游戏呀(2)
  5. SimpleDateFormat
  6. Ansoft Links 3.0 (EDA接口程序)
  7. 【rzxt】笔者支招:AMD双核电脑安装补丁后的问题
  8. VS 2005中文版用户请谨慎使用我提供的Atlas Xml Scripts Intellisense方法
  9. FreeBSD安装(虚拟机)version:13.1
  10. HTTP:Web主机托管