selenium是最广泛使用的开源Web UI自动化测试套件之一。本文中使用selenium的PythonSKD,通过代码段完成对selenium的操作。
html2canvas是一个js库,可以实现在浏览器上截取网页或其一部分的“屏幕快照”。总体思路是通过在服务端搭建chromedriver环境,利用selenium实现打开网页,运行js等一系列动作。然后通过注入html2convas的js代码,完成获取当前页浏览器任意dom元素图片。通过这种方式,可以在服务端截取任意网页区域。本文主要介绍在Linux环境下通过各种工具的组合,实现截取任意区域生成图片的方法,其他系统下方法类似。
环境准备
chromedriver 安装
首先需要安装浏览器内核环境,可以在官网https://chromedriver.chromium.org下载需要的版本。如果Linux没有中文字体,需要安装中文字体,避免网页乱码。
selenium 安装
pip install selenium
html2canvas
可以访问https://html2canvas.hertzen.com/查看html2canvas的使用方法
运行方法
1初始化
加载浏览器环境,打开网页。如果chromedriver没有在系统PATH下,需要为webdriver.Chrome()添加executable_path参数,指定chromedriver路径。import timefrom selenium import webdriver# chrome 参数chrome_options = webdriver.ChromeOptions()chrome_options.add_argument('--headless')chrome_options.add_argument('--no-sandbox')chrome_options.add_argument('--disable-dev-shm-usage')driver = webdriver.Chrome(chrome_options=chrome_options)# 加载网站driver.get("https://github.com/trending")time.sleep(1)
2
注入脚本
首先需要引入html2canvas的js库。这里通过创建一个script标签,追加到head中,实现html2canvas。html2canvas = """var s=window.document.createElement('script');s.src='https://html2canvas.hertzen.com/dist/html2canvas.min.js';window.document.head.appendChild(s);"""driver.execute_script(html2canvas)time.sleep(1)
然后根据实际情况,获取dom元素,生成dom元素的图片数据。这里使用了html2canvas的方法,当转换canvas成功后,向body中添加一个含图片数据的元素。该元素可以是任意元素,主要用于存储图片数据。由于html2canvas()函数无法立即将图片数据以返回值的形式传递到python的execute_script()函数。所以通过共享一个dom元素,实现图片数据传递。
buildImage = """html2canvas(document.querySelector('#side_nav')).then(canvas => { data = canvas.toDataURL('image/jpeg', 0.98); var input = document.createElement('input'); input.setAttribute('type', 'text'); input.setAttribute('id', 'html2canvas_data'); input.setAttribute('value', data); document.body.appendChild(input)});return data;"""driver.execute_script(buildImage)time.sleep(1)
最后获取图片信息。读取上一步中生成的id为html2canvas_data元素中存储的图片数据。execute_script()函数的返回值即为图片的base64数据。
imageData = """return document.getElementById('#html2canvas_data').getAttribute('value');"""data = driver.execute_script(imageData)
退出chrome
driver.quit()
3
图片生成
上一步中,最后一个js执行的返回结果为图片的base64值。通过base64解码,便可以得到图片。这里需要注意的是返回值中的base64结果中会包含一段图片信息数据:data:image/jpeg;base64,。解码时需要先移除,再进行转码。 注意- 执行每一条js后,需要增加延时,保证js执行成功。也可以使用selenium提供的显性等待函数WebDriverWait,完成监听元素加载状态。
- 加载html2canvas.js库时,若网站设置了安全策略,如跨域、域限制等策略,需要想方法绕过,再加载js
- 实际应用时,可将js下载到内网,加快js加载速度
实际应用时,可能会出现driver.quit()后,chromdriver进程仍然存在,需要手动kill
集成Docker
将上述所有需要的软件放入docker中。当有新的环境需要时,不必再次安装,同时也可以避免环境差异导致的意外的问题。
如果业务有需求,将上述图片生成方法,结合自身业务需求,在Docker中完成业务实现,从而提供一个可以生成符合业务需求的浏览器截屏服务。例如建立一个http服务,通过传入网页地址与对应的dom元素,返回对应dom元素的图片数据。下面是基于已有的chromedriver镜像robcherry/docker-chromedriver,制作的一个简单的可以运行浏览器截屏程序的环境。在chromedriver的基础上,添加字体库,安装selenium。FROM robcherry/docker-chromedriverCOPY chinese /usr/share/fonts/chineseRUN curl https://bootstrap.pypa.io/get-pip.py -o /tmp/get-pip.py && \ python /tmp/get-pip.py && \ pip install selenium && \ mkfontscale && mkfontdir && fc-cache -fvCMD ["/usr/local/bin/supervisord", "-c", "/etc/supervisord.conf"]
其中chinese是字体目录,可以使用Windows系统下的字体目录中的字体文件。然后生成镜像:
docker build -t demo/html2canvas .
最后将上面的python程序,挂载到容器内,在容器内运行,查看效果
关注我们
界世的你当不
只做你的肩膀
无
360官方技术公众号
技术干货|一手资讯|精彩活动
空·