资讯专栏INFORMATION COLUMN

我还是踩上了网页截图的坑

jcc / 3239人阅读

摘要:最近做了个实现网页缩略图的项目,其中不免需要用到网页截屏。选择好方案后还是踩了不少坑,第一个就是我得想办法让它和通信,不然我没法通过前端只传一个需要被截图的链接给就能实现截图。

最近做了个实现网页缩略图的项目,其中不免需要用到网页截屏。

一开始想的是看看能不能在前端直接实现截图,因为Web端的截图并生成图片并不算是一个高频的需求,网上资料自然也不算多,查来查去,发现JavaScript 目前还不能实现真正意义上的网页截屏,未来如果能够实现,也一定是浏览器提供了相关接口,JS 去调用这些接口。

既然js不能实现真正意义上的截屏,那我们能做的只有通过拿到DOM的一些信息利用canvas来生成图片。

如何将dom转换成canvas图片?自然是要一点点画到canvas里,想想都是件麻烦事。网上找来找去看看有没有现成的轮子,找到了html2canvas,通过分析 niklasvh/html2canvas,梳理了其大致的思路:

遍历页面中的所有元素,提取DOM节点,填充到一个rederList,并附加是否为顶层元素/包含内容的容器等信息

通过提取的css属性和元素的层级信息将rederList排序,计算出一个canvas的renderQueue

遍历renderQueue,将css样式转为setFillStyle可识别的参数,依据nodeType调用相对应canvas方法,将节点对应到 canvas 上。

这个方案听起来就很复杂了,无论是排序优先级的计算还是从css到canvas的转换,毫无疑问都是些巨麻烦的事,尤其是放在真实的业务场景里,DOM模版中往往会包含复杂的样式与排版,html2canvas 足足用了20多个js来实现这层转换,复杂成度可见一斑。不过这个库封装的不错,使用起来比较简单:

html2canvas(document.body).then(function(canvas) {
   canvas.id = "screenshotCanvas"
   document.body.appendChild(canvas)
});

此时,页面的截图已经 append 到了 body 中了。虽然过程是很复杂,但是已经有了这些轮子,我们了解原理就好,人家有现成的库可以用,那咱们就不要再花费力气去造轮子,不好玩。

说了这么多这个canvas的方案,但是我最终还是没有选择它,因为我的网页里面有不少图片,都是外域资源,而这套方案我认为最大的问题就是:无法跨域加载资源 (虽然html2canvars补充了方案来弥补这个问题,但是对于我的项目实现起来成本都太高)

忘了说,在研究html2canvars的过程中我还发现了一个库叫rasterizeHTML.js。知乎的意见反馈功能里面的截图就是使用的这个库,原理有点类似,不过使用的是svg,所以我还是没有选择它,它也没法绕过跨域请求资源这个问题。

最后只能从node端使用 phantomJS 来实现了。phantomJS 它提供了一个截屏函数,通过它可以整屏获取页面截图,而且他支持的格式也比较多:JPG/PNG/GIF/PDF。通过简单的两句命令就可以把一个网页截取下来:

// render.js
var webPage = require("webpage")
var page = webPage.create()
page.viewportSize = { width: 1920, height: 1080 }
page.open("http://www.iqiyi.com", function start(status) {
  page.render("iqiyi_home.jpeg", {format: "jpeg", quality: "100"})
  phantom.exit()
})

安装 phantomjs 之后执行下上面的文件:

phantomjs render.js

调用完你会发现,图片已经保存到了同目录下。

选择好方案后还是踩了不少坑,第一个就是我得想办法让它和node通信,不然我没法通过前端只传一个需要被截图的链接给node就能实现截图。

于是接着在网上找,发现又是这么复杂,动不动就是websocket的方式等,只能接着找轮子,还好有诸多前辈已经实现好了,万花丛中选择了一个比较适合我项目的叫做phantom的库解决了这问题。

走到这一步以为万事具备了,然后开干,发现截了张白屏给我,一开始以为是要截的网页数据没有加载完,于是delay了一会再去截图,发现还是白屏,这就很绝望了。

走到这一步再放弃就不好玩了,最终经过长久的debug发现,原来phantomJS没有支持到promise,而我网页请求数据走的是fetch api,phantomJS模拟浏览器打开我的网页,数据一直请求不到,打开的网页是个空的,截图自然就变成白屏了。

最后的结局是好的,就是再对promise 做了一下polyfill,实现了我想要的截图。过程也是好的,作为前端菜鸟,能学到的简直不能再多了。(最近看了看刚出来的Headless chrome,或许以后的截图我就用不到phantom了)

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/85146.html

相关文章

  • 【在网页中获取截图数据】Chrome和Firefox下的实战经验

    摘要:最近在实现一个功能,需求如下前提当前页面无弹窗页面任意位置执行粘贴读取剪切板中的截屏数据上传截图首先还是从网上找相关的例子。找到了上的专栏文章获取剪切板内容,控制图片粘贴。 最近在实现一个功能,需求如下: 前提:当前页面无弹窗 页面任意位置执行粘贴 读取剪切板中的截屏数据 上传截图 首先还是从网上找相关的例子。 找到了SF上的专栏文章《js获取剪切板内容,js控制图片粘贴》。 于是...

    vslam 评论0 收藏0
  • 再也不用担心网页编码的坑了!

    摘要:的链接在感兴趣的同学可以自行查阅最后总结当返回头没有的时候,使用猜测出来的编码一般都是很准的当返回头里面有的时候,如果有,则的编码为的值。截图自己看把,地址在如果还有猜测编码的方法,欢迎留言完 大家爬取网页的时候,应该都遇到过这种情况  当我打印网页源代码的时候 发现 全部是乱码的 showImg(https://segmentfault.com/img/remote/14600000...

    ky0ncheng 评论0 收藏0
  • 2017个人总结

    摘要:特此写个流水账总结,供自己以后羞耻的回顾。正逢月计划辞职回家玩游戏过个暑假,结果在如今部门老大的忽悠下加入到了新东家。和组长两人继续没昼夜的忙活,最终也按时交差,上了线。卷土重来,回报过去的一份念旧,期待的美好,个人选型入坑。 前言 2017年发生了太多的事情,结了婚,住进了新家,成功的播了种,当上了准爸爸。公司也蒸蒸日上搬进了高大上的写字楼。前端的坑越来越大,都来不及填。特此写个流水...

    Jason 评论0 收藏0
  • 这儿有一个使你网页性能提升10倍的工具

    摘要:昨天上午,我发布了业界第一款性能统计分析框架。同时,这个工具也是学习浏览器加载渲染网页过程和性能优化的一个利器,因此我们也可以把他作为一个强大的学习辅助工具,不至于让我们在样本过少的情况下得到错误的结论。 昨天上午10:00,我发布了业界第一款「性能统计分析框架」Hiper。 截止到2018年6月6号20:00分,已经500个star了,同时项目也冲上了Github新热门榜单第三名的位...

    Leck1e 评论0 收藏0

发表评论

0条评论

jcc

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<