Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >实现完整网页保存为图片的方法

实现完整网页保存为图片的方法

作者头像
是Vzn呀
发布于 2022-07-14 09:05:14
发布于 2022-07-14 09:05:14
3.1K00
代码可运行
举报
文章被收录于专栏:架构悟道架构悟道
运行总次数:0
代码可运行

业务场景中,会存在某些场景需要将网页内容快照保存下来的场景。因为有些网页内容是联网异步获取的,所以爬虫保存html页面的方式无法保证后续数据与此前的一致性,因此将网页内容以图片保存下来,是一种简单而直接的思路。本文档即针对上述诉求的技术可行性进行论证, 并给出可行的技术实现手段。

整体阐述

按照前面提出的思路,一种简单的业务处理场景可以抽象为如下的模型:

主机服务器上部署一个服务, 从来源处获取到 url 信息, 然后请求此 url 内容并生成截图保存在文件服务器中, 可以在数据库中保存此图片与 url 的映射关系, 便于后续查找。

下面主要阐述下如何实现根据 url 生成其对应内容全量截图(图中蓝色部分)。本文中主要提供了2种可选的实现方案,分别是:

  • 通过 PhantomJS 方式
  • 通过Chrome headless 方式

需要说明的是,在GitHub 上显示 PhantomJS 已经暂停维护了。仅从URL截图这一个诉求来分析的话,已有版本是完全满足要求的、且实现上更简单。如果有更多方面的考量,可以优选Chrome headless方案

网页截图技术方案

通过 PhantomJS 实现

PhantomJS是一个基于webkit的JavaScript API。作为一个免费且开源的工具,支持Windows/Linux/Mac等多平台上运行,且可以通过JAVA/Python/bat/sh等方式进行调用。

以Windows平台为例,PhantomJS提供了一个exe文件,可以通过在JAVA或者Python中进行简单的封装调用即可,下面对其用法进行简单介绍。编写其js脚本如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var page = require('webpage').create();
page.open(url, function(status) {
  console.log("Status: " + status);
  if(status === "success") {
    page.render(pic_name);
  }
  phantom.exit();
});

则在cmd窗口中,执行phantomjs.exe screenshot.js命令,则会将js中指定的url页面内容生成图片并保存在指定的位置。

在工程中调用PhantomJS的用法如下:

JAVA实现

JAVA工程中可以通过拼接命令并调用exe文件执行抓取操作来实现。考虑先准备一份js模板,然后代码中处理替换掉js模板中的url和pic_name字段,并调用phantomjs.exe screenshot.js命令完成图片抓取。

代码DEMO片段如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/**
* 将url内容转换为png图片保存
 * @param url 目标url地址
 * @param pngSavePath 图片保存位置
 */
public static void convertHtml2Png(String url, String pngSavePath) {
  // 读取js模板
  String templateJsContent = FileUtil.readFile("Template.js", "utf-8");
  // 将js模板中的url和图片路径占位符全部替换为实际的
  String realJsContent = templateJsContent
      .replace("url", "'" + url + "'")
      .replace("png_name", "'" + pngSavePath + "'");
  String realJsTempPath = "./tmp/" + UUID.randomUUID().toString() + ".js";
  // js内容写入临时文件
  FileUtil.writeFile(realJsTempPath, realJsContent);

  // 拼接cmd命令并执行
  String cmd = "phantomjs.exe " + realJsTempPath;
  try {
    Runtime.getRuntime().exec(cmd);
  } catch (Exception e) {
    // ...
  }

  // 删除js临时文件
  new File(realJsTempPath).deleteOnExit();
}

此方案需要安装相关环境信息如下:

  • JDK
  • PhantomJS
Python实现

Python中结合selenium和PhantomJS可以轻松实现页面全图截取,代码DEMO演示如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
from selenium import webdriver
import os

driver = webdriver.PhantomJS()

urls = open("urls.txt") 
for url in urls:
    driver.get(url)
    driver.save_screenshot(str(hash(url)) + '.png')

driver.close()

此方案需要安装相关环境信息如下:

  • Python(含selenium库)
  • PhantomJS(.exe放到python安装目录script目录下)

通过Chrome headless模式实现

如前面所述,PhantomJS在根据url生成图片方面已经满足要求了,但是PhantomJS目前暂停更新了。且在高版本的python selenium中已经将PhantomJS标记为deprecated并推荐使用chrome headless方式来替代。

所谓headless模式,也即无UI模式,在不打开chrome浏览器窗口的情况下,在后台进行无界面处理。

下面介绍下在python中通过chrome headless进行url全图保存的实现方式。参考如下的DEMO代码片段:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
from selenium import webdriver
import os
import time
from selenium.webdriver.chrome.options import Options

chrome_options = Options()
chrome_options.add_argument('--headless')
chrome_options.add_argument('--disable-gpu')
chrome_options.add_argument('--start-maximized')

urls = open("urls.txt") 
for url in urls:
    driver = webdriver.Chrome(executable_path='chromedriver.exe', chrome_options=chrome_options)
    driver.get(url)
    # Get the actual page dimensions using javascript
    width = driver.execute_script("return Math.max(document.body.scrollWidth,document.body.offsetWidth, document.documentElement.clientWidth, document.documentElement.scrollWidth, document.documentElement.offsetWidth);")   
    height = driver.execute_script("return Math.max(document.body.scrollHeight, document.body.offsetHeight,document.documentElement.clientHeight, document.documentElement.scrollHeight, document.documentElement.offsetHeight);")
    #resize
    driver.set_window_size(width,height)
    time.sleep(1)
    driver.save_screenshot(str(hash(url)) + '.png')
    driver.quit()

因为通过chrome headless的方式进行截图的时候,默认只截取当前显示屏幕区域。因此如果需要截取网页全部内容,便需要进行额外的处理(如上述代码中红色标识的代码片段)。在python中通过执行js语句,计算出网页真实的width和height值,然后对页面resize操作使其展示全部大小,之后再进行截图就可以保存整个网页了。

此种方案,需要安装相关环境信息:

  • Python(2或者3都行、selenium库);
  • Chrome浏览器(以及配套的chromedriver)。

配置好相关环境变量信息(或者代码中指定相关路径)即可。

抓取到的图片效果如下:

性能考量

上面提及的两种方案,本质上都属于爬虫的一种,而且需要根据远端请求到的内容进行渲染成具体页面,再将页面转换为图片写入磁盘。

受网速、webkit渲染CPU占用、页面内容大小、IO读写等多方因素影响,其单线程页面图片抓取的速度并不高(在笔记本上DEMO测试的时候,百度等小页面1s以内完成,门户财经相关新闻网站页面很大,加载完成并截图保存耗时7-8s,如果部署在服务器上的性能理论上会好一些)。

如果对处理性能有较高要求,可以考虑多线程并发提升性能,但是整体单机处理性能并不会太高,数据量特别巨大的时候可以考虑集群部署增加处理节点。

附录,软件包获取

  1. chromedriver: http://chromedriver.storage.googleapis.com/index.html
  2. PhantomJS: https://phantomjs.org/download.html
  3. Python3: https://www.python.org/getit/
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-09-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 架构悟道 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Selenium | 笔记
这里我们选用第三种,相对来说适应性比较好,也方便查看进展,如果想隐藏页面,只需要加入—headlss选项即可。
yiyun
2022/04/01
3K0
Selenium | 笔记
WebScreenshot | 开发笔记
关联仓库: https://github.com/yiyungent/WebScreenshot-python
yiyun
2022/04/01
6400
08 Python爬虫之selenium
当获取一个网站的图片数据时,只能爬取到图片的名称,并不能获得链接,而且也不能获得xpath表达式。这是应用了图片懒加载技术。
py3study
2020/01/15
1.1K0
Python3 Selenium+Chr
以前抓取动态网页是用PhantomJS + Selenium + ChromeDriver,但是新版的Selenium不支持PhantomJS了,程序跑的时候总会跳出一些warnings.
py3study
2020/01/10
5050
Selenium及Headless Ch
一般的的静态HTML页面可以使用requests等库直接抓取,但还有一部分比较复杂的动态页面,这些页面的DOM是动态生成的,有些还需要用户与其点击互动,这些页面只能使用真实的浏览器引擎动态解析,Selenium和Chrome Headless可以很好的达到这种目的。
py3study
2020/01/19
1.1K0
爬虫最终杀手锏 — PhantomJS 详解(附案例)
Selenium: 可以根据我们的指令,让浏览器自动加载页面,获取需要的数据,甚至页面截屏,或者判断网站上某些动作是否发生。Selenium 自己不带浏览器,不支持浏览器的功能,它需要与第三方浏览器结合在一起才能使用。但是我们有时候需要让它内嵌在代码中运行,所以我们可以用一个叫 Phantomjs 的工具代替真实的浏览器。
全栈程序员站长
2022/09/06
2.4K0
Python爬虫技术系列-04Selenium库的使用
针对119.0.x的版本驱动需要在 https://googlechromelabs.github.io/chrome-for-testing/ 中下载
IT从业者张某某
2023/11/07
1.3K0
Python爬虫技术系列-04Selenium库的使用
selenium使用
请注意,本文编写于 1727 天前,最后修改于 996 天前,其中某些信息可能已经过时。
曼亚灿
2023/05/17
1.5K0
selenium使用
PhantomJS,chrome,firefox 驱动截取图片
package com.lenovo.sciv4.utils; import com.amazonaws.services.s3.model.ObjectMetadata; import com.itextpdf.text.Rectangle; import com.lenovo.sciv4.commons.download.utils.S3Connection; import com.lenovo.sciv4.commons.frameworks.utils.LogUtil; import com.l
binc
2021/12/13
1.3K0
爬虫系列(9)爬虫的多线程理论以及动态数据的获取方法。
将将要爬去的url放在一个队列中,这里使用标准库Queue。访问url后的结果保存在结果队列中
野原测试开发
2019/07/10
2.7K0
爬虫系列(9)爬虫的多线程理论以及动态数据的获取方法。
Headless Chrome简介
在 Chrome 59中开始搭载Headless Chrome。这是一种在无需显示headless的环境下运行 Chrome 浏览器的方式。从本质上来说,就是不用 chrome 浏览器来运行 Chrome 的功能!它将 Chromium 和 Blink 渲染引擎提供的所有现代 Web 平台的功能都带入了命令行。
随心助手
2020/08/04
1.7K0
别去送死了。Selenium 与 Puppeteer 能被网站探测的几十个特征
很多人喜欢使用Selenium 或者 Puppeteer(Pyppeteer)通过模拟浏览器来编写爬虫,自以为这样可以不被网站检测到,想爬什么数据就爬什么数据。
青南
2020/12/02
13.5K5
别去送死了。Selenium 与 Puppeteer 能被网站探测的几十个特征
python python截取长网页 并发送邮件
python截取长网页 并将截取的网页保存至本地 后发送邮件 准备工作 安装依赖 yum install chromedriver yum install https://dl.google.com/linux/direct/google-chrome-stable_current_x86_64.rpm pip install selenium 核心代码 #!/bin/python # coding=utf-8 # author: wz # mail: 277215243@qq.com # dat
葫芦
2019/11/16
1.3K0
火狐谷歌模拟一个虚拟界面
在Python中进行浏览器测试时,一般我们会选择selenium这样的库来简化我们工作量。而有些时候,为了对一些动态数据进行抓取,我们会选择
周小董
2019/03/25
9810
火狐谷歌模拟一个虚拟界面
python识别批量网站中的图片
实现方式: 下载网页源码,在源码中识别包含图片url的标签,如<img>,<div>,<li>。由于对html了解较少,哪些标签可能含有图片是从查看多个网站的源码中总结出来的。
py3study
2020/01/20
1.5K0
使用 selenium 写的多进程全网页截图工具,发现了 PhantomJS 截图的 bug
selenium 是一个可以模拟浏览器操作的工具,据我所知,不仅仅是 Python,还有其他的编程语言也有支持的 selenium 库,可以作为爬虫或者自动化测试。当然,还有今天要说的,可以使用 selenium 来作为全网页截图工具。
Hopetree
2022/09/26
1.1K0
使用 selenium 写的多进程全网页截图工具,发现了 PhantomJS 截图的 bug
搭建谷歌浏览器无头模式抓取页面服务,laravel->php->python->docker
公司管理系统需要获取企业微信页面的配置参数如企业名、logo、人数等信息并操作,来隐藏相关敏感信息并自定义简化企业号配置流程
猿哥
2019/08/06
2.4K0
搭建谷歌浏览器无头模式抓取页面服务,laravel->php->python->docker
利用 Python + Selenium 实现对页面的指定元素截图(可截长图元素)
WebDriver.Chrome自带的方法只能对当前窗口截屏,且不能指定特定元素。若是需要截取特定元素或是窗口超过了一屏,就只能另辟蹊径了。
周小董
2019/03/25
11K2
爬取煎蛋XXOO妹子图片
今天回忆廖大的多线程的时候,看到下面有人写了个多线程的爬虫http://www.tendcode.com/article/jiandan-meizi-spider-2/,点进去看了下,分析的很仔细,写了接近200行代码吧
全栈程序员站长
2022/09/07
3630
Python动态网页爬虫—爬取京东商城
动态网页则需要依靠客户端的脚本和服务端的脚本两种方式进行渲染才形成最终的显示文档。
AnieaLanie
2021/12/11
1.6K0
相关推荐
Selenium | 笔记
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验