1. 为什么大家突然都在问“滚动长截图”?先厘清真实痛点
先说个我自己的经历。有次要给客户整理一份后台管理页面的完整功能截图,页面大概有两千多像素高,数据列表带分页,顶部还有固定导航栏。我试过浏览器自带的截图插件、试过切换到移动端模式、试过按 F12 把浏览器窗口拖长再截,最后折腾了快二十分钟,截出来的图要么底部被裁掉,要么导航栏被折叠,要么图太长导致微信发送后直接被压缩成看不清的细条。后来换用影刀RPA写了个自动化滚动截图流程,从配置到跑完,不到三分钟,导出的 PNG 横平竖直,每一行数据都完整。
很多刚接触影刀RPA的朋友会问:截图这种“小事”不是有很多现成工具吗,为什么非要用 RPA?这里面的核心区别在于——通用截图工具只能截“当前视口可见的内容”,而长截图需要的是“视口之外的完整内容”。网页也好,桌面软件也好,当信息超过一屏时,都需要先“滚动”,再分段截图,最后拼合成一张完整的长图。而“滚动”这个动作,在不同场景下触发方式完全不同:网页可以用脚本驱动、可以用 End 键、可以用鼠标滚轮;桌面软件则可能只响应鼠标滚轮,或者只响应拖拽滚动条,甚至表格控件有自己独立的滚动逻辑。
影刀RPA在这个问题上的价值,恰恰在于它把“操作浏览器”“操作鼠标键盘”“调用截图接口”这些能力打通了。你不需要懂前端脚本,不需要会 C# 写桌面截图,很多情况下只需要把现成的指令块拖拽组合起来,就能覆盖“网页+桌面软件”大多数长截图需求。
另外我注意到搜索热词里反复出现“滚动截屏自动拼接原理”这个词,说明很多人不只是想要一个傻瓜式点击按钮的教程,还想理解这背后的逻辑。这篇文章我打算从原理讲起,再分别给出网页场景、桌面软件场景、横纵双向滚动场景的完整实现方案,最后补充一些参数调优和异常处理的踩坑记录。无论你是刚装好影刀的新手,还是已经用过一段时间但没搞过滚动截图的开发者,都可以直接照着做。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 从原理上拆解“自动滚动长截图”:三步循环与拼接逻辑
2.1 长截图的基本构成:滚动、截屏、拼拼图
不要被“长截图”三个字吓住,拆开了其实就是三件事的组合:
- 把内容区域移动到一个起始位置(通常是顶部或左上角)。
- 截取当前可见部分的图片。
- 触发滚动操作,让视口移动到下一块区域,再次截图。
- 重复第 2、3 步,直到内容被完整覆盖。
- 把所有截图按照滚动偏移量拼接成一张完整图片。
这个过程用一句话概括就是“分段采样、按序拼接”。
这里为什么强调“按序拼接”而不是“随便拼”?因为如果拼接顺序错乱,或者滚动偏移量和截图高度不匹配,就会出现内容重叠或断层。比如你的屏幕截图高度是 800 像素,每滚一次正好向下移动 800 像素,那两张图刚好无缝衔接;如果滚动了 1000 像素,那么第二张图会多出 200 像素的重复内容;如果只滚动了 600 像素,第二张图就会漏掉 200 像素的内容。
所以理想情况下,每一步的滚动距离应该等于截图高度。但在实际操作中,由于浏览器页面底部可能有固定元素、表格可能有固定表头、页面可能存在懒加载,所以很难做到绝对的完美对齐。这也是为什么很多成熟的 RPA 长截图流程,最后都会加一个“图像拼接”步骤,通过算法识别重叠区域并自动对齐,而不是简单地把图片首尾相连。
2.2 影刀RPA在这件事里的角色分工
在影刀RPA中,完成长截图并不是靠某一个单独指令,而是多条指令协同:
- “激活窗口”指令:确保网页或桌面软件处于前台状态,避免截图截到其他窗口。
- “滚动”相关指令:影刀提供了滚动网页的专属指令,也有更通用的鼠标滚轮、键盘按键指令,用于桌面软件场景。
- “截图”指令:有“截取屏幕”“截取窗口”“截取元素”等不同维度,按需选择。
- “循环”指令:用条件循环或次数循环组织重复的“滚动+截图”过程。
- “图像拼接”能力:影刀本身没有提供直接拖拽的“长图拼接”指令,通常需要调用外部 Python 代码或专门的图像处理步骤来完成最终合并。
用个生活化的类比:影刀就像一位会操作电脑的助理,你告诉它“每隔 2 秒翻一次页,每次翻完后按一下截屏键”,它老老实实执行完,最后你把几十张截图交给程序拼接。助理负责采集素材,程序负责生成成品。
这个分工很重要,因为很多新手会误以为用影刀一拖,就能直接产出一张完整的长图。实际上「自动滚动截图」和「自动拼接长图」是可以拆开的两个环节。影刀极强的部分是前者,后者我们通常会借助 Python 的 PIL 库来自定义实现——这也是后文要重点讲解的部分。
2.3 滚动距离、截图高度、拼接阀值:三个核心参数的关系
在具体配置前,先记住这三者之间的关系公式:
单次滚动距离 = 截图高度 × 重叠率系数(通常为 0.9~1.0)
为什么要考虑重叠率?因为实际滚动过程中会有精度误差,页面也可能因为图片懒加载导致内容高度动态变化。如果你严格按 1.0 滚动,一旦有一张图因为加载问题缺了一截,后续拼接就会整体错位。而设置 10% 左右的重叠区域,后续拼接可以通过特征匹配来修正误差。
举个例子:假设窗口内容区域高度是 800 像素,你安排每次滚动 800 像素、截取一张 1280×800 的图,理想状态下不需要重叠。但实际上,如果页面在滚动后继续加载了新的图片,整体高度会突然增加,原先规划的次数就不够了。这时你可以把滚动距离设为 720 像素,让每张图和上一张有 80 像素的重叠区,再由拼接脚本做对齐。
影刀中控制这些参数的位置主要在“循环内滚动指令”的属性面板中。网页场景下有“滚动到元素”“滚动指定像素”等细粒度选项,桌面场景下则依靠模拟鼠标滚轮行数来控制单次滚动量。建议先用小参数测试一轮,观察截图的重复区域大小,再决定最终取值。
3. 网页场景方案:利用影刀内置指令实现自动滚动长截图
3.1 最佳实践流程(含指令级配置)
网页是影刀RPA支持最完善的应用场景,因为有浏览器内核的深度集成,滚动截图比桌面软件简单得多。我个人推荐的流程如下:
- 启动浏览器,打开目标网址,等待页面完全加载。
- 点击“网页滚动截图”相关指令(影刀较新版本在“网页自动化”分类下可能直接提供“滚动截图”命令)。
- 如果没有内置指令,则需要手动实现循环:先获取页面总高度或判断滚动条是否到底,再逐步滚动和截图。
影刀在不同版本中,指令名称和分类位置略有差异。我这里介绍一种相对通用、不依赖于特定版本的实现方式,用到的都是基础指令。
先说方案 A——使用“滚动网页”指令配合“截取网页元素”:
- 在“网页自动化”分类中找到“滚动网页”指令,下拉方向选“向下滚动”,方式可以选择“滚动像素值”或“滚动到页面底部”。
- 在“图像自动化”分类中找到“截取屏幕”或“截取指定元素”指令,选择截取目标为“网页窗口区域”。
- 把上述两个指令放进“循环”中。循环次数不要写死为固定值,建议用“条件循环”,判断“是否还能继续向下滚动”,或判断“滚动条位置是否已经到达底部”。
具体可以参考以下配置思路:
text复制1. 打开网页
2. 等待网页加载完毕(等待元素出现,例如页面的标题或某个关键节点)
3. 循环(条件:页面滚动条位置小于页面总高度 - 可视区域高度)
3.1 截取当前视口,保存为 images/截屏_001.png
3.2 记录当前截图序号 +1
3.3 滚动网页(向下滚动 700 像素)
3.4 等待 0.5 秒(让页面渲染稳定)
4. 循环结束
5. 调用 Python 脚本或外部工具拼接所有图片
这里有几个细节需要注意:
- 截取视口而非整页:在“截屏”指令中,不要选择“截取整个网页”,那样会直接得到一张长图,但无法覆盖懒加载场景。我们要的是“当前可见部分”,所以目标应选择“网页窗口”或“当前标签页”。
- 滚动像素和截图高度的匹配:建议滚动像素设置成截图高度的 0.9 倍,比如视口高度约 800 像素,就滚动 720 或 760 像素,留出重叠余量。
- 滚动后等待:尤其是懒加载页面,滚动后必须有 0.3~0.8 秒的等待,否则图片可能还在加载中就截图了。
3.2 怎么判断滚动到底了?推荐用条件循环
在影刀的“条件循环”指令中,可以配置一个条件表达式。网页滚动位置的判断可以通过 JavaScript 表达式来获取,影刀支持在条件中执行 JS:
javascript复制// 获取当前滚动位置
window.scrollY
// 获取页面总滚动高度
document.documentElement.scrollHeight - window.innerHeight
当 window.scrollY >= 页面总滚动高度 - 视口高度 时,说明已经到底。
不过这里有个小坑——如果目标网站用了自定义滚动容器(比如 div 内部滚动,而不是整个浏览器窗口滚动),上述 window.scrollY 永远拿不到正确位置。这时候需要先定位到那个可滚动的元素,用元素自身的 scrollTop 来判断。影刀中可以通过“执行 JavaScript 脚本”指令传入元素选择器,再读取属性值。
我的建议是,条件尽可能写成“防御性”的:假设最多循环 50 次,条件同时判断“是否到底”和“是否超过最大次数”,防止异常情况下无限循环。
3.3 懒加载页面和动态加载内容的处理技巧
现在很多后台系统、数据大屏页面都是懒加载的,滚动到某一位置后才触发新内容的加载。对于这类页面,单纯按固定次数滚动截图,容易出现下半部分空白或内容缺失。
处理思路有两种:
- 做两次滚动:第一遍快速滚动到页面底部,触发所有懒加载内容加载完成,再回到顶部,开始真正的逐段截图。这种做法“以空间换时间”,适合内容较多且加载快的页面。
- 逐段滚动并等待:每滚一次后,等待页面加载完成——可以通过判断某个“加载状态元素”消失,或者等待网路请求停滞,但这在 RPA 中比较难精确判断。一个折中的办法是固定等待 1~2 秒,适合内容加载时间稳定的内部系统。
我实际经验是,对绝大多数后台系统,“先滚到底,再回顶部,再逐段截图” 的成功率最高。虽然多花了一点时间,但很少出现截图内容缺失。
另外,如果页面上有“回到顶部”按钮,可以在第二遍滚动前直接点击它;如果没有,就模拟按键盘 Ctrl+Home 或执行 JS window.scrollTo(0,0)。
3.4 网页场景完整示例:一个可视化的配置步骤
假设我们想截取某个新闻资讯页面的完整长图,页面内容包括顶部大图、文章列表、底部推荐。具体操作如下:
- 打开网页后,等待页面中出现“正文内容”这个元素。
- 执行 JS
window.scrollTo(0, document.body.scrollHeight),等待 2 秒。 - 再执行 JS
window.scrollTo(0,0),等待 0.5 秒。 - 定义变量
index = 1,开始条件循环:
text复制条件:window.scrollY < 页面总滚动高度 - 600
1. 截取当前视口,保存为 "screen_" + index + ".png"
2. 滚动网页向下 600 像素
3. 等待 0.6 秒
4. index = index + 1
这样一轮下来,少则十几张、多则几十张截图会被保存到指定目录,最后再用 Python 按顺序拼接即可。
4. 桌面软件场景:没有内置指令时怎么玩转滚轮+截图
4.1 为什么桌面软件比网页更麻烦?
网页有标准化的 DOM 结构和滚动机制,影刀可以精准获取页面高度、滚动位置。但桌面软件五花八门:有些是 Electron 套壳的(内部其实是网页),有些是 MFC/WPF 写的原生程序,有些是 Java Swing 写的。软件内的滚动组件可能是系统标准滚动条,也可能是自绘的滚动区域,甚至是表格控件内部的滚动条。
这就导致影刀在桌面软件中,没有一个“读取总高度”的通用方法。面对桌面软件,我们能做的只有几件事:
- 激活窗口并固定窗口位置和大小。
- 模拟鼠标滚轮滚动。
- 截取窗口区域或截取整个屏幕。
- 通过判断屏幕像素变化判断滚动是否结束。
4.2 核心思路:固定窗口+滚轮滚动+循环截屏
桌面软件的滚动截图,我推荐这样设计:
- 利用影刀“启动软件”或“激活窗口”指令,把目标软件置于前台。
- 用“设置窗口状态”指令,把窗口最大化或调整到一个固定尺寸。这一步非常重要,因为窗口尺寸一旦变化,截屏区域就会错位。
- 把鼠标移动到内容区域中心,模拟一次滚轮滚动(向下滚动 3~5 格)。
- 截取整个窗口,或截取屏幕上固定的一块区域。
- 重复第 3、4 步,直到内容不再变化。
判断内容不再变化,是桌面软件长截图的难点。通常有两种判断方法:
- 像素比对法:截取当前屏幕后,与上一张截图做相似度比较,如果相似度超过 95%(因为鼠标或动态元素可能造成微小变化),就认为已经滚动到底部。
- 固定次数法:根据以往经验,估算目标内容大概有几屏,设置一个固定的循环次数。适用于内容数量相对固定的报表或文档阅览器。
影刀中可以通过“计算图像相似度”或“调用 Python 脚本”来实现像素比对。如果你不想引入 Python,可以在影刀里用“条件循环”配合“图像变化检测”技巧——但实际测试下来,响应速度不如 Python 直接处理。
4.3 某些软件滚动指令无响应怎么办?——用鼠标滚轮和键盘按键兜底
如果你试过影刀的“滚动窗口”或“滚动鼠标滚轮”指令,在某个软件上没反应,大概率有两种原因:
- 鼠标指针不在正确的滚动区域内。
- 目标软件聚焦的控件不支持滚轮滚动,而是需要拖拽滚动条。
其中第一种原因最常见。解决办法是先把鼠标移动到目标内容区域正中央,再执行滚轮指令。影刀中可以用“鼠标移动”指令,移动到指定坐标或相对偏移,然后再“鼠标滚轮”。
第二种情况需要模拟拖拽滚动条。影刀有“鼠标点击”和“鼠标拖拽”指令,你可以先定位到滚动条滑块的位置,按住左键,拖到目标位置,然后松开。这个方案比较考验坐标定位,成功率取决于滚动条是否标准。若软件是用 Qt 或 WPF 自绘的滚动条,拖拽也需要选择正确的“滑块元素”作为拖拽点。
还有一种比较取巧的办法:很多桌面软件都支持键盘操作,比如上下方向键可以移动焦点、PageDown 可以翻页。你可以直接模拟按下“向下翻页键(PageDown)”,再截图。这种方式对表格类软件特别有效,因为方向键通常被原生支持。
实际做过的项目中,我用“模拟鼠标滚轮+键盘 PageDown 双通道”兜底,处理过一款老旧的医药库存管理软件(MFC 程序),效果很稳。
4.4 桌面软件长截图示例:以 PDF 阅读器为例
假设我们要在某个 PDF 阅读软件中,将一本书的前 50 页截图保存为长图:
- 打开 PDF 文件,激活阅读器窗口。
- 窗口最大化。
- 设置“显示方式”为“连续滚动”(如果软件支持),这样页面会纵向连续排列。
- 循环 50 次:
- 鼠标移动到阅读区域中央。
- 向下滚动鼠标滚轮 5 格(或按 PageDown)。
- 等待 0.3 秒。
- 截取窗口区域,保存。
- 拼接图片。
这种方式原理很简单,但注意 PDF 阅读器通常有工具栏、侧边栏,截取窗口时会包含这些无关内容。如果想更干净,可以用“截取屏幕区域”而不是“截取窗口”,把坐标范围限定到正文区域,效果更好。
5. 横纵双向滚动:从需求到实现,能横向就不将就
5.1 什么场景需要横向滚动截图?
很多人没意识到“横向滚动截图”的需求其实很常见。比如前端页面有横向图表(数据大屏常见)、Excel 表格列数过多、代码编辑器的行很长、设计稿预览时横向超出屏幕。
横向滚动截图和纵向长截图原理完全一致,只是滚动方向从“向下”改成“向右”,截图拼接时的坐标系从纵向改成横向。但实际做起来比纵向麻烦很多,因为大部分网页的横向滚动条不在默认视口内,需要先检查是否存在横向滚动,再决定滚动到哪个容器。
5.2 影刀中实现横向滚动的两种方式
网页场景下,横向滚动依然可以用 JavaScript 驱动。定位到有横向滚动条的元素,设置它的 scrollLeft,就是向右滚动。
javascript复制// 让页面横向滚动到指定位置
window.scrollTo(500, 0);
// 如果是特定容器,例如 id 为 data-panel 的 div
document.getElementById('data-panel').scrollLeft = 500;
如果是在桌面软件中,则用“鼠标滚轮 + Shift 键”这个经典组合。Windows 下,按住 Shift 键滚动鼠标滚轮,可以触发横向滚动。影刀中可以用“键盘按键”指令按下 Shift,再用“鼠标滚轮”指令滚动。
实际操作时有一个细节:必须先按下 Shift 键,再滚动滚轮,滚动完成后松开 Shift。如果顺序反了,系统可能识别不到横向滚动意图。
5.3 横纵双向结合:双循环嵌套方案
如果你的目标场景既需要纵向滚动,又需要横向滚动,比如一个超宽的报表页面,或者一个大画布工作区,那么需要两个循环嵌套:
- 外层循环:纵向滚动,从顶部到底部。
- 内层循环:横向滚动,从左侧到右侧。
我画一个逻辑流程给你参考(这里用文字描述,不用图表):
text复制1. 先回到左上角初始位置。
2. 外层循环(纵向未到底时执行):
2.1 内层循环(横向未到最右时执行):
a. 截图保存
b. 向右滚动一个固定宽度
c. 等待页面稳定
2.2 内层结束后,向下滚动一个固定高度
2.3 回到横向最左侧(scrollLeft = 0)
这套逻辑的要点在于:每一行横向截图完成后,必须先回到最左侧,再向下滚动。否则,下一行截图会从上一行结束的右侧位置开始,完全错乱。
举个例子,一个内容实际宽度为 3000 像素、高度为 2000 像素的页面,屏幕可视区域为 1000×800。那么横向需要截 3 段(1000+1000+1000),纵向需要截 3 段(800+800+400),总共 9 张图。拼接时按 3×3 网格排列。
5.4 横向滚动常见的坐标定位坑
在影刀中,直接使用“鼠标滚轮+Shift”进行横向滚动时,必须确保鼠标指针悬浮在目标内容区域上。如果鼠标在一个不响应水平滚轮的区域(比如页面空白处),即使按下 Shift 也可能没有反应。
还有一类特殊场景:某些地图类应用、画布类工具,它们没有标准的滚动条,而是通过“鼠标拖拽”来平移视图。这种情况下,更可靠的做法是模拟“鼠标中键拖拽”或“按住空格键+鼠标左键拖拽”,这些交互模式在大型设计软件和地图应用中非常常见。
6. 图片拼接实战:不借助外部截图工具的 Python 方案
6.1 为什么建议用 Python 而不是影刀自带功能?
到写这篇文章时,影刀本身并没有提供一个非常通用的“长截图自动拼接”指令。虽然部分版本中有“图片拼接”相关功能,但这个指令在社区反馈中出现较少,而且对大图、大量图片支持不够稳定。
所以我的建议是:让影刀专注做“滚动+截屏”的信息采集工作,让 Python 做“拼接+优化”的后处理工作。两件事分开,各自可控,也方便排查问题。
6.2 一个可直接复用的中文备注版 Python 拼接脚本
下面这段 Python 脚本基于 Pillow 库,功能是把一个文件夹下的多张截图,按文件名顺序纵向拼接。支持设置重叠像素,自动去除重复区域:
python复制import os
from PIL import Image
def vertical_merge_images(image_folder, output_path, overlap=20):
"""
纵向拼接长图
image_folder: 存放截图的文件夹,图片按文件名排序
output_path: 输出文件路径
overlap: 重叠像素,用于去除相邻图片的重叠区域
"""
files = [f for f in os.listdir(image_folder) if f.lower().endswith(('.png', '.jpg', '.jpeg'))]
files.sort() # 按文件名排序,注意截图命名要带序号
if not files:
print("文件夹中没有图片")
return
images = [Image.open(os.path.join(image_folder, f)) for f in files]
width = max(img.width for img in images)
total_height = sum(img.height - overlap for img in images) + images[0].height
# 创建空白画布
canvas = Image.new('RGB', (width, total_height), (255, 255, 255))
y_offset = 0
for i, img in enumerate(images):
# 第一张图完整贴入,之后的图从 overlap 像素后开始
if i == 0:
canvas.paste(img, (0, 0))
y_offset = img.height - overlap
else:
canvas.paste(img, (0, y_offset))
y_offset += img.height - overlap
canvas.save(output_path)
print(f"拼接完成,保存至 {output_path},总高度 {total_height}px")
# 使用示例
vertical_merge_images("./screens", "./output/long_screenshot.png", overlap=60)
这个脚本做了最简单的纵向拼接。如果你想支持横向拼接,原理一样,只是把坐标从 (0, y) 变成 (x, 0),再把总宽度累加。
6.3 更智能的拼接:通过像素特征对齐消除错位
上面这个脚本是“机械拼接”,假设每张图之间的重叠量是恒定值。但实际滚动截图时,滚动距离可能因为页面加载、卡顿等原因,导致每次实际滚动量和预期不一致。这时候,就需要“特征对齐”了。
一个简单可行的方案:比较相邻两张图在重叠区域内的像素相似度,找到最佳对齐偏移。比如你预期重叠 60 像素,实际可能是 40~100 像素,那么循环跑一遍这个范围,找到使两张图重叠区域像素差异最小的偏移量,再以此偏移为准拼接。
这个逻辑用 Python 实现也不算复杂,但代码量会多一些。考虑到影刀配合 Python 执行时有一定性能开销,如果每张图都做全图对齐计算,总耗时可能很长,所以我个人建议:
- 在可控场景(内部系统、企业软件)中,使用“固定重叠量”即可。
- 在不可控场景(公网网页、动态内容较多)中,使用“特征对齐”。
6.4 拼接前做好三件小事,能帮你省几个小时
第一,文件命名必须有序。影刀中给截图命名时,建议使用纯数字序号,且用“补零”方式保证排序正确,比如 001.png、002.png……而不是 1.png、10.png、2.png。否则排序会乱。
第二,截图格式用 PNG 不要用 JPG。长图拼接过程中涉及多次像素复制,PNG 无损压缩能避免细节失真。尤其是包含文字内容的界面,JPG 压缩后文字边缘容易出现锯齿。
第三,预留至少 50 像素的重叠区域。哪怕你觉得自己滚动非常精准,也建议保留重叠。因为很多软件在滚动过程中有惯性动画,截图时刻可能比目标位置偏移一些。
7. 实测中的几个参数建议与异常处理
7.1 延迟时间的控制:不是越长越好
滚动截图最常见的失败原因,就是滚动后立刻截图导致内容尚未渲染。网上很多教程会建议“等待 1 秒”,但实际中不同页面加载速度差异巨大。一例是内部管理系统,页面滚动后 200 毫秒内就能渲染完成,等待 1 秒纯属浪费时间;另一例是数据可视化大屏,图表数据异步加载,滚完等 2 秒都有可能只看到 loading。
我给的建议是分两段设置:
- 初始等待(滚动前):0.3 秒。
- 滚动后稳定等待:0.5~1.5 秒,按页面复杂度调整。
影刀中可以直接用“等待”指令,简单粗暴,也可以配合“等待元素可见”来做动态等待——但这种方法需要你判断页面上某个“数据已加载”的元素,如“表格行数变化”等,配置起来更麻烦。
7.2 滚动步长与截图高度匹配的实测记录
我把自己测试过的几组参数记录分享一下,不是标准答案,但可以帮你少走弯路:
| 场景 | 可视区域高度 | 单次滚动像素 | 重叠像素 | 结果 |
|---|---|---|---|---|
| 普通资讯网页 | 800 | 720 | 80 | 稳定 |
| 后台表单页面(带固定顶部栏) | 800 | 680 | 120 | 稳定,但需减去顶部栏高度 |
| 数据大屏(懒加载) | 900 | 850 | 50 | 偶尔丢底部,需等待 1.5s |
| PDF 阅读器(桌面软件) | 950 | 900 | 50 | 稳定,但连续滚动时内容可能闪烁 |
| Excel(横向长表格) | 视口 1200 | 横向 1100 | 100 | 稳定 |
注意,在带有固定顶部导航栏或底部操作栏的网页中,每张截图的顶部会包含固定导航栏,如果直接拼接,导航栏会重复出现很多次。解决思路是:让截图区域不要包含顶部固定栏,方法是用“截取指定元素”而不是“截取整个窗口”,或者把窗口内容区域往上移动一个导航栏的高度,但这样会影响滚动判断。
一个更简单粗暴的做法是:在拼接时统一裁剪掉每张图顶部和底部的固定区域,再执行拼接。这个可以在 Python 拼接脚本里完成。
7.3 截图过程中鼠标挪位置了怎么防干扰
桌面软件场景下,如果你的流程里用到了鼠标滚轮或鼠标移动,那么在“截图”这个动作发生前,一定要确保鼠标没有遮挡内容区域。
我处理过的方案是:在截图前,把鼠标移动到一个不遮挡内容的角落,比如窗口左上角或标题栏上,然后再截图。影刀“截取屏幕”指令默认会包含鼠标指针吗?实测中不一定,但为了保险起见,建议统一鼠标位置后加一个极短的等待(0.1 秒),再触发截图。
7.4 拼接后图片发暗或发白?多半是动态效果的锅
这个细节很隐蔽。网页中如果存在跑马灯、闪烁图表、自动轮播的广告位,那么截取出来的连续图片中,这些区域的内容会不同,拼接后视觉上会出现“断层”或“颜色突变”。
如果你截的是普通文档页面,通常不会遇到;但如果你截的是实时监控面板、股票行情页,请提前和需求方确认:这些动态区域截图后本来就是错乱的,一般要接受,或者尝试关闭动画、暂停轮播后截图。
8. 如果影刀内置指令满足不了需求,可以写一个自定义扩展
8.1 影刀调用 Python 的标准姿势
影刀支持“调用 Python 脚本”指令,你可以在本地写好脚本,然后用影刀传入参数、执行、接收返回值。
经典的组合方式是:
- 影刀负责:打开网页、获取页面信息、滚动、截图命名。
- Python 负责:图像拼接、图片压缩、特征对齐。
在影刀指令中,使用“执行 Python 代码”,把代码粘贴进去,或者通过“Python 文件”方式引用外部文件。注意执行环境要统一,建议在影刀设置中指定一个独立的 Python 解释器,避免牵一发动全身。
8.2 实现“判断滚动是否结束”的一个轻量思路
在 Python 拼接之外,还有一个常用功能值得自动化:判断当前截取的图片和上一张图片是否高度相似。如果相似,说明滚动没有生效或已到末尾。
这个功能可以直接在影刀中结合“图像处理”实现,也可以用 Python 脚本:
python复制from PIL import Image
import numpy as np
def similarity(img1_path, img2_path):
img1 = np.array(Image.open(img1_path).convert('L').resize((200, 200)))
img2 = np.array(Image.open(img2_path).convert('L').resize((200, 200)))
diff = np.mean(np.abs(img1.astype(int) - img2.astype(int)))
return diff
# diff 越小越相似。通常小于 3 说明基本没变化
在循环中调用这个脚本,当 diff 小于阈值时,终止循环。这比固定次数循环智能得多。
8.3 长图拼接后太大?按目标用途做压缩
长截图动不动就是 5000、10000 像素高。如果你要把长图发到企业微信、钉钉或在线文档,很可能被压缩到看不清。我通常会在拼接后,再做一个“分段导出”或“缩小比例导出”的步骤。
比如原图高度 12000 像素,我会按比例缩小到宽 1280 像素,整体高度可能 3000 多像素。这样发出去,文字虽然不一定每处都清晰,但整体内容轮廓完整,接收方能快速浏览。
9. 一个完整的示例流程:从配置到运行,细到每一步
最后我把自己经常用的一套通用流程完整写出来,你可以直接当作模板。假设目标是一个网页版的后台管理页面,需要纵向长截图,内容包含表格和图表。
第一步:新建影刀流程,添加“打开网页”指令,URL 填目标地址。
第二步:添加“等待元素可见”指令,选择页面中的一个关键元素(例如页面标题或表格容器),确保页面加载完毕。
第三步:添加“执行 JavaScript”指令,执行“回到顶部”的逻辑:
javascript复制window.scrollTo(0,0);
第四步:定义一个变量,例如 screen_index = 1。在循环开始前,确保截图保存目录已创建。可以用“创建文件夹”指令。
第五步:添加“条件循环”,条件中执行 JavaScript:
javascript复制window.scrollY < document.documentElement.scrollHeight - window.innerHeight - 100
这个“-100”是防止最后一点点距离反复循环。
第六步:循环内依次放这几个指令:
- “截取网页元素”或“截取屏幕区域”,区域范围固定为当前窗口的内容区。
- 保存文件路径设为“目录/screen_” + screen_index + “.png”。
- “滚动网页”指令,向下滚动 720 像素。
- “等待”指令,等待 0.6 秒。
- “变量操作”,screen_index = screen_index + 1。
第七步:循环结束后,调用前面写的 Python 拼接脚本,把 screen_001.png 到最后一个文件依次拼接。
第八步:输出检查。拼接后的图片如果确认无误,流程结束。
这套流程跑一个 3000 像素高度的页面,大约耗时 15 到 30 秒,具体取决于等待时间。如果是桌面软件,只需把“打开网页”换成“启动软件/激活窗口”,把“滚动网页”换成“鼠标滚轮”,把“执行 JavaScript 判断滚动位置”换成“固定循环次数”或“图片相似度判断”。
我在实际项目里,用这套逻辑已经处理过不少需求:给客户做系统验收截图、给运营做活动页面存档、给开发做页面还原度对比、给产品做需求文档配图。每次都稳定交付。
最后再分享一个小技巧:如果你只是偶尔截一张长图,不想搭完整流程,可以只跑“滚动+截图”部分,把截图交给任何一款长图拼接软件手工处理。但如果你要隔三差五地截——比如每周截一次后台报表页面,那就值得把完整自动化流程建好,一劳永逸。
