滚动内容自动提取
滚动内容自动提取使用文档
自动滚动手机屏幕连续截图,去除相邻截图的重叠区后拼接成长图,再交给 AI 视觉模型分析提取内容,最终导出为 Excel (.xlsx) / Word (.docx) 文档。
目录
- 功能概述
- 三阶段工作流
- 核心算法
- 两种提取模式
- Agent 工具定义
- 使用案例
- 导出格式说明
- 常见问题
功能概述
解决的痛点
| 痛点 | 解决方案 |
|---|---|
| 逐页调 LLM 提取慢、Token 消耗大 | 先本地拼接长图,LLM 调用次数从 N 页降为少量长图分段 |
| 跨屏被截断的条目丢失 | 相邻截图去重叠拼接后条目完整呈现,不再按页丢弃边缘条目 |
| 状态栏 / TabBar 在长图中反复出现 | 行灰度签名自动检测固定 UI 区域并剔除 |
| 不同帧之间的重复数据叠加 | Fingerprint Set 全局去重(分段边界重叠区的重复由指纹兜底) |
| 滑动触底的准确判定 | aHash 感知哈希比较(16×16 灰度降采样,相似度 ≥ 97% 判定触底) |
| 内容加载延迟导致截图不完整 | 每次滑动后等待可配置的 settle 时间(默认 800ms) |
核心能力
- 快速采集:滚动阶段不调用 LLM,只做截图 + aHash 触底检测,速度大幅领先逐页提取
- 本地长图拼接:纯 Canvas 计算,自动剔除固定状态栏/底部栏,精确对齐相邻截图重叠区
- 超长图自动分段:按 4096px 分段输出,段间保留 300px 重叠避免条目被切断
- 双提取模式:Schema 结构化表格模式(Excel/通用)与 richMode 图文模式(Word 专用)
- 任务自动收尾:提取成功后 AI Agent 任务直接结束,不再进入下一轮 LLM 决策
三阶段工作流
与旧版逐页提取的对比
| 维度 | 旧版(逐页提取) | 新版(长图拼接) |
|---|---|---|
| LLM 调用次数 | 1 次 Schema + N 页 × 1 次提取 | 1 次 Schema + 分段数 × 1 次提取(30 屏通常只有 3~5 段) |
| 滚动速度 | 每页需等待 LLM 返回 | 滚动阶段零 LLM 调用,只受 settleMs 限制 |
| 截断条目 | 每页丢弃上下边缘不完整条目 | 拼接后条目完整,无信息丢失 |
| 固定 UI 干扰 | 每页都含状态栏/TabBar | 自动检测剔除,只保留一次 |
screenshots返回值 | 每页原始截图 | 拼接后的长图分段(即实际交给 AI 的图片) |
核心算法
1. 触底判定(aHash 感知哈希)
输入:滑动前截图 A、滑动后截图 B 处理: 1. 将 A、B 分别降采样为 16×16 像素 2. 转为灰度图(加权公式:R*0.299 + G*0.587 + B*0.114) 3. 计算 256 个灰度值的均值 avg 4. 每个像素 >= avg → '1',否则 → '0',得到 256bit 哈希串 5. similarity = 1 - 汉明距离/256 判定:similarity >= 0.97 → 触底,停止滚动2. 行灰度签名(拼接的基础)
每张截图宽度降采样到 48 列 → 逐行取灰度均值 → Float32Array(高度)一次getImageData即可得到整张图的行级特征,后续固定栏检测和重叠匹配都在这个签名数组上进行,避免反复读像素。
3. 固定栏检测(detectFixedBars)
取滑动前后两帧的行签名: 从顶部逐行比较,|差值| < 2 的连续区域 → 固定顶部栏(状态栏/导航栏) 从底部逐行比较,同理 → 固定底部栏(TabBar/输入框) 单侧上限 20% 屏高,防止纯色背景误判拼接时中间帧剔除固定栏;首帧保留顶部(含状态栏),末帧保留底部,保证长图首尾完整。
4. 重叠区匹配(findOverlapOffset)
在前一帧内容区 [topBar, height-bottomBar) 中滑窗搜索: 与当前帧内容区顶部 120 行签名最匹配的位置 matchY 匹配误差 = 窗口内平均灰度差,> 8 视为匹配失败 匹配成功:当前帧从 topBar + (prevEnd - matchY) 行开始为新内容 匹配失败:保留当前帧完整内容区(少量重复由指纹去重兜底)带提前放弃优化(累计误差已劣于当前最优即跳出),30 屏拼接耗时毫秒级。
5. 长图分段(Chunk)
虚拟长图总高 = 各拼接片段高度之和 按 CHUNK_MAX_HEIGHT = 4096px 分段渲染到 Canvas → JPEG (质量 0.85) 段间保留 CHUNK_OVERLAP = 300px 重叠 → 条目不会在分段边界被切断分段原因:视觉模型对超高长图的细节识别能力会下降,且 Canvas 存在尺寸上限。
6. 跨段去重(Fingerprint)
| 模式 | 指纹规则 |
|---|---|
| Schema 模式 | 前 2 个非空字段值 trim 后用|拼接 |
| richMode | 条目文本 trim 后取前 60 字符 |
使用全局Set<string>追踪,分段重叠区 300px 内重复识别的条目会被自动去掉。
两种提取模式
Schema 模式(默认,Excel / both 格式)
- 用首段长图让 LLM 推断列表字段结构(如
{"name":"string","price":"number"}) - 逐段按 Schema 结构化提取 JSON 数组
- 产出
result.items(表格数据),导出 Excel / Word 表格
richMode 图文模式(Word 格式自动启用)
- 跳过 Schema 推断
- 逐段让 LLM 返回每个条目的
image_region(像素坐标)+text(全部文本) - 用 Canvas 从长图分段中裁剪图片区域 → JPEG data URL
- 产出
result.richItems,导出为图文混排 Word 文档
调用入口(react.ts / phone-tools.ts)在
outputFormat === 'word'时自动传richMode: true。
Agent 工具定义
ExtractScrollingContent已注册为 Phone Tool,ReAct / Plan-and-Resolve Agent 可自主调用。
工具参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
description | string | 是 | 要提取什么数据,如"product list with name, price, rating" |
maxPages | number | 否 | 最大滚屏次数 |
settleMs | number | 否 | 每次滚动后的等待时间 (ms) |
schemaHint | string | 否 | 逗号分隔的字段名提示 |
outputFormat | excel|word|both | 否 | 导出格式,默认both;word自动启用 richMode 图文模式 |
工具返回值示例
Extraction complete. Extracted 47 unique items across 12 page(s). Removed 5 duplicates. End reason: bottom_reached. Files downloaded: extract-2026-06-16-1789551234567.xlsx + .docx任务自动结束行为
提取成功(返回以Extraction complete开头)后,整个 AI Agent 任务立即结束:
- ReAct 模式(react.ts):不再截图进入下一轮 LLM 决策,当前步骤标记成功,
task.conclusion直接取提取报告,task.status = 'finished' - Plan-and-Resolve 模式(agent.ts):剩余 pending 步骤全部标记
skipped,跳过 Report 阶段的 LLM 总结
提取无数据(No data extracted...)时任务继续正常流转,LLM 有机会调整策略(如先滚动到正确页面再重试)。
使用案例
案例 1:聊天自然语言触发(最常用)
在 AI 对话框中直接输入:
把当前页面的商品列表提取到 Excel提取美团外卖商家列表,包含店名、评分、月销量、起送价把这个小红书笔记列表保存成 Word 文档(含封面图)Agent 会自动识别意图并调用ExtractScrollingContent工具,任务在提取完成后自动结束。
案例 2:组合指令(先导航再提取)
打开小红书,搜索 deepseek,把搜索结果列表提取到 Excel,包含标题、作者、点赞数Agent 先执行打开 App、搜索等操作,最后调用提取工具并结束任务。
案例 3:通过 phone-agent MCP 调用
在支持 MCP 的客户端(如 Qoder)中:
使用 run_agent_task:提取当前手机页面的新闻列表到 Excel,字段包含标题、来源、时间任务完成后 MCP 返回 Markdown 格式的执行报告(含每步 summary 与工具调用)。
进度消息参考
onProgress回调依次会收到类似以下消息:
Capturing initial screenshot... Page 1: scrolling down (1 screenshot(s) captured)... Page 2: scrolling down (2 screenshot(s) captured)... Bottom detected (similarity=98.4%). Captured 9 screenshot(s). Stitching 9 screenshot(s) into a long image... Stitched into 3 image segment(s). Analyzing content with AI... Inferring data schema from stitched image... Segment 1/3: extracting data... Segment 1/3: +15 new items (total 15) Segment 2/3: extracting data... Segment 2/3: +14 new items (total 29) Segment 3/3: extracting data... Segment 3/3: +11 new items (total 40)导出格式说明
Excel (.xlsx) — Schema 模式
| 特性 | 说明 |
|---|---|
| Sheet 名 | Data(数据)+Screenshots(截图,传入 screenshots 时生成) |
| 第一行 | 列头(字段名) |
| 列宽 | 自动适配(基于最大内容长度) |
| 数据类型 | 数字保持 number,字符串保持 string,null → 空 |
| 截图保存 | 每页截图的 Base64 按单元格上限分列存入Screenshotssheet(拼接解码可还原图片),同时逐张下载为独立图片文件(.png/.jpg,与 Excel 同名前缀、按页编号) |
说明:xlsx 社区版库(SheetJS)不支持单元格内嵌图片,故截图以「Base64 分列存储 + 独立图片文件下载」双方式保存,确保图片不丢失。
Word 表格版 (.docx) — Schema 模式(both 格式)
| 特性 | 说明 |
|---|---|
| 标题 + 统计行 | 一级标题、“共提取 N 条数据,导出时间” |
| 表格样式 | 深色表头、交替行色、自动列宽 |
| 截图附录 | 传入screenshots时嵌入拼接后的长图分段 |
Word 图文版 (.docx) — richMode(word 格式)
| 特性 | 说明 |
|---|---|
| 每条内容 | 裁剪图片(300px 宽等比缩放,如有)+ 多行文本段落 + 分隔线 |
| 文本样式 | 第一行加粗稍大(标题感),其余行普通样式 |
| 页面 | A4,1.25 英寸左右页边距 |
常见问题
Q: 提取结果为空?
排查步骤:
- 确认手机屏幕当前确实显示列表/卡片内容
- 检查
description是否准确描述了要提取的数据 - 查看控制台
[ScrollExtract]日志,确认拼接分段数和 Schema 推断是否正常 - 尝试添加
schemaHint明确指定字段名
Q: 拼接后的长图有错位或重复条带?
可能原因:
- 页面滚动时有视差动画/吸顶元素,行签名匹配失败(此时该帧保留完整内容区,会出现重复但不会丢内容)
- 列表项之间是大面积纯色背景,重叠匹配找到了错误位置
说明:匹配失败产生的重复条目会被指纹去重移除,一般不影响最终数据;如果错位严重,可增大settleMs让页面完全静止后再截图。
Q: 过早判定触底?
可能原因:
- 页面有大面积固定区域(如顶部 Banner),滑动后变化区域占比小
endThreshold设置过高
解决方案:降低endThreshold(如 0.95 或 0.93)。
Q: 提取速度还想更快?
- 减小
settleMs(如 500ms),适用于静态内容页面 - 减小
maxPages限制采集范围 - 使用更快的视觉模型;LLM 耗时只与拼接后的分段数相关,与滚屏数无关
Q: 长图分段边界会不会切断条目?
分段之间保留 300px 重叠区,被切断的条目会在相邻分段中完整出现一次,重复识别由指纹去重兜底。
Q: 为什么 Word 格式和 Excel 格式提取出的内容结构不同?
outputFormat: 'word'自动启用 richMode 图文模式,产出"图片 + 自由文本"(richItems);excel/both走 Schema 模式,产出结构化表格(items)。两种模式的 LLM prompt 与产物完全不同。
Q: 支持哪些类型的列表?
| 列表类型 | 支持情况 |
|---|---|
| 原生 Android RecyclerView | 支持 |
| React Native FlatList | 支持 |
| Flutter ListView | 支持 |
| WebView 内 H5 列表 | 支持 |
| 分页加载(非无限滚动) | 支持(需配合点击翻页) |
| 横向滚动列表 | 暂不支持(当前仅纵向拼接) |
核心优势:基于截图 + 视觉 AI,不依赖 UI dump 或 XPath,对任意渲染框架通用。
