长截图问题

问题:使用dom-to-image和html2canvas来进行长截图会出现一个问题,如果图片非常长,一些图片会只加载一半,如果图片再长一些,截图就会为空。

目前我测试的结果:截图的大小在8mb出现图片缺了的情况
截图为空不是库的bug,是浏览器到了极限,无法输出了,这时cpu飙到快100%。

图片缺失这个情况还可以优化,可以想办法把dom进行拆分,再分别截图,最后拼接图片

优化长截图的思路:

  1. 还是用js里的dom-to-image,不断拆分dom,分别截图,最后合并
  2. 使用selenium截图,滚动截图,再用opencv拼接图片

上面两个思路,是不是能实现无限长的截图呢?

方法一:按理说应该能无限长的,但是浏览器扛不住,我的测试结果是截图大小在18mb左右,再大一些就不输出了。
方法二:这个方法能实现无限长的截图,但太慢了

代码实现

方法一:推荐做法

核心思想:把如下图所示拆分的dom分别使用dom-to-image截图,再通过canvas合并图片,最后下载

要截图的完整dom

拆分的dom1

拆分的dom2

拆分的dom3

const start = async() => {// 拆分domconst domArr = this.splitChatDom()// 生成图片到imageListdomArr.forEach((domList,index) => {const dom = this.mergeChat(domList)document.body.appendChild(dom)this.createImage(dom,index)})await this.sleep(5000);// 合并图片this.mergeImage()await this.sleep(5000);// 下载this.download(this.canvas.toDataURL('image/png'),this.getFilename())
}
start()

把需要截图的子元素取出来,放到数组中

// 拆分chat子元素
splitChatDom() {let chat = document.querySelector("#chat")let chat_inner = chat.getElementsByClassName("chat-inner")[0]const dom_length = chat_inner.children.lengthlet childs = chat_inner.childrenlet domArr = []let i = 0;// 拆分个数const num = 20while (i < dom_length) {let arr = []for (let j=0;  j< num && i+j<dom_length; j++) {const element = childs[i+j];arr.push(element)}domArr.push(arr)i+=num}return domArr
},

还原dom的父节点

mergeChat(domList) {let chat = document.createElement("div")chat.id = "chat"let chat_inner = document.createElement("div")chat_inner.className = "chat-inner"chat.appendChild(chat_inner)// console.log(domList);domList.forEach((dom) => {chat_inner.appendChild(dom)})return chat
},

分别截图

// 根据dom创建图片
createImage(dom,index) {domtoimage.toPng(dom, { quality: 1 }).then((dataUrl) => {this.imageList[index] = dataUrlthis.heightList[index] = dom.offsetHeight})
},

合并截图

// 合并图片
mergeImage() {this.canvas = nulllet canvas = document.createElement("canvas")let context = canvas.getContext("2d")context.scale(0.8,0.8)const scale = 0.8;const width = 1000 * scale; // 确保canvas的尺寸和图片一样const canvas_height = this.heightList.reduce((a,b)=>a+b-170) * scale;canvas.width = widthcanvas.height = canvas_heightlet sumHeight = 0for (let i = 0; i < this.imageList.length; i++) {const dataUrl = this.imageList[i];const height = this.heightList[i]let img = new Image()img.src = dataUrlimg.width = widthimg.height = heightimg.onload = () => {context.drawImage(img,0,sumHeight,width,height * scale)sumHeight += (height - 170) * scalethis.mergeFlag[i] = true}}this.canvas = canvas
},

暂停方法,需要在异步方法中调用

sleep(time){return new Promise((resolve)=>{setTimeout(()=>{resolve();}, time)})
},

方法二:效率低

def save_screenshot(url, fp_pic):chrome_options = webdriver.ChromeOptions(); chrome_options.add_experimental_option("excludeSwitches", ['enable-automation']);driver = webdriver.Chrome(options=chrome_options);driver.get(url)time.sleep(5)# 获取要截图的dom的高度chat = driver.find_element_by_id("chat")dom_height = chat.get_attribute("offsetHeight")offset_top = chat.get_attribute('offsetTop')page_height = 500driver.set_window_size(1080, page_height)# 滚动到要截图的位置#driver.execute_script("arguments[0].scrollIntoView();", chat)driver.execute_script('window.scrollBy(0,{});'.format(int(offset_top)))driver.save_screenshot('temp.png')n = int(dom_height) // (page_height-85) # 需要滚动的次数base_mat = np.atleast_2d(Image.open('temp.png')) # 打开截图并转为二维矩阵for i in range(n):print(i,page_height*(i+1))driver.execute_script('window.scrollBy(0,{});'.format(page_height-85)#'window.scrollTo(0,{});'.format(page_height*(i+1)+int(offset_top)))driver.save_screenshot(f'temp_{i}.png') # 保存截图mat = np.atleast_2d(Image.open(f'temp_{i}.png')) # 打开截图并转为二维矩阵base_mat = np.append(base_mat, mat, axis=0) # 拼接图片的二维矩阵Image.fromarray(base_mat).save(fp_pic, format='PNG')os.remove(f'temp_{i}.png')os.remove('temp.png')driver.quit()if __name__ == "__main__":url = ''save_screenshot(url,'aaa.png')# 缩放图片img = cv2.imread('aaa.png')img = img[:,:1250]img = cv2.resize(img,None,fx=0.64, fy=0.64, interpolation = cv2.INTER_CUBIC)cv2.imwrite('aaa.png',img)

dom截图——探究长截图的极限相关推荐

  1. 如何翻滚截屏_电脑端文档如何滚动截图(长截图)?

    我们都知道,在手机端某些安卓的手机支持长截图,或叫做滚动截图.那么你知道在电脑端如何对excel或者word进行滚动截图吗? 不知道不要紧,看完这篇文章你就知道啦,并且以后可以完美应用到学习.工作当中 ...

  2. 使用selenium将网页保存网页截图,长截图,html文件,mhtml文件

    最近在做网页分析需要爬取很多的网页,然后就使用selenium进行了一系列的操作,最后可以保存网页的首页截图,整体截图(包含所有滚动区域),HTML源文件和MHTML源文件,整理后的代码如下: 邮箱, ...

  3. 浏览器截图方法(长截图、node截图、指定区域截图)

    1.打开需要截屏的页面,按键盘上的F2(或者Ctrl+Shift+I)打开浏览器控制台 2.Ctrl+shift+P进入搜索框,输入"screen": 这里有四种截图模式,点击需要 ...

  4. iShot 1.7.8 中文版 (支持长截图的截图工具)

    iShot 是一款适用于Mac优秀的截图工具.功能全面,支持:区域截图.窗口截图.长截图.延时截图.屏幕录制以及截图标注.这里要特别表扬一下iShot的延时全屏截图以及快速标注工具.对于小编这种重度依 ...

  5. 必备!iShot 1.7.6 中文版 (支持长截图的截图工具)

    iShot 是一款适用于Mac优秀的截图工具.功能全面,支持:区域截图.窗口截图.长截图.延时截图.屏幕录制以及截图标注.这里要特别表扬一下iShot的延时全屏截图以及快速标注工具.对于小编这种重度依 ...

  6. 安卓上的微软 Edge 浏览器新增支持长截图

    据 MSPoweruser 报道,安卓上的微软 Edge 浏览器正在获得一项新功能,允许用户进行长截图,类似于安卓版 Chrome 浏览器的做法.目前,Edge Canary 频道提供了长截图的功能, ...

  7. 实用!你不知道的小技巧,电脑快速实现屏幕长截图

    在日常工作中,我们经常需要用到屏幕长截图这个功能,而要实现这个功能往往需要下载好几个软件,而且经常截图的效果并不如意. 其实国民软件QQ目前已经有了长截图功能. 首先下载QQ最新版,然后在需要截图的页 ...

  8. 手机屏大字滚动_在iPhone手机中,实现长截图的几种方法

    如何在iPhone手机中,实现长截图功能,是小伙伴们一直以来讨论的问题.其实在自带的Safari浏览器中,是支持长截图功能.但如若是需要截取其他软件或者系统界面,可能就只能依赖于第三方App了接下来就 ...

  9. 如何优雅的完成长截图?

    安利一个截长图的工具ScreenShotTools. ScreenShotTools ScreenShotTools是一个Android长截图工具.目的是轻松搞定常见的View截图功能. 目前功能有: ...

最新文章

  1. wangEditor编辑器中解析html图文信息问题(三)
  2. OTA整包的制作流程(未完)
  3. STC89C52RC内部EEPROM编程
  4. java开发爱恩斯坦棋,爱恩斯坦棋计算机博弈关键技术研究
  5. Python分析《我们与恶的距离》豆瓣剧评
  6. java基础 ArrayList集合基本方法演示
  7. linux usermod修改用户所在组方法
  8. elk 概念整理 集群状态 - yellow
  9. 空间三维技术重现“山水林田湖草”管理沙盘
  10. tplink无线网卡的linux,Linux系统下怎么用TP-Link的无线网卡?
  11. HTML常用的元素介绍
  12. ajax网页没有办法采集,Ajax网页采集方法(最新) - 八爪鱼采集器
  13. 阿西莫夫定律:自动驾驶汽车算不算机器人?该不该伤人?
  14. 情感日记:2009年12月24日平安夜—“马头琴”
  15. 360浏览器中页面打开如何默认极速模式
  16. 【电路】电容(二)——滤波电容
  17. vue打印问题(分页打印、批量打印条形码)
  18. 从与迪思杰签约 看浪潮主机生态如何布局?
  19. 港科夜闻|香港科技大学(广州)与广东联通签署多方位战略合作协议
  20. python连接hive步骤(不出错版)

热门文章

  1. 使用Relational Cache加速Spark数据分析
  2. 数值计算方法 第一章 数值计算中的误差 笔记
  3. 地址传送指令LEA,LDS,LES;
  4. 单片机控制发光二极管的显示(1)
  5. 做Nodejs项目服务器部署
  6. 微信公众号的注册(实例:订阅号)
  7. 随便玩玩-root用户下rm -rf /的后果
  8. 第13章 统一的数据访问异常层次体系
  9. 耀启新篇 筑梦新程 l 棱镜数聚西安分公司乔迁新址
  10. 俞敏洪(新东方董事长)赢在中国现场演讲