归档 | 一款支持截图中文网站的 Actions 截图工具。

前言

因为某些特殊的需求,我想看到某个网站在过去的某天是什么样子的,尝试过在 互联网档案馆(archive.org) 上搜索,但是找到的内容只是 HTML 代码,因为是前后端分离的网站,其请求的接口数据并没有被保存下来,所以很遗憾,丢失了数据,只能从头来运行,这时我想起半年前写过一个 Python 截图小工具,因为那时候是随手写的,主要是给朋友用的,所以只算是个半成品,拿过来用发现并不能获取全尺寸屏幕截图,不大好用,所以趁着这次机会将这个工具完善了一下,调了一整天参数,可以说是在中文互联网社区来说算是比较好用的了。

对于这个项目我有如下创新点:

  1. 采用 4 种截图模式可进行 全尺寸截图 方式选择,有滚动截图,有拉高屏幕截图
  2. 滚动截图时采用精准像素无缝拼接,并且在尾页做了特殊处理,不会出现多处来一块的情况
  3. 支持自动等待页面加载完成和强制截图延时,可以自行设置相关参数保证截图的完整性
  4. 项目采用 Github Actions 驱动,一看仓库就知道可以跑,可以放心粘贴代码
  5. 同时采用 Actions 方便部署,Fork 改密钥 即可运行
  6. 本项目爬取完数据之后会放回原分支,并且支持单个域名的详细保留截图日期
  7. 支持定时,全自动触发

仓库地址:https://github.com/zkeq/Python-WebSite-Screenshot

补充:写完此文后我发现一个使用 ts + puppeteer 编写的截图仓库,并且可运行于 vercel 推荐一波: https://github.com/Lete114/WebStack-Screenshot

无图无真相

  • www.google.com
  • adobe.onmicrosoft.cn
  • icodeq.com
  • alist.learnonly.xyz
  • blog.learnonly.xyz
  • github.com
  • tuostudy.com
  • www.fast.com
  • www.youtube.com

项目README

本项目是由 Python 写成的网站截图工具。 支持中文网站截图,该功能由 @valetzx 开发。

使用方法

  1. 在 list.json 中填入你的网站列表。
  2. 在 Github 生成一个 TOKEN 并且赋予 repo 权限
  3. 在 环境变量中填入 MY_GIT_TOKEN,该环境变量用于将截好的图再次放回 GitHub。

参数说明

参数

说明

url

网站网址

timeout

sele 模块中等待时间,加载出网站后会停止(秒)

real_time_out

强制等待时间,在上述 timeout 后休眠时间(秒)

width

截图宽度

height

截图高度

daydel

截图的保存时间(天)

full_page

是否截取全屏 (参数为 0 时,表示使用拼接方式,参数为 1 时,表示使用拉高视窗模式,参数为 2 时,不截取全屏,参数为 3 时,调用设备模拟截[实验? 中])

思路

  • 这个项目我首先写的只是打开浏览器,然后截图
  • 这里要感谢 @valetzx 他为本项目增加了中文语言支持功能。
  • 就这样,基本的截图功能算是实现了,也就是进入到今天的正题,如何进行长截图呢?

经过查阅资料,发现 selenium3 以及后续版本已将此功能删去

于是我想到了最容易想到的方法:截图多张,然后拼接

好像写法不大优雅,但是可以无缝拼接…

笔者在撰写此文时,搜到了似乎更为优雅的代码,可以看看这个:

  • python+selenium实现网页全屏截图

上面的代码调参数调了好长时间,大半天的时间过去了,但是我写完之后突然想到:既然我已经有代码获取到页面的整体高度,那么我直接让浏览器的高度等于找个高度,不就没有滚动条了么,而且也不用拼接了

于是就发现只要改动两行 就可以实现…

离谱,似乎前面的工作白做了?那么多白写了?

后来发现不是,这张方法有bug,以我的博客为例,会变成这样:

也就是说屏幕被拉长了..但是同时背景图片因为设置了某个样式,他也被拉长了

还好,之前写的代码并没有浪费,也就是这时候派上用场了

又去搜了一些文章,发现还有一种 设备模拟 的方式,遂又加上:

  • 提供一个在Selenium截网页长图的实现

于是再加上第一次的不进行操作就截图,一共是四种,于是便整理好作为一个参数供用户选择

附上完整代码:

一些其他的本文未提及的相关资料

笔者只是看到这些,并未全部验证可行性,感谢所有为中文编程区做出教程的博主!

  • selenium进行网页长截图,模块长截图
  • Selenium执行cdp命令,driver.execute_cdp_cmd用法
  • 使用selenium网页截图,解决截图不全问题
  • Selenium全屏截图,使用PIL拼接滚动截图
  • Python selenium操作浏览器全屏截图
  • 使用Selenium Webdriver进行全屏截图
  • selenium中整个页面的截图及局部截图(方法分析)
  • python+selenium 把整个网页截图 长截图
  • selenium 截长图
本文转载于网络 如有侵权请联系删除

相关文章

  • js入门(ES6)[六]---异步编程

    js是单线程执行同一时间只能做一件事(任务)但是有子线程 任务分两种一种是同步任务一种是异步任务 同步任务在主线程中排队执行异步任务进入一个任务队列在同步任务形成的执行栈完成后再执行异步任务的队列中的任务 比如主线程有同步任务A异步任务B同步任务C异步任务D同步任务E 那么就先执行ACE再执行BD 例子如下 functionone(){ console.log(1) } functiontwo(){ returnnewPromise(function(resolve){ resolve(2) }) } functionthree(){ console.log(3) } functionfour(){ returnnewPromise(function(resolve){ resolve(4) }) } functionfive(){ console.log(5) } one(); two().then(()=>{ console.log(2) }); three(); four().then(()=>{ console.log(4) });

  • 玩转 Commander.js —— 你也是命令行大师

    最近做团队底层构建工具架构升级和命令行交互打了不少交道,再加上在研究Vue-CLI的源码,觉得Commander.js作为Node.js下这么优秀的命令行交互工具,值得总结一下,文章主体内容搬运了Commander.js的官方文档,对一些晦涩的翻译部分进行了注解和必要的代码注释,适合躺在收藏夹,需要时拿出来查一查。 1.安装npminstallcommander复制2.声明program变量直接引入对象(本文使用的方式):const{program}=require('commander'); program.version('0.0.1');复制创建实例方法:const{Command}=require('commander'); constprogram=newCommand(); program.version('0.0.1');复制TypeScript用法://index.ts import{Command}from'commander'; constprogram=newCom

  • 神经网络基础之可视化和交互式指南!

    作者:夏落,本文内容翻译自jalammar的高赞文章神经网络基础之可视化和交互式指南1.动机我不是机器学习专家。我只是一个受过训练的软件工程师,我很少和人工智能打交道。我一直想钻研更深入的机器学习,但从来没有真正找到“in”。这就是为什么2015年11月谷歌开源TensorFlow的时候,我非常兴奋,知道是时候开始学习了。听起来不太戏剧化,但对我来说,这实际上有点像普罗米修斯从机器学习的奥林匹斯山把火传给人类。在我的脑海里浮现出这样一个想法:当谷歌研究人员发布他们的MapReduce论文时,整个大数据领域和Hadoop等技术都得到了大大的加速。这一次,这不是一篇论文,而是经过多年的发展,他们在内部使用的软件。因此,我开始尽我所能地学习这个主题的基础知识,并意识到需要为在这个领域没有经验的人提供更温和的资源。这是我的尝试。2.出发让我们从一个简单的例子开始。假设你在帮助一个想买房的朋友。她以40万美元的价格买了一栋2000平方英尺(185米)的房子。这个价格合适吗?没有参照系是不容易判断的。所以你问你的朋友谁在同一个社区买了房子,你最终得到三个数据:Area(sqft)(x)Price(

  • 将多个Celery定时任务添加到Systemd

    当多个celery定时任务都需要开机自动启动,所以都需要添加到systemd,但在/etc/conf.d/下只有一个配置文件,肯定不可能多个定时任务共用同一个配置文件.本文介绍同一台服务器上多个celery定时任务加入systemd管理的配置方法和步骤. 一、设置pythoncelery项目的配置1.在/etc/conf.d/目录下复制之前的celery配置文件(第一个定时任务的celery配置,参考上一篇Celery增加到Systemd配置),修改文件名为celery_demo(与已有的不重复),修改配置文件中的相关内容,具体如下#work_demo CELERYD_NODES="work_demo" #orwecouldhavethreenodes: #CELERYD_NODES="w1w2w3" #Celery CELERY_BIN="/usr/local/bin/celery" #CELERY_BIN="/virtualenvs/def/bin/celery" #Appinstancetouse #

  • 听说MongoDB你很豪横?-------------MongoDB数据库基础详解

    文章目录一、MongoDB相关概念1、业务应用场景2、MongoDB可应对“三高"需求。3、什么时候选择MongoDB?二、MongoDB简介1、体系结构2、数据模型三、MongoDB的特点四、安装MongoDB1、配置本地yum源2、yum安装3、修改配置文件4、启动mongodb5、进入MongoDB数据库五、数据库简单的操作命令1、选择和创建数据库2、数据库的删除3、集合的隐式创建与删除4、插入数据5、更改数据六、导入导出1、导出school库的info表:2、查看导出文件:3、导入:(导入一个新表info2,如果表不存在,会新建这个表)4、进入数据库验证5、基于条件的导出:(导出info表里id=10的记录)七、备份恢复八、克隆1、克隆数据库2、克隆集合(表)一、MongoDB相关概念1、业务应用场景传统的关系型数据库(如MySQL),在数据操作的"三高需求以及应对Web2.0的网站需求面前,显得力不从心。 解释:“三高”需求: ●Highperformance-对数据库并发读写的需求。 ●HugeStorage-对海量数据的高效率存储和访问的需求。 ●Hi

  • Android开发 - 汉字转拼音首字母

    概述工作中经常会遇到的一些排序问题,比如按汉字的拼音首字母排序,比如人名排序等,就要用到下面的方法了,思路:1.获得汉字2.将汉字转换成首字母,并记录下(必要时保存到数据库)3.按首字母进行排序并展示演示控制台输出演示:汉字转首字母演示,请输入汉字:4654*&&^_FDSF你i好3啊>?>?>(*33P{}{直接转换convertTo:4654*&&^_FDSFnih3a>?>?>(*33P{}{ 保留一些字符convertAndClear:4654&&^_FDSFnih3a>?>?>(33P{}{ 仅保留字母和数字convertAndClearAll:4654FDSFnih3a33P实现代码如下,直接复制后就能使用:packagepinyin; importjava.util.Scanner; publicclassMain{ publicstaticvoidmain(String[]args){ Scannersc=newScanner(System.in); System.

  • Centos 配置eth0 提示Device does not seem to be present

    一.故障现象:[root@c1node01~]#servicenetworkrestartShuttingdownloopbackinsterface:[OK]Bringinguploopbackinsterface:[OK]Bringingupinterfaceeth0:Deviceeth0doesnotseemtobepresent,delayinginitialization.[FAILED]解决办法:[root@c1node01~]#rm-rf/etc/udev/rules.d/70-persistent-net.rules[root@c1node01~]#reboot………………[root@c1node01~]#servicenetworkrestartShuttingdownloopbackinsterface:[OK]Bringinguploopbackinsterface:[OK]Bringingupinterfaceeth0:[OK][root@c1node01~]#二.另一种方法造成这样的原因,是因为在虚拟机(Vmware)中移动了Centos系统对应的文件,导致重

  • 打造前端 Deepin Linux 工作环境——调节鼠标滚轮速度

    打造前端DeepinLinux工作环境——调节鼠标滚轮速度在deepin的系统设置里面,没有找到鼠标滚轮速度调节的选项。但是默认情况下,其滚轮的速度又特别的慢。经过一番搜索,终于解决了这个问题。安装imwheel首先执行sudoapt-getinstallimwheel-y复制安装imwheel软件。创建调整脚本#创建自定义脚本目录 mkdir~/.bin/ #创建并编辑我们的脚本文件 vim~/.bin/setwheel复制然后在文件中粘贴进去以下代码:#!/bin/bash #Version0.1Tuesday,07May2013 #Commentsandcomplaintshttp://www.nicknorton.net #GUIformousewheelspeedusingimwheelinGnome #imwheelneedstobeinstalledforthisscripttowork #sudoapt-getinstallimwheel #Prettymuchhardwiredtoonlyuseamousewith #left,rightandwheelinthemi

  • Django学习目录

    Django基础一之web框架的本质 Django基础二之URL路由系统 Django基础三之视图函数 Django基础四之模板系统 Django基础五之django模型层(一)单表操作 Django基础五之django模型层(二)多表操作 Django学习之model进阶 Django基础六之ORM中的锁和事务 Django基础七之Ajax Django基础八之cookie和session Django基础九之中间件 Django基础十之Form和ModelForm组件 Django基础之django分页 Django基础之jQuery操作cookie Django基础十一之认证系统 Django学习之文件上传 Django学习之文件下载 Django学习之django自带的contentType表 Django学习之Django-debug-toobar Django学习之缓存和信号 Django学习之完成数据库主从复制、读写分离和一主多从情况下的使用办法 DjangoRestFramework学习一之restful规范、APIview、解析器组件、Postman等 DjangoR

  • 2020及2021年小记:编辑器与衍生的时代

      去年偷了个懒,忘记写年度小记了,现在两年过去了,确实发生了太多事情了。   这两年来,编辑器经历了很大的变化,也做了很多款demo,从19年底的百魂,到20年开始的军团制方向,类似moba的竞技场的demo,到21年上半年大世界的demo,到后来快速迭代的自走棋玩法,属实变化很大,自走棋这款确实比较不错,目前自己也比较满意,但是能不能成也属于另外一回事了。   项目组有了自己的名字,不再被叫做新项目了,一开始叫做W3,自走棋后被称为W4,最后统一称为重骑兵工作室,以后开发的所有游戏都归于重骑兵工作室名下。   这两年的人员变动也挺大的,当初19年底颐久的离开,在20年中又回到了项目组,同时20年大黑加入了团队,带领我们制作“最好的军团制手游”,不过后来成为了RO的制作人,在W3这边花费的时间就变少了。另外,仓鼠也在20年初加入了项目组。   关于技术这方面,没有像以前一样提升那么快了,不过越来越找到了学习的方向,图形学应该是近几年都要学习的核心,其他方面的知识以涉猎为止,不过今年对C#和IL的学习也比较深入,我的IL学习终于步上正轨了哈哈,而且今年基于IL自动深拷贝和深比较工具性能

  • 关于js框架 dwz 与 yii的的分页 以及筛选的结合

    此为jicheng1014原创。。。。地址为http://jicheng1014.cnblogs.com dwz是一个不错的前端框架 但是注意 所有的后端 都是要自己写的    常见的应用是 有一堆条件作为筛选,之后下面是一个表,如果数据量大的话 就涉及到了分页  由于dwz是前端框架 所以获取数据什么的 就需要自己写了     分页前端其实只需要知道4个东西  1、当前页面 2、当前数据 3、每页的大小 4、数据的行数       但是其实Yii里本身就有自己的数据显示控件CGridview,理论上应该是封装了分页需要的所有动作,那么怎样把Yii和Dwz的数据结合起来?、 答案是 CActiveDataProvider 这个对象  即model里search的返回 因为这个Provider里面有个属性,Pagination,很明显,那存放的是关于分页的信息。

  • nginx部分命令

    启动nginx startnginx复制 停止nginx nginx-sstop复制 重启nginx nginx-sreload复制 查看版本信息 nginx-v 大写V是查看配置信息复制 查看nginx进程 tasklist/fi"imagenameeqnginx.exe"复制  关闭nginx nginx-squit复制  

  • 【SSM】Eclipse使用Maven创建Web项目+整合SSM框架

    自己接触ssm框架有一段时间了,从最早的接触新版ITOO项目的(SSM/H+Dobbuzk),再到自己近期来学习到的《淘淘商城》一个ssm框架的电商项目。用过,但是还真的没有自己搭建过,一直都是用别人搭建好的。所以,从网上找了一些材料,结合自己来解决过程中的一些问题,使自己对ssm框架理解更加深了,不为分享,只是总结一下,下次有机会再搭建的时候,直接看自己的博客,省得找了!   一、准备环境: maven:apache-maven-3.2.3 jdk:jdk1.8.0_25 tomcat:tomcat-6.0.37 二、配置Maven、jdk 1、Window——>Preferences——>Maven——>设置自己的Settings 2、Window——>Preferences——>Java——>InstalledJREs——>Add 配置好maven之后,就可以在本地设置好的地方看到对应的Maven文件了,还有包含resp文件夹   三、新建Maven项目: 1、右击——>New(或者是File——>New

  • 蓝桥杯省赛备战笔记—— (三)使用sort排序

    需要载入头文件 #include<algorithm>复制 一、使用 #include<iostream> #include<algorithm> usingnamespacestd; intmain(){ intarr[]={2,4,5,3,1}; //sort(arr,arr+5); sort(arr+1,arr+4); for(inti=0;i<5;i++) cout<<arr[i]<<''; return0; }复制 sort(arr,arr+5)  ————(数组名,数组名+长度)——将整个数组从小到大排序 sort(arr+i,arr+j)————将arr[i]到arr[j-1]排序,其余元素保持原位置不变 如果希望arr中的元素从大到小排序(或按照某一个规则排列),传入第3个参数——”排序方法“ sort(arr,arr+5,greater<int>());复制 <int>表示待排序的数组中的元素类型为int    例题:前

  • 体积很小的vsftpd_pureftpd_docker_在unraid中的配置_支持TLS和ipv6(图文)

    体积很小的vsftpd_pureftpd_docker_在unraid中的配置_支持TLS和ipv6 转载注明来源:本文链接来自osnosn的博客,写于2022-06-02. 当需要,传大量的文件(并且有多层目录结构)给朋友的时候, 可以建个ftp服务,使用专用账号,加密传输。 家里的宽带已经有公网ipv6了。 把文件放家里,共享出去,让朋友方便的时候自己下载。 如果你用的不是unraid。但能装docker。此文也能参考。 配置环境 unraid6.9.2。 安装docker镜像bfren/ftps 是vsftpd-3.0.5,支持tls-1.3,只有一个账户,ipv4和ipv6可以同时工作。如果注重安全,推荐这款。 支持"TLS数据连接会话恢复",这项似乎有更好的安全性,性能也比pureftpd好一些。 【YourFTP/SSLsolutionisreallysecure,right?】【CESA-2008-002-rev1】 没有ftpwho命令。只能通过ps,netstat-an间接了解在线连接数。 镜像包7.4MB,安装完占用18.7MB。 在unraid的APPS中搜

  • [Umbraco] Data Types介绍

    DataTypes是在建立documenttype时需要用到的,系统自带了很多用于开发的类型,如常用的下拉列表dropdown,textbox,radiobox,checkbox以及上传,html编辑器等等。但是这些往往还并不能满足我们的需要。   例如dropdown来源于某一数据库中的表时,显然系统不能帮助我们解决这些,那怎么办呢?umbraco不会让我们办法的,在创建一个新的DataType时,Rendercontrol选择如图 这样就可以开发自己的控件了 在vs里创建一个web应用程序,新建web用户控件   在ascx里放一个dropdown控件,并命名为ddlUser   cs文件里我们需要引用一下 usingumbraco.editorControls.userControlGrapper;   继承IUsercontrolDataEditor接口并实现其属性,控件的cs代码如下 1publicclassUserList:System.Web.UI.UserControl,IUsercontrolDataEditor 2{ 3

  • 程序员的算法课(8)-贪心算法:理解霍夫曼编码

    版权声明:本文为博主原创文章,遵循CC4.0BY-SA版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/m0_37609579/article/details/100024908 一、一种很贪婪的算法定义 贪心是人类自带的能力,贪心算法是在贪心决策上进行统筹规划的统称。 【百度百科】贪心算法(又称贪婪算法)是指,在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,他所做出的是在某种意义上的局部最优解。 二、贪心跟动态规划 贪心选择 贪心选择是指所求问题的整体最优解可以通过一系列局部最优的选择,即贪心选择来达到。这是贪心算法可行的第一个基本要素,也是贪心算法与动态规划算法的主要区别。贪心选择是采用从顶向下、以迭代的方法做出相继选择,每做一次贪心选择就将所求问题简化为一个规模更小的子问题。对于一个具体问题,要确定它是否具有贪心选择的性质,我们必须证明每一步所作的贪心选择最终能得到问题的最优解。通常可以首先证明问题的一个整体最优解,是从贪心选择开始的,而且作了贪心选择后,原问题简化为一个规模更小的类似子问题。

  • 深入JSP学习

    常规JSP JSP页面最终会由容器来生成Servlet类的,比如Tomcat容器生成JSP的Servlet类放在work目录里。因此在JSP里可以用很多简化的语法供容器使用,这篇就来整理一下。 JSP语法 scriptlet:<%%> 可以在里面写Java代码,如<%out.print("27");%>; 指令:<%@%> 可以在页面转换时向容器给出特殊的指示;它有三个指令:page、include和taglib;而指令又有很多属性如import是page的属性:<%@pageimport="foo.*,java.util.*"%>; 表达式:<%=%> 表达式会成为out.println()或out.print()的参数,因此<%=27%>等价于<%out.print(27);%>; 声明:<%!%> 是JSP转换成Servlet类的声明,因此可以声明类变量(静态变量)、实例变量、方法等; 注释:<%--%&

  • python集合相关操作

    集合相关操作 集合是一个无序的,不重复的数据组合,它有着两个主要作用:去重以及关系测试。 去重指的是当把一个列表变成了集合,其中重复的内容就自动的被去掉了 关系测试指的是,测试两组数据之间的交集、差集、并集等关系。 去重测试代码如下: #创建一个列表--里面存在一些重复值 test_list=[1,2,3,4,2,2,3,4,3,2,3,4] #利用集合将列表中重复的内容去掉 test_list=set(test_list) #打印测试并且查看test_list被赋予新值后的数据类型 print(test_list,type(test_list))#{1,2,3,4}<class'set'>复制   Tip:需要注意的是,集合和字典一样都是无序的。 获取交集需要使用集合中的方法intersection方法,获取两个集合中的交集代码如下: #创建两个集合,并且获取集合的交集 test_list_01=set(['YanYan','LiBai','LuLu','YangMi']) test_list_02=set(['YanYan','LiuDeHu

  • redis--迁库操作

     如果碰到redis库要迁移(之前的redis用作他用)或者备份用,就需要操作redis迁移   importredis defqianyi(k=None,v=None,name=None): r1=redis.Redis(host='1',password="123456",port=6379,db=0)#读 r2=redis.Redis(host='7',password="123456",port=6379,db=1)#取 res=r1.keys() forkinres: ifr1.type(k)==b'string':#判断是不是string类型,加b因为返回的都是b类型复制   v=r.get(k)r2.set(k,v)else:hash_data=r1.getall(k)#返回一个字典  fork2,vinhash_data.items():    r2.hset(k,k2,v)复制   不深思则不能造于道。不深思而得者,其得易失。

  • react-native DatePicker --- &#39;react-native-datepicker&#39; 小坑

    经常需要二级联动的日期上面,DatePicker在模拟器和真机上面有一点小差别, 我们经常需要截止时间不小于开始时间,在模拟器上, 开始时间 结束时间,但是结束时间可以比开始时间提前一天! 在真机上测试时,就是正常的。 <DatePicker style={{width:pTd(130)}} date={this.state.createTimeStart} mode="date" placeholder="生产日期" format="YYYY-MM-DD" minDate="2016-05-01" maxDate="2040-06-01" confirmBtnText="Confirm" cancelBtnText="Cancel" customStyles={{ dateIcon:{ display:'none' }, dateInput:{ height:pTd(32), //marginLeft:36 } //...Youcancheckthesourcetofindtheotherkeys. }} onDateChange={(date)=>{ this.se

相关推荐

推荐阅读