ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

AI代理+浏览器自动化:把短视频刷成结构化信息报告

AI代理+浏览器自动化:把短视频刷成结构化信息报告 AI、浏览器、短视频这三个词放在一起家长的第一反应多半是孩子又要想办法偷懒了。我在实际测试这类工具时发现真正的问题不在技术而在“刷”字的含义。如果它只是一个循环点播放脚本那确实不该鼓励但如果它本质上是“AI代理”让浏览器按计划访问短视频页面、提取信息、生成摘要、存成结构化数据那这件事就变成了一场特别有价值的编程与AI实验。这篇文章把这类工具拆开讲它到底能做什么、需要哪些环境、怎么一步步做出来、哪些参数影响稳定性以及家长该用什么标准判断孩子是不是走偏了。1. 先分清“刷”和“整理”之间的边界1.1 自动播放不等于自动整理很多孩子会跟父母解释我写了一个工具让浏览器自动刷短视频。这句话听起来技术含量很高但“刷”具体指什么差别很大。如果程序做的事情是打开一个短视频等它播完自动切下一个如此循环循环两个小时。那这个程序本质上就是一台“自动看视频机器”。它既不会让内容变少也不会让学习变多反而会因为异常行为触发平台的账号风控。就算只是用游客模式访问大量无效播放也会消耗带宽和服务器资源这不是健康的自动化场景。我见过有一些开源项目把“自动刷视频”包装成“提高效率”实际上就是把播放器点掉、挂机换时长。这种项目演示起来很酷但真正落地时没有任何正面价值还会让账号被限制。家长如果看到孩子在做这个确实该停下来聊一聊。1.2 AI代理真正值得做的形态是内容整理同样的技术栈换一个目标价值完全不同。一个真正的“AI浏览器代理”应该做的是每天定时打开你指定的短视频信息流页面读取页面上的公开文字信息比如标题、作者、时长、标签、简介然后调用大模型对这批信息做摘要、分类、去重最后生成一份“今日内容报告”保存到本地。程序也访问短视频页面但它不做无效播放不模拟点击观看不增加播放量。它更像一个信息浏览助手把大量短视频列表变成一份可阅读的文字清单帮你快速判断哪些内容值得打开。这才是 AI Agent 浏览器 短视频 的正确组合方式。1.3 家长可以先按这套标准判断行为判断说明让浏览器自动播放视频挂机刷时长不建议对学习无帮助容易触发平台限制也容易养成走捷径的习惯定时打开短视频页面抓取公开信息可接受低频、公开、不登录、不模拟点击播放用 AI 对标题和简介做摘要、分类、去重鼓励这是 AI 应用开发的核心思路绕过登录校验、破解接口、对抗风控必须停涉及非法使用不是技术学习该碰的范围拿程序去注册账号、批量制造虚假浏览数据必须停属于刷量和舞弊行为我建议把这个标准直接摆在桌面上。孩子做之前先确认你要写的是“浏览整理工具”不是“自动播放器”。2. 运行要准备哪些环境2.1 第一台实验机器不需要多高配置先给结论这个项目不需要 GPU不需要服务器不需要高端游戏本。普通办公电脑就能跑。我建议的最低配置如下CPU4 核以上双核也能跑但编译、安装依赖时慢一点内存8GB。16GB 更稳因为浏览器进程本身很吃内存磁盘预留 10GB。浏览器内核占几 GBPython 环境、缓存、日志也会持续占空间显卡不需要。AI 摘要部分用在线模型接口或本地 CPU 模型都能跑操作系统Windows 10/11、Ubuntu 20.04、macOS 都可以如果你的电脑是 4GB 内存的老机器也能跑但要降低并发一次只开一个浏览器页面并且不要同时跑模型。2.2 软件依赖怎么选这个项目最核心的依赖是浏览器自动化库。我用得比较多的是 Playwright因为它对现代浏览器支持好、等待页面加载的机制比老方案更可靠。基础环境建议这样Python 3.10 或 3.11Node.js 18 以上如果你后面想加前端或脚本PlaywrightPython 版或 Node 版都可以Chromium 浏览器内核Playwright 会自动下载一个可调用的 AI 模型服务AI 模型这一层最灵活。你可以用本地部署的模型比如 Ollama也可以用你自己申请的模型 API。关键是把模型调用封装成一个独立函数这样后面换模型不用改主程序。2.3 安装依赖的几个常见坑第一次装 Playwright 时最容易遇到的问题是浏览器内核没有下载成功。安装命令通常是pip install playwright playwright install chromium如果安装 chromium 时网络慢可以换镜像源也可以单独下载浏览器包。安装成功后先用下面这段代码验证from playwright.sync_api import sync_playwright with sync_playwright() as p: browser p.chromium.launch(headlessTrue) page browser.new_page() page.goto(https://example.com) print(page.title()) browser.close()能打印出Example Domain就说明环境没问题。注意如果这一步报错先看浏览器内核是否装好再检查系统缺少的底层库。Linux 下经常要额外安装一些系统依赖Windows 下则相对简单。2.4 项目目录和日志目录提前规划别把日志、输出、临时文件全堆在桌面上。我第一次跑这类项目时就吃过亏跑了几个小时最后输出文件散落得到处都是很难检查哪条任务成功、哪条失败。建议目录结构如下video_browser_agent/ main.py # 主入口 tasks.json # 待处理的任务列表 outputs/ # 最终结果 report_20250101.json logs/ # 运行日志 app.log cache/ # 去重缓存用来判断哪些 URL 已经处理过一开始就养成这个习惯后面排查问题会快很多。3. 从浏览器自动化到 AI 代理的核心实现3.1 第一层让浏览器自己打开短视频信息页第一步要解决的是“打开页面”的问题。这里不是打开视频自动播放而是打开一个短视频列表页或单个视频的信息页面读取页面上的公开文字内容。用 Playwright 写一个最简单的单页任务from playwright.sync_api import sync_playwright def fetch_page_info(url: str): with sync_playwright() as p: browser p.chromium.launch(headlessTrue) page browser.new_page() page.goto(url, timeout60000, wait_untildomcontentloaded) page.wait_for_timeout(2000) title page.title() text page.inner_text(body)[:2000] browser.close() return title, text if __name__ __main__: print(fetch_page_info(https://example.com/video/123))为什么要设置timeout60000因为短视频页面的图片、脚本、广告资源很多如果等待时间太短页面还没渲染完提取到的文字可能是空的。设置 60 秒是给慢网络留出余量。为什么还要wait_for_timeout(2000)这是给页面里的 JS 一个执行时间。短视频站点大量使用前端渲染不等待就可能拿不到动态加载的内容。3.2 第二层提取公开信息而不是截取视频内容很多新手会把页面整段inner_text全塞给 AI 模型这样既浪费 token又容易得到噪音结果。我更建议先做一层“字段提取”视频标题一般从h1或meta标签里拿作者名发布时间时长标签或话题视频简介公开的评论摘要非必需代码上可以先做一个简单的提取函数def extract_meta(page): meta {} try: title page.locator(h1).first.inner_text(timeout5000) except Exception: title page.title() meta[title] title.strip() return meta这个函数看起来简单但实际项目里最重要的就是这一层。页面结构一变字段就可能提取不到。所以不要把所有逻辑都写在采集函数里最好单独维护一个“页面解析模块”。3.3 第三层让 AI 模型生成摘要和分类提取到标题和简介之后下一步就是交给模型处理。封装模型调用的核心思路是输入一段短文本输出结构化的结果。这里我给一个通用示例具体模型服务以你自己的环境为准def summarize_with_ai(title: str, desc: str) - dict: prompt f 你是一个短视频内容整理助手。 请根据下面的标题和简介输出 JSON 格式结果 字段包括summary一句话摘要、category分类、watch是否建议观看。 标题{title} 简介{desc[:1000]} # 这里替换成你自己的模型服务调用代码 raw call_llm(prompt) # 解析返回结果最好用 try/except 兜底 result json.loads(raw) return result为什么要限定desc[:1000]因为简介太长会拖慢模型响应而且很多信息是重复的1000 字以内足够判断内容类型。为什么要用 JSON 格式因为后续要把结果存到 SQLite 或 JSON 文件里结构化数据方便统计和查询。3.4 第四层把多步操作串成一个任务队列分开写每一层最后合起来就是完整流程读取任务列表 - 逐个打开页面 - 提取字段 - AI 摘要 - 写入结果 - 进入下一个任务这个流程用一个函数串起来def run_task(task: dict): url task[url] title, text fetch_page_info(url) meta extract_fields_from_text(title, text) result summarize_with_ai(meta[title], meta[desc]) save_result(url, result)先跑单条任务。能跑通之后再考虑批量。4. 批量任务调度和增量更新4.1 任务队列的最小运行顺序批量跑之前先把任务列表设计好。最简单的方式是一个 JSON 文件[ { url: https://example.com/video/123, source: daily_list }, { url: https://example.com/video/456, source: daily_list } ]运行顺序应该是单条 - 两条 - 一个文件 - 定时任务。不要一上来就把几百条地址全塞进去否则你需要同时排查的问题太多。4.2 去重和增量更新要用 URL 哈希短视频站点的重复内容很多。同一个视频可能被多次推荐不同链接也可能指向同一个内容。所以必须做去重。最简单的去重方案是用 URL 哈希import hashlib def url_hash(url: str) - str: return hashlib.sha256(url.encode(utf-8)).hexdigest()每次处理前先检查这个哈希是否已经存在。如果存在直接跳过。更完整一点可以再保存标题哈希。因为同一视频的链接有时会带不同参数标题反而更稳定。4.3 定时任务用 APScheduler如果只想在本地定时运行不需要部署分布式系统APScheduler 是最合适的选择。from apscheduler.schedulers.blocking import BlockingScheduler def job(): print(开始执行短视频信息整理任务) run_task_list() scheduler BlockingScheduler() scheduler.add_job(job, cron, hour9, minute0) scheduler.start()这里设置每天上午 9 点执行一次。为什么建议低频因为内容源不需要每时每刻都刷新。刷得太频繁既浪费资源也可能对目标站点造成压力。4.4 结果怎么存结果存储有两个层次单次运行结果存成带日期的 JSON 文件方便人工翻阅累计缓存存 SQLite方便去重和增量更新SQLite 示例import sqlite3 conn sqlite3.connect(cache.db) conn.execute( CREATE TABLE IF NOT EXISTS seen_urls ( url_hash TEXT PRIMARY KEY, title TEXT, created_at TEXT DEFAULT CURRENT_TIMESTAMP ) )这个表只需要保留“看过的 URL 和标题”不需要保存页面全文。页面全文占用空间大而且后续不一定用得上。5. 生产化运行要关心的关键参数5.1 速度、稳定性和资源占用要分开看同一个功能跑一次和跑一百次是完全不同的问题。跑一次只要能成功打开页面就行跑一百次就要考虑崩溃恢复、超时重试、内存回收。下表是我在实际项目中常用的参数区间具体数值要根据你的网络和任务源调整参数建议值说明单页超时时间30s - 60s太短容易误判失败太长会拖慢整个任务任务重试次数2 次超过 2 次基本不是网络抖动可能是站点结构问题两个页面之间的间隔3s - 8s不要连续高频访问低频运行更稳妥最大并发页面数1 - 2本地学习场景坚决不追求并发稳定性优先日志保留时间7 天日志会持续增长定期清理或按天拆分AI 模型超时30s模型响应慢时不要无限等待每次任务读取简介长度1000 字过长的简介既费 token 又没什么增量信息5.2 不要把并发理解成越快越好短视频页面非常“重”会加载大量图片、脚本、样式。如果你同时开 5 个小号浏览器单页都打开视频信息页内存可能瞬间占用超过 4GB8GB 的电脑很快就会卡死。我的建议是本地实验强制串行最多开一个浏览器实例。串行的特点是每个任务慢一点但整体稳定失败后也容易定位。如果以后确实要用多并发也应该用“任务队列 固定数量 worker”的方式不要直接用for循环开页面。5.3 一定要有错误隔离项目里最常见的错误是单个页面解析失败导致整个程序退出。更稳妥的做法是给每个任务单独加异常处理def safe_run(task): try: result run_task(task) return {status: success, data: result} except Exception as e: return {status: failed, error: str(e), url: task[url]}这样即使一条任务失败也不会影响后面的任务。最后再统一看失败列表。5.4 尊重目标站点的公开访问边界这句话要单独说任何自动化程序都只能访问公开页面不能绕过登录校验不能模拟大规模点击不能对抗风控。简单来说控制三个指标频率每个页面间隔至少 3 秒不要用高并发扫描范围只抓公开信息不碰用户私密数据行为不模拟观看不制造浏览量不注册批量账号你只是在“浏览”不是在“攻击”。这两个边界的区别是最重要的技术素养。6. 常见问题排查6.1 启动失败浏览器打不开如果是 Playwright 相关先按这个顺序排查检查浏览器内核是否安装成功重新执行playwright install chromium检查系统依赖Linux 下用playwright install-deps补依赖检查权限有些系统目录不允许浏览器写缓存改用有头模式先跑一遍把headlessTrue改成headlessFalse看看浏览器窗口是否正常弹出6.2 页面打开成功但提取不到内容这个问题最常见的原因有两个页面还没加载完成就执行了提取逻辑。解决方法是把wait_for_timeout改成等待某个关键元素出现短视频页面的标题或描述是在动态数据里并不出现在静态 HTML 中。解决方法是先获取页面里所有文本再利用正则或关键词定位不要一上来就怀疑是项目代码有问题。先用浏览器开发者工具打开同一个页面看一下“元素面板”里结构长什么样再写提取逻辑。6.3 AI 模型返回空结果或返回格式错误先看模型服务的原始返回再去检查解析逻辑。模型返回空结果通常是 prompt 里的输入内容为空或者上下文长度超限。我建议在调用模型前打印一次输入长度if len(desc) 20: print(简介太短跳过 AI 处理)简介太短的视频不值得花一次模型调用处理。直接标记为“需要人工查看”更合理。6.4 程序运行一段时间后卡住卡住先看两个地方日志停在哪一个 URL当前内存占用是多少。如果是单个页面卡住大概率是网络请求一直没返回。这时要依赖超时参数把page.goto的 timeout 调短一点或者在任务调度层设置整体超时。如果是内存持续上涨大概率是浏览器实例没有正确关闭。检查browser.close()是否在finally里执行browser None try: browser p.chromium.launch(headlessTrue) ... finally: if browser: browser.close()注意排查顺序永远是先看现象、再看日志、再看输入、再看环境。不要先乱改参数。7. 家长怎么看该哭还是该笑7.1 判断孩子有没有走偏看三个信号第一个信号程序是不是在制造虚假观看数据。只要涉及刷量、挂机、伪造播放无论写得多“聪明”都应该叫停。第二个信号孩子是不是在挑战平台风控。如果他在花大量时间研究如何绕过验证码、更换设备指纹、突破频率限制那就不是正常学习而是在往灰色地带走。第三个信号他有没有去做“信息整理”。正常的方向是能不能把一千条短视频列表用 AI 整理成一份清晰报告包含分类、摘要、值得看指数。这个方向需要用到浏览器自动化、数据解析、模型调用、存储设计确实是实打实的技术能力。7.2 值得鼓励的成长路径如果孩子已经写出了第一版“AI 短视频信息整理代理”接下来可以引导他继续做四件事把单网页解析改成多结构适配学习不同页面的选择器设计用 SQLite 代替 JSON 文件学习数据库设计给任务加统计面板统计每天抓了多少条、摘要成功率是多少把“看视频”彻底改成“读信息”做一套自己的每日内容推荐系统每一步都是工程化能力而不是投机取巧。7.3 真正该给的答案是“把刷变成读”回到标题父母是该哭还是该笑如果孩子只会让浏览器自动播放视频挂机那确实该管。但如果他在用 AI 做一只“内容研究助手”在学习如何让浏览器按指令工作、如何让模型输出结构化结果、如何稳定运行批量任务那这不该被骂反而值得鼓励。技术本身没有方向使用目标才有方向。同样是浏览器自动化你可以做一台无意义的播放器也可以做一个有价值的信息整理器。差别不在代码而在“刷”和“读”之间。我会建议所有家长先看一次孩子跑的日志再决定要不要没收电脑。如果日志里全是“开始播放、自动切下一个”那就好好聊一聊如果日志里是“页面提取成功、AI 摘要生成、分类完成”那其实可以顺手夸一句这小子方向找对了。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进