用Selenium + ChromeDriver 实现多屏滑动截取+拼接(有源码)
纳尼,我的图表怎么少了。后来问过前端的同学,他说绘制图的时候使用了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 实现多屏滑动截取+拼接(有源码)相关推荐
- selenium 无头模式截屏
原文链接: selenium 无头模式截屏 上一篇: wecode 生日贺卡 flask 服务端 下一篇: wecode 图片查看组件 截取百度首页,保存为图片 砸死ubuntu环境中,可能会出现中文 ...
- python测试脚本截图_Python+selenium实现截图图片并保存截取的图片
这篇文章介绍如何利用Selenium的方法进行截图,在测试过程中,是有必要截图,特别是遇到错误的时候进行截图.在selenium for Python中主要有三个截图方法,我们挑选其中最常用的一种. ...
- Selenium ChromeDriver 截图标记指定元素的方法
phantomjs 是无头浏览器的代表,可以截全屏的图,对于标记元素来说是很简单的;不过最新的 Selenium 版本表示不再支持:所以只能使用其他的代理品; 正好 chrome ,Firefox 等 ...
- 解决selenium + chromedriver模拟登录被淘宝反爬
解决selenium + chromedriver模拟登录被淘宝反爬 问题 使用 selenium + webdriver 模拟淘宝登录时,出现滑动验证码反爬,尝试程序模拟滑动滑块,以及在程序打开的 ...
- ionic4中使用Swiper触屏滑动---心酸路
心酸历程: 积分首页的轮播图,我想做得好一点,按照小谷给的原型图,找到了很不多的实例. 但是实现的过程遇到了很多问题,同时也学到了很多! 2019-7-9: 找人弄源码,想通过上次那样,在网页上找到类 ...
- 手机触屏滑动图片切换插件swiper.js
今天给大家分享一款手机触屏滑动图片切换插件swiper.js是一款swiper手机触屏滑动图片幻灯片,适合各种尺寸.效果图如下: 在线预览 源码下载 实现的代码. html代码: <div ...
- mac 搭建python+selenium+chromedriver环境
mac 搭建python+selenium+chromedriver环境 有关配置默认python3,请查看:https://blog.csdn.net/qq_35098526/article/det ...
- JS 移动端触屏滑动
首页> 程序开发 > web前端 > JavaScript > 正文 JS案例之5--移动端触屏滑动 2014-08-15 0个评论 收藏 我要投稿 移动端 ...
- JS移动客户端--触屏滑动事件 banner图效果
JS移动客户端--触屏滑动事件 移动端触屏滑动的效果其实就是图片轮播,在PC的页面上很好实现,绑定click和mouseover等事件来完成.但是在移动设备上,要实现这种轮播的效果,就需要用到核心的t ...
最新文章
- java遇见的问题分析
- 文章中嵌入代码块_如何在您的文章中嵌入多项选择测验问题
- 部署gogs_可以更快地查阅 Gogs 文档了!
- 阿里巴巴、支付宝员工都在用的知识管理工具,究竟有何特别?
- java根据sessionid获取session
- 一切问题的解决都离不开人
- 《深度学习》李宏毅 -- task2 回归
- 机器学习 Machine Learning- 吴恩达Andrew Ng 第6~10课总结
- netty使用(7)传输一个序列化对象
- java 单例模式(饿汉模式和懒汉模式)
- java读取邮件超大附件_javamail在收邮件时可以得到邮件大小,但是javamail在发邮件时怎么得到邮件大小?...
- 嗅探服务器系统,嗅探服务器
- matlab开始如何设置,MATLAB 2018B: 如何创建快捷方式
- 3D游戏开源引擎分析
- python制作壁纸获取器exe,壁纸采集
- 强烈推荐-这个方法让chrome浏览器拓展程序打包成.crx文件最快?
- 百度网盘Mac版如何分享链接?创建百度网盘 for Mac分享链接的方法
- 前端面试官常问的问题有哪些?(前端面试题总结)
- Java的开发环境、测试环境、生产环境、UAT环境、仿真环境
- Python+IDM实现百度网盘批量下载