遇见一篇有意思的文章,或者是在购物时发现了好东西,需要分享。

不想发送链接,也许搞一个长截图是个很好的选择。

Selenium

Selenium是一种自动化测试工具,它支持各种浏览器,包括 Chrome,Safari,Firefox 等主流界面式浏览器,如果你在这些浏览器里面安装一个 Selenium 的插件,那么便可以方便地实现Web界面的测试。换句话说叫 Selenium 支持这些浏览器驱动。Selenium支持多种语言开发,比如 Java,C,Ruby, Python等等。

在这个案例中,我们使用基于Python3的运行环境进行演示。

使用pip3安装selenium


$ pip3 install selenium

获取chrome-driver

在淘宝npm镜像中可以找到Chrome版本对应的驱动: http://npm.taobao.org/mirrors/chromedriver/

初始化浏览器

def init_browser():chrome_options = Options()# --headless参数表示,Chrome将不会有一个可视化的图形界面# chrome_options.add_argument("--headless")chrome_options.add_argument("--disable-gpu")chrome_options.add_argument("--disable-web-security")# 以iPhone 6的屏幕宽度作为基准mobile_emulation = { "deviceName": "iPhone 6" }chrome_options.add_experimental_option("mobileEmulation", mobile_emulation)return webdriver.Chrome("./chromedriver",chrome_options=chrome_options)browser = inti_browser()

调用Webdriver提供的API, 获取网页基本信息

url = "https://code.evink.me"# browser是我们刚刚初始化的浏览器实例# 设置页面渲染超时browser.set_page_load_timeout(30)# 设置脚本执行超时browser.set_script_timeout(100)# 获取网页资源browser.get(url)# 给浏览器设置一个默认的初始宽高(非必要)browser.set_window_size(375, 1000)

Chrome在iPhone 6的模拟环境下进行网页渲染,其宽是一定的,所以可以通过调用运行于webdriver内部的javascript代码,获得我们想要的内容。

webdrive提供了丰富的接口供我们全方位操控这个小小的浏览器。

# browser是我们刚刚初始化的浏览器实例body_height = browser.body.get_attribute("clientHeight")

或者,这里还有一个更加可操作的方法,直接在webdriver里跑js代码。Selenium提供了execute_script(str)接口,可以让用户通过自己更为熟悉的方式,得到自己想要的内容。

# browser是我们刚刚初始化的浏览器实例body_height = browser.execute_script(get_script("body_height")))# get_script(str) -> strdef get_script(_type):if _type == "body_height":return """// get body_heightreturn document.getElementsByTagName("body")[0].clientHeight;"""

滚屏截图

webdriver提供了一个保存当前浏览器窗口截图的接口save_screenshot(path)

我们只需要让网页沿着一个预设定的高度滚动就好。

这里,这个高度是667(基于我们以iPhone 6的虚拟环境初始化的浏览器)。设定大于667的高度,每次也并不会截取到更多的页面内容,而小于667的高度,会让你最后进行图片处理的时候非常头疼。

dir_path = "tmp_screenshots"filename = "evink" + int(datetime.now().timestamp())paging_list = []def take_screenshot():# loop_times由网页高度和单屏高度计算而来for i in range(loop_times):browser.execute_script(get_script("scroll_window") % (i + 1))# 截取屏幕path = "%s/%s_%s.png"%(dir_path, filename, i)browser.save_screenshot(path)paging_list.append(path)return paging_listdef get_script(_type):if _type == "scroll_window":return """// 滚动的次数var m = %s;// 屏幕rangevar begin = 0;var end = 667;// 滚屏window.scrollTo(begin, end * m);"""if _type == "scroll_y":return """return window.scrollY;"""

合成图片

上一步结束之后,我们在/tmp_screenshots目录下会发现若干png格式的图片,利用Python中的PIL Image库,可以很方便的对图片做处理。

“`python

def paste_imgs(self):# loop_times由网页高度和单屏高度计算而来for i in range(loop_times):path = "%s/%s_%s.png"%(dir_path, filename, i)if os.path.exists(path):continueelse:# 记录存在的最大图片张数max_screen = i# 根据总图片张数计算合成的单张图片高度page_total_height = 667 * 2 * loop_times# 声明一张空白的图片实例image = Image.new('RGB', (375 * 2, page_total_height), (255, 255, 255))for i in range(loop_times):path = "%s/%s_%s.png"%(dir_path, filename, i)from_img = Image.open(path)# 粘贴图片image.paste(from_img, (0, 1334 * ( i + 1 )))path = "%s/%s_part_%s.jpg"%(dir_path, filename, part+1)# 保存图片 以JPEG格式,60质量image.save(path,format='JPEG', quality=60)return "%s/%s.jpg"%(dir_path, filename)

“`

处理细节

上一步结束之后,我们获得了一张完整的图片,但是,你一定会发现很多小细节没有处理。

图片未被加载

如果你要截取的网页采用了图片懒加载模式(可以提升访问速度),你会发现所截取的网页的图片都被灰色的色块所替代。

我们可以分析网页中,未被加载的图片是否有什么共同点。比如说,是否含有特定的class,是否有自定义的属性值。

# 假设图片未加载时,此网页图片的class会有 "img_loading"# 获取所有的图片元素imgs = browser.find_elements_by_tag_name("img")img_load_start = datetime.now().timestamp()while True:# 已加载的图片数img_loadeds = 0for img in imgs:# 拿到class属性clz = img.get_attribute("class")if clz.find("img_loading") == -1:img_loadeds += 1print("已经加载完毕的图像数:%s"%img_loadeds)if img_loadeds == len(wait_load_imgs):print("all imgs loaded")break# 给他设置一个超时if datetime.now().timestamp() - img_load_start > 60:print("imgs loading timeout")breaksleep(0.1)

图片底部 显示不完全 / 留有大量的空白 / 拼接不完美

造成这个原因,无非是高度和留余问题。

网页高度

某些网页上,在滚屏完毕(即所有图片都被加载后)的高度和网页初始化后的高度并不一致。

高度的错误会导致生成图片时抛出异常

# 妈妈让我再滚一次def scroll_window(need_renew_height=False):for pre_scroll in range(loop_times + 1):self.browser.execute_script(self.get_script("scroll_window")%pre_scroll)sleep(0.5)print("-- 已经滚完 --")if need_renew_height:# 重新录入高度body = browser.find_element_by_id('activity-detail')body_height = int(body.get_attribute("clientHeight"))loop_times = math.ceil(body_height / height)def get_script(self, _type):if _type == "scroll_window":return """// 滚动的次数var m = %s;// 取出所有图片var imgs = document.querySelectorAll('img');// 屏幕rangevar begin = 0;var end = 667;// 滚屏window.scrollTo(begin, end * m);// 图片的相对距离for(var i = 0;i < imgs.length;i++){var y = imgs[i].getBoundingClientRect()["y"];if(y >= begin && y <= end){imgs[i].setAttribute("type", "wait_load");}}"""

处理好收尾工作

在生成滚屏时,最后一张图片含有两种状态。

  • 完美占据一屏的空间 (375 * 667)
  • 只占据部分空间,底部含有留白

处理好最后一屏图片和倒数第二屏的关系,就可以避免出现图片拼接不完美的情况。

图片 黑屏 / 损坏

图片过长,尝试按照固定的屏幕数,将一张图切成几张小图。


原文地址: https://code.evink.me/2018/07/post/python-use-chrome-to-make-a-long-page-screenshot/

使用Chrome来做一张长截图相关推荐

  1. iphone长截图哪个软件好_这可能是 iPhone 手机里最好用的长截图、拼图 APP。

    手机里最好用的长截图.拼图APPhttps://www.zhihu.com/video/1066038718523043840 如何在手机上制作一张拼合图片,我们首先想到的可能就是美图秀秀,但是美图秀 ...

  2. 谷歌浏览器怎么长截图怎么截_chrome长截图如何操作_chrome怎么滚动截长图-win7之家...

    在使用chrome浏览器搜索网页的时候,常常会遇到一些篇幅较大的文章,这时有些用户可能不想要通过收藏网址将其保存下来的时候就可以通过截取长图的方式保存自己想要的部分,那么chrome怎么滚动截长图呢? ...

  3. 使用chrome保存完整网页为长图片

    转:chrome也可以整张网页截图,保存完整网页为图片 原链接:http://www.webkaka.com/blog/archives/chrome-save-a-webpage.html 关于浏览 ...

  4. Chrome原生工具实现长截图

    Chrome原生工具实现长截图 文章目录 Chrome原生工具实现长截图 前言 操作步骤 参考文章 前言 我们在网上冲浪时,经常遇到一些搞笑的或者是写的比较好的文章,想长截图给别人分享.可是 Wind ...

  5. 谷歌浏览器chrome长截图功能,不用工具轻松截图

    在谷歌浏览器chrome中打开需要截图的网页 等待需要截图的网页打开完毕 然后按F12 打开开发者工具 然后按组合键 Ctrl+Shift+P 调出谷歌浏览器chrome长截图需要的面板 然后输入 f ...

  6. Chrome浏览器 网页长截图方法

    平时我们在浏览网页的时候,碰到自己喜欢的页面,想要截图而自己的显示器窗口高度有限,我下面将为大家分享这种方式,获得整个网页的截图.一起来开始吧: 首先,我们用到的浏览器是谷歌的Chrome浏览器. 第 ...

  7. 使用Chrome浏览器实现网页长截图 无需安装插件

    有些网页比较长,一屏装不下,需要拉动滚动条才行,这种网页我们想截图截取全部内容时就比较困难 如果使用的是Chrome浏览器,可以使用如下方法截图: 打开网页后 按快捷键 F12 打开移动设备预览模式( ...

  8. 你的Chrome浏览器不可以长截图?

    文章目录 前言 一.浏览器自带方法 1.打开控制面板 2.快速查找 3.输入cap 二.使用第三方插件 1.安装插件 2.使用插件 总结 前言 随着截图功能越来越成为人们的生活习惯,我们可以手机截图. ...

  9. python如何截长图_使用python实现对元素的长截图功能

    一.目标 浏览网页的时候,看见哪个元素,就能截取哪个元素当图片,不管那个元素有多长 二.所用工具和第三方库 python ,PIL,selenium pycharm 三.代码部分 长截图整体思路: 1 ...

最新文章

  1. lambda在python中的用法_在python中对lambda使用.assign()方法
  2. Python切片(入门7)
  3. 全国计算机二级公共基础知识练习,2020年全国计算机二级公共基础知识练习题(7)...
  4. Stack around the variable 'date' was corrupted.
  5. PHP面向对象常见的关键字和魔术方法
  6. python写sql语句_Python操作文件模拟SQL语句功能
  7. delphi控件切图界面闪烁_一份最详尽全面的UI界面切图命名规范
  8. 从零开始刷Leetcode——数组(118.119.121)
  9. idea一键导包快捷键_十三肝了2晚的《IDEA操作手册-终极秘籍》终于来了...
  10. NVIDIA背书-Kaldi是目前最受欢迎的开源语音识别框架
  11. 精通PHP的十大要点
  12. 微软开始受到越来越多尊重 谁是幕后功臣?
  13. 关于路由器认证校园网的可行方案.md
  14. RTCM3.1/3.2
  15. 职场001 什么时候跳槽
  16. HADOOP HA之NameNode HA集群配置与应用
  17. 函数传参问题,桶排序去重,分治递归,摩尔投票求数组众数,数组中心下标求法
  18. 做个爱看电影的人-----袁岳
  19. 人工智能、机器学习、深度学习学习资料整理(开发必备)
  20. java web 工具_MagicTool

热门文章

  1. 《卡卡保皇》12.31上线链游玩家|塔防升级、休闲闯关
  2. 华为鸿蒙安装酷喵,华为鸿蒙系统首次体验,3799元,4K屏!
  3. ftp自动上传或下载脚本
  4. 男生脸型测试比较好的软件,怎样测自己的脸型,男生脸型分类图
  5. 学计算机的需要配哪种笔记本,大一新生有必要带电脑吗?辅导员说出答案,报道前需要了解清楚...
  6. 分享联发科MT8665 datasheet,MT8665数据手册,MT8665规格书资料
  7. 如何将CAD图纸导出为天正各版本图纸?
  8. Matplotlib绘图技巧——自定义横轴
  9. 转- android硬件传感器
  10. shell脚本基础和shell工具