返回 Skill 列表
extension
分类: 数据与分析无需 API Key

金融类广告公关辅助工具

金融机构专属公告广告监控与分析(v10.1)。监控 151 家金融 APP + 机构官网 + 财经媒体 + 财经论坛 + 自媒体的广告投放、产品推荐与舆论信息(基金/银行/券商/保险/第三方销售/媒体/论坛等)。无需登录直接爬取公开 Web/H5。图片广告(轮播逐帧 OCR+视觉)、文字广告三种形式全覆盖;视频广告轻量实装(v10:video poster+src 提取 + 海报帧下载 + iframe 播放器)。媒体新闻稿件 + 论坛舆论 + 情感分析;多机构×多平台横向对比(谁投放多、哪个平台活跃)+ v9.1 新增同类别竞品对比矩阵 + 跨平台投放对比 + 广告语 TF-cosine 相似度 + 多维投放强度排行榜 + 素材复用检测。Word 报告 11 大板块(v10 新增竞品投放对比);轮播抓取强化(v10.1:全页背景图/伪元素/iframe/shadow DOM/canvas 连拍/dHash 去重),支持一次性 / 增量 / 定时采集 / 时间范围查询(--query);交互模式为 3 步对话式向导(范围→浏览器模式→附加能力)。仅爬取非登录公开页面,合规安全。 触发词:监控 APP 首页推荐 / 轮播广告监控 / APP 首页广告爬取 / 爬取轮播图 / 基金销售 APP 推荐 / 银行 APP 首页 / 券商 APP 推荐 / 保险 APP 首页 / 天天基金 / 蛋卷基金 / 京东金融 / 和讯 / 蚂蚁基金 / 小白套餐 / 对比趋势 / 金融 APP 广告采集 / 理财推荐监控 / 首页推荐产品 / 公告广告监控 / 机构官网监控 / 财经媒体新闻爬取 / 基金公司新闻稿 / 财经论坛舆论 / 股吧舆情 / 自媒体监控 / 视频广告监控 / 文字广告 / 广告投放对比 / 多机构对比 / 时间范围查询 / 舆情分析 / 情感分析 / 交互模式 / 对话式向导 / 竞品分析 / 投放强度 / 广告相似度 / 跨平台对比 / 视频海报 / 热度评分。

person作者: user_9d5a2a39hubcommunity

金融机构公告广告监控与分析(v10.1)

总览

面向金融从业者/竞品分析师/合规审计,监控中国 210 个数据源的公告广告与舆论:

  • 151 家金融 APP 首页:推荐产品清单 + 轮播广告图逐帧(OCR/视觉提取广告语)
  • 机构官网(website):banner 广告图 + 文字广告 + 产品 + 公告/资讯页
  • 财经媒体(media):权威媒体/门户上各家基金公司的新闻稿件
  • 财经论坛(forum):股吧/基金吧/雪球/知乎的舆论帖子 + 热度
  • 自媒体(social):公开可爬部分(B站/美篇)+ 登录墙手动补充

三种广告形式全覆盖:图片(轮播逐帧)、文字(页面广告文案)、视频(下载→抽帧→OCR/ASR)。

通过 Playwright 模拟浏览器访问公开 Web/H5(无需登录),最终生成一份嵌入思源字体的 Word 报告。

适用场景

  • 竞品监测:跟踪同类机构(银行/券商/基金)的推广策略和新品节奏
  • 广告投放对比:横向对比各机构广告投放量、各平台活跃度
  • 媒体舆情:基金公司新闻曝光量、论坛舆论热点、情感倾向
  • 趋势追踪:隔周/隔月重跑,看广告语、产品、新闻、帖子变化
  • 合规审计:收集非登录公开页面的展示信息作为证据

不适用

  • 需要登录才能看的个人化内容(资产/持仓/交易记录)
  • 强反爬+登录墙的自媒体(微信/抖音/快手/小红书/视频号),标注 none 并给出手动补充指引

核心能力(v10.1)

🆕 v10.1 新增:banner 轮播抓取与分析强化

抓取侧(修复 7 大盲区) | 盲区 | v10.0 | v10.1 | |---|---|---| | background 轮播 | 只扫 3 类 class + 单 url() | 全页面大尺寸块级启发式 + 多 url() 拆分url(a),url(b) 全取)+ 伪元素 ::before/::after + data-bg 懒加载 + 60% 页面高度 | | iframe 内轮播 | 完全不可见 | 遍历 page.frames 逐帧扫描 | | shadow DOM 轮播 | 完全不可见 | shadowRoot 递归 pierce | | canvas 绘制轮播 | 无指示器仅截 1 帧 | 自动连拍(2s×8 次 + 字节去重,捕获 autoplay 切换帧) | | JS 动态 swiper | data-src 拷贝 | slide 数量 3 次采样稳定等待 + Swiper 实例读取 | | 指示器 | 仅 pagination 圆点 | + 左右箭头(.swiper-button-next/prev)+ JS slideNext() 兜底 | | 配置 | 151 家全模板 | 15 家精配覆盖(天天基金 .banner_box/#top_banner 等文档选择器落地) |

分析侧(修复 3 大瓶颈) | 瓶颈 | v10.0 | v10.1 | |---|---|---| | 帧级去重 | 仅 URL 归一化 | dHash 感知哈希内容去重(同素材变体/多页重复/截图重复剔除,保护 30 帧上限、省 OCR/vision 费用) | | 截图质量 | 无指示器截整页 400px | JS 精确定位轮播容器 clip(_CAROUSEL_BOX_JS) | | vision 误判 | 截图帧按"单张广告图"分析 | is_page_shot 页面截图模式(专用 PAGE_SHOT_PROMPT) |

链路强化

  • 失败帧重试通道:采集阶段下载失败的帧(image_url 保留)在 OCR 阶段按 URL 重试下载再入 OCR
  • OCR 并发:两处 OCR 循环 ThreadPoolExecutor 并发(6 线程,与 vision 一致)

核心能力(v10.1)

🆕 v10.0 新增:广告爬取 / 广告图 / 分析能力全面强化

广告爬取强化 | 强化项 | v9.1 | v10.0 | |---|---|---| | ad_fetcher_enhance 集成 | 158 词库/意图分类/视频海报为死代码(零调用) | 全面接入 scraper + website_collector 主路径,文字广告入库附 ad_score + 意图 | | 视频广告 | media 资源被拦截、无 producer | 轻量实装:解除 media 全拦(白名单放行站内视频)+ extract_videos(video poster/src + iframe 播放器 + 海报帧下载) | | 懒加载/iframe/弹窗 | 产品不滚动、iframe 广告不处理 | 产品提取前滚动触发懒加载;全屏广告弹窗([class*='ad'] fixed 层)清理 | | 反爬检测 | 15 词 + 2000 字符采样 | HTTP 状态码 + 验证码 iframe/img + 多轮采样 + headless 特征自检 | | 产品提取 | yield_rate/risk_level 永远为空 | 正则提取 + products 表加列入库 |

广告图获取强化 | 强化项 | v9.1 | v10.0 | |---|---|---| | 下载方式 | 串行(30 帧最坏 15 分钟) | ThreadPoolExecutor 并发(4 线程) | | 原始 URL | frames 表无 image_url 列(入库即丢) | image_url 列迁移 + 下载失败标记可重试 | | 截图帧编号 | DOM/截图帧 frame_index 冲突丢帧 | 统一编号器 | | 指示器点击 | 直接 click + 固定 1.2s | 拟人化(scroll_into_view + 随机延时 + 像素验证重试) | | 图片质量 | webp 不转换 | webp→PNG 自动转换 + >5MB 跳过 |

广告分析强化 | 强化项 | v9.1 | v10.0 | |---|---|---| | 竞品分析接入 | full_competitor_report 从未被调用(最大断点) | 接入报告流水线:Word 新增板块 11(强度 TOP10 柱状图 / 品类矩阵 / 相似对 / 素材复用) | | 投放强度分 | 线性数量堆叠 | 四维加权(数量 40% + 素材多样性 20% + vision 质量 20% + 意图覆盖 20%)+ 品类内 z-score 归一化 | | 素材复用 | 无 | detect_shared_assets:同图多投检测(image_hash 聚类) | | 广告语相似度 | 全文本 bigram Jaccard(稀释) | TF 加权 cosine + n-gram 共现短语抽取 | | diff 检测 | text_changed 无阈值(OCR 抖动误报);video_changed 死类型 | 相似度阈值(≥0.8 不算变) + 空文本转换检测 + frame_image_changed(同位置图变)+ video_changed 实装 + 换序降误报 | | 时间趋势 | 仅最近两次 diff | diff_trend:N-run 序列环比(帧数/产品数/主题热度) | | OCR | 无方向检测/竖排/缓存 | OSD 方向回正 + PSM 多通道重试 + 逐词置信度 + NFKC 归一化 + image_hash 缓存 | | 视觉校验 | 串行、无缓存、原图直传 | verify_batch 并发(5 线程)+ 结果缓存 + 图片压缩(长边≤1568)+ 指数退避重试 + schema 校验 | | LLM 整页点评 | 复用 banner prompt(语义错位) | 专用四段式 prompt(布局/主推产品/营销策略/风险提示) | | 情感词典 | 20+19 词、无否定处理 | 200+ 金融词 + 否定词翻转("未出现违规"不再误判负面)+ 模型并发+缓存 |

性能提升

  • 图片并发下载 + vision 并发校验 + OCR/vision/文本三处 hash 缓存(跨 run 复用)
  • save_results_to_storage 主路径统一 bulk 单事务(200 帧 200 事务 → 1 事务)
  • 单 APP 软超时保护(默认 180s,防一个卡死拖垮整批)

🆕 v9.1 新增:广告/公告获取增强(ad_fetcher_enhance.py)

| 增强项 | 原版 | v9.1 | |---|---|---| | 广告话术关键词 | 30 个 | 100+ 个(促销/拉新/福利/收益/行动/节日/品牌/教育/投资 9 大类) | | 视频海报帧提取 | 未实装 | v9.1 部分实装<video poster> + .video-cover img 两种来源) | | 背景图 CSS 解析 | 单引号/无引号 | 三引号兼容 + data:URI 过滤 + 关键字过滤 | | 热度评分 | 无 | 综合评分(点赞×1 + 回复×5 + 浏览×0.1,4 档 cold/warm/hot/viral) | | 日期解析 | ISO 格式 | 相对+绝对("刚刚"/"X 分钟前"/"X 小时前"/"昨天"/"X 天前"/"X 月前") | | 广告意图分类 | 无 | 4 类意图(拉新/促活/留存/挽回) |

🆕 v9.1 新增:竞品分析对比(competitor_comparator.py)

| 对比维度 | 说明 | |---|---| | 同类别横向对比矩阵 | 同组内各家投放强度排行 + 推广主题偏好 + 强度差距分析 | | 跨平台投放对比 | APP / 官网 / 媒体 / 论坛 / 自媒体 5 类平台投放量/活跃度对比 | | 广告语相似度 | Jaccard 系数(bigram + 关键词)+ TOP 5 相似对 | | 投放强度排行榜 | 全市场 TOP 10 投放最强 APP(含轮播/产品/文字广告/模块数明细) | | 完整竞品报告 | full_competitor_report(results) 一键产出 4 大板块 |

📊 11 大板块 Word 报告

📊 11 大板块 Word 报告

| 板块 | 内容 | 适用对象 | |------|------|---------| | ① Banner 汇总清单 | 跨 APP/官网全部轮播帧缩略图 + 广告语 + 跳转链接 | 整体速览 | | ② 页面模块 | 导航 / 卡片 / 活动入口汇总 | 运营参考 | | ③ 元信息 + 整页截图 | 采集时间 / 数据源列表 / 成功率统计 + 首页截图 | 合规留痕 | | ④ 多时点对比趋势 | diff 文字摘要 + matplotlib 折线图(20 类变化,v8 增新闻/帖子/广告) | 趋势追踪 | | ⑤ 自动点评 | 统计型 + 趋势型 + 跨源对比 + 舆情热点 + 情感分析 + 可选 LLM | 决策参考 | | ⑥ 媒体新闻监测(v8) | 跨源新闻表格 + 各机构报道量排行 | 媒体监控 | | ⑦ 舆论监控(v8) | 情感分布 + 舆情热点 + 热帖榜 | 舆情分析 | | ⑧ 文字广告汇总(v8) | 跨源文字广告表格 | 广告监控 | | ⑨ 视频广告(v8) | 视频列表 + 关键帧 + 字幕/OCR 摘要 | 视频广告 | | ⑩ 跨源横向对比(v8) | 机构×平台投放量/新闻量矩阵 | 竞品分析 |

🤖 自动点评引擎(commentary_engine.py + v9.1 competitor_comparator.py)

  • 统计型(默认开启,无依赖):同类别横向对比、OCR 关键词聚类(10 大推广主题)、产品类型分布
  • 趋势型(自动开启):基于 diff 数据归纳(变化最频繁 APP、营销节奏判断)
  • 竞品对比型(v9.1 新增):同类别对比矩阵、跨平台投放对比、广告语相似度、投放强度榜
  • LLM 点评--with-llm-comment 启用,需 VISION_API_KEY):整页一句话点评;未配 key 自动降级

🛠️ 工程能力

  • APP 名单 151 家 / 14 类别:第三方销售/基金销售/互联网理财/互联网保险/财富管理/券商/保险/期货/国有大行/股份制/政策性银行/城商行/农商行/民营银行
  • 小白友好--preset beginner 一键跑 8 家 + python scripts/setup.py 自动装齐依赖(pip / Chromium / Tesseract / 字体 / OCR 语言包)+ --guide 5 分钟上手
  • 增量采集:SQLite 持久化 + 多时点 diff(8 类变化:轮播帧增删 / 广告语变化 / 产品增删 / 页面模块增删改)+ 趋势图
  • 真定时任务--schedule "0 9 * * 1"):croniter + 指数退避 + 健康探活 + 死信保护
  • 反爬 6 级降级链:UA 伪装 → stealth → 资源拦截 → 反爬关键词检测 → 退避重试 → 降级标注
  • 合规边界:仅爬非登录公开 Web 页;不破解验证码;不存登录态/个人信息

完整清单:python scripts/run.py --list-apps(秒回,不触发依赖安装)

五分钟上手(小白必看)

# 1. 第一次跑:自动装齐所有依赖 + 跑小白套餐(8 家基金销售类APP)
python scripts/run.py --preset beginner

# 2. 查看上手向导
python scripts/run.py --guide

# 3. 列出全部APP
python scripts/run.py --list-apps

会自动发生的事:

  1. 检测 pip 依赖 → 缺哪个装哪个
  2. 下载 Playwright 浏览器内核(约 150MB)
  3. 检测 Tesseract 文字识别工具 → 缺则尝试 winget/choco 自动装
  4. 下载思源字体到 assets/fonts/
  5. 下载OCR中文语言包到 assets/tessdata/
  6. 跑 8 家APP:天天基金、京东金融、蚂蚁财富、和讯、蛋卷基金、雪球、东方财富、同花顺
  7. 出 1 份嵌入思源的 Word 报告(约 1-3 MB)

如果中途出错: 错误会用中文告诉你为什么以及下一步该做什么,不用看堆栈。

步骤 1:检测运行环境(可选)

!python "scripts/run.py" --check-env

如果跳过上一步就开跑,run.py 会自动检测并补齐所有依赖。

步骤 2:选择监控范围

5 种方式(v8 多数据源):

  • 预设套餐(小白友好)--preset beginner(8 家)/ --preset fund_sales(基金销售类)/ --preset third_party(第三方销售类)
  • 指定数据源(中文名、简称、英文标识)--apps "天天基金,京东金融,和讯" / --apps "招行,工行,农行"
  • 按类别--apps 基金销售 / --apps 第三方销售 / --apps 银行
  • v8 新增类别--apps 财经媒体(媒体)/ --apps 财经论坛(论坛)/ --apps 基金公司(官网)/ --apps 自媒体 / --apps 官网
  • 全部--apps all(210 个数据源,约 30-60 分钟)

步骤 3:执行爬取与提取

一次性跑(默认):

!python "scripts/run.py" --apps "{用户指定的范围}" --output "公告广告监控报告_{日期}"

增量跑(写数据库,第二次跑能看差异):

!python "scripts/run.py" --collect --apps "{范围}" --db data/monitor.db

带视觉模型(OCR 看不懂的字自动调AI):

!python "scripts/run.py" --apps "{范围}" --with-vision

时间范围查询(--query,读数据库不爬取):

!python "scripts/run.py" --query --since "2026-08-01" --until "2026-08-31" --db data/monitor.db

视频广告深度采集(需 yt-dlp/ffmpeg 可选):

!python "scripts/run.py" --apps "{范围}" --with-video

模型级文本/情感分析(需 VISION_API_KEY,无 key 自动降级词典):

!python "scripts/run.py" --apps "{范围}" --with-llm-analysis

参数默认值(小白可全部省略): | 参数 | 默认值 | 说明 | |------|--------|------| | --apps | (无) | 必须指定;或用 --preset beginner | | --preset | (无) | 小白套餐 | | --source-type | (不加) | 数据源过滤:app/website/media/forum/social | | --since / --until | (不加) | 时间范围(YYYY-MM-DDYYYY-MM-DD HH:MM) | | --query | (不加) | 时间范围查询模式(读库出报告,配合 --since/--until) | | --no-headless | (不加) | 默认无头模式;调试时加此参数显示浏览器 | | --output | 自动生成 | 输出文件名(不含扩展名) | | --collect | (不加) | 增量模式(写数据库 + 后续可对比) | | --db | data/monitor.db | 数据库路径 | | --with-vision | (不加) | 低置信度OCR帧自动调视觉模型 | | --with-video | (不加) | 视频广告深度采集(下载→抽帧→OCR/ASR) | | --with-llm-analysis | (不加) | 文本/情感分析启用模型级(无 key 降级词典) | | --strict | (不加) | 严格模式:任何环境缺失都抛错(持续集成用) |

流程说明(脚本内部自动完成):

  1. 按 source_type 分派:app→scraper、website→官网深爬、media→新闻、forum→帖子、social→自媒体公开部分
  2. 提取各自内容(产品/轮播/文字广告/新闻/帖子/视频),产出归一化结果
  3. OCR(Tesseract 中文简体 + 英文)提取图片广告语;低置信度帧调视觉模型校验
  4. 视频广告深度:下载→抽帧→OCR帧内容→ASR转文字(全部可选降级)
  5. 文本/情感分析(词典级兜底,可选模型级)
  6. 增量模式:写数据库 + 计算与上次的差异(20 类变化:帧/产品/模块/新闻/帖子/文字广告/视频)
  7. 生成汇总 Word(10 板块)+ 嵌入思源字体

步骤 4:定时监控(可选)

!python "scripts/run.py" --schedule "0 9 * * 1" --apps all

特性:

  • 真定时(基于定时表达式库,不是循环等待)
  • 指数退避(失败 1分钟 → 2分钟 → 4分钟 → ... 上限 60分钟)
  • 健康探活(data/scheduler_logs/health.json
  • 死信保护(连续失败 10 次自动停服)
  • 可优雅停止

常用定时表达式: | 表达式 | 含义 | |--------|------| | 0 9 * * * | 每天 9:00 | | 0 9 * * 1 | 每周一 9:00 | | 0 */6 * * * | 每 6 小时 | | 0 9 1 * * | 每月 1 号 9:00 |

步骤 5:输出结果

向用户报告:

  1. Word 报告路径data/output/APP首页监控报告_YYYYMMDD_HHMMSS.docx
  2. 数据库(增量模式)data/monitor.db
  3. 爬取统计:成功数 / 总数、推荐产品数、轮播广告帧数
  4. 截图目录data/screenshots/
  5. 轮播图目录data/carousel_images/{APP名}/
  6. 可爬性说明:蚂蚁财富不可爬(无公开网页版首页,Word 中有手动截图补充指引);部分APP降级处理说明

注意事项

  • 仅爬取非登录公开网页页面,不破解验证码,不存储登录态或个人敏感信息
  • 蚂蚁财富无公开网页版首页,自动跑手动指引占位节(可手动截图后放入 data/carousel_images/蚂蚁财富/ 重新生成报告)
  • 视觉模型校验为可选(需配置视觉模型接口密钥),缺失时降级为纯OCR
  • 部分APP(工行基金、保险需登录;建行、交行轮播纯图片)会降级处理并在报告中标注
  • 各APP的页面元素选择器基于调研初步配置,实际页面结构变化时可能需调试 scripts/app_registry.py

安装指引(已自动化,无需手动)

# 自动检测 + 补齐所有依赖(pip 依赖、浏览器内核、文字识别工具、字体、语言包)
python scripts/setup.py
# 或:跑任意 run.py 命令时自动调用

v7.4 缓存防御(上传/分发前必跑)

# 清理 __pycache__/*.pyc(部分同步工具按扩展名拒收 .pyc 二进制)
python scripts/cleanup_cache.py
  • scripts/run.py / scripts/setup.py 顶部已设 sys.dont_write_bytecode = True,运行时不生成 .pyc
  • conftest.py 已让 pytest 不生成源码 .pyc(仅 pytest 自身的 conftest.pyc 仍会生成)
  • 上传/分发前跑一遍 cleanup_cache.py 即可彻底干净

如果自动装失败(winget 不可用 / 无管理员):

  • Tesseract 手动安装:https://github.com/UB-Mannheim/tesseract/wiki (勾选简体中文)
  • 字体手动:从 https://github.com/adobe-fonts/source-han-sans/releases 下载 4 个 OTF 字体放到 assets/fonts/
  • 设置 TESSERACT_CMD=<tesseract.exe路径> 环境变量

视觉模型接口(可选):

set VISION_API_KEY=<你的接口密钥>
set VISION_API_BASE=https://open.bigmodel.cn/api/paas/v4
set VISION_MODEL=glm-4v

小白词典(10 行速查)

  • 轮播图:APP 首页顶部那张会自己滚动切换的大广告图;本工具把每一帧都抓下来
  • 轮播:上面的轮播图通常 3-5 张为一组,按时间自动切换,叫"轮播图组"
  • OCR:把图片里的中文读成文字的技术(这里用 Tesseract);读不准的字会再请AI看一眼
  • 视觉模型:能"看图说话"的AI(这里默认GLM-4V),作为OCR的兜底
  • 字体嵌入:把字体文件塞进Word文档里,对方打开不会缺字体(思源黑体、思源宋体)
  • 浏览器身份标识:浏览器身份证,决定你看到的是移动H5还是电脑网页版
  • 隐身模式:反反爬技术,让网站尽量看不出我们是机器人
  • 降级:某一步失败时自动改用更简单但更稳的方式(如截屏代替页面元素解析)
  • 对比差异:两次抓取之间"什么变了",是第 4 板块(对比趋势)的核心
  • 定时表达式:定时任务的写法,如 "0 9 * * 1" 等于每周一早上 9 点

参考文件

  • references/scrapability_report.md -- 可爬性调研报告(首批 15 家深度调研,其余按类别模板推断;何时查看:了解各APP可爬性依据)
  • references/app_selectors.md -- 各APP页面元素选择器配置说明(何时查看:选择器失效需调试时)
  • references/word_font_embedding.md -- OOXML字体嵌入技术说明(何时查看:字体嵌入相关问题)
  • scripts/app_registry.py -- 151家APP配置表(何时查看:增减APP或调整网址、选择器时)
  • scripts/deps.py -- 依赖清单唯一真源(何时查看:增减 pip 依赖时;必需 vs 可选分开)
  • scripts/storage.py -- SQLite 增量存储(何时查看:差异算法、调数据库时)
  • scripts/diff_engine.py -- 多次爬取对比算法 + CHANGE_TYPE_CN 变化类型中文名真源(何时查看:自定义对比类型时)
  • scripts/_auto_install.py -- 首次运行自动安装逻辑(何时查看:自定义安装项时)
  • scripts/setup.py -- 一键环境准备(何时查看:手动安装时)
  • scripts/cleanup_cache.py -- 清理 pycache/*.pyc(何时查看:上传/分发前必跑)
  • conftest.py -- pytest 全局配置(禁用 .pyc 生成)
  • scripts/run.py --check-env -- 环境检测(何时查看:排查依赖问题时)
  • scripts/registry_websites.py / registry_media.py / registry_forums.py / registry_social.py -- v8 多数据源注册表(何时查看:增减官网/媒体/论坛/自媒体源时)
  • scripts/collector.py -- v8 多数据源统一分派入口(何时查看:新增 source_type 时)
  • scripts/news_collector.py / forum_collector.py / website_collector.py / social_collector.py -- v8 各数据源采集器(何时查看:某类源爬取异常时)
  • scripts/text_analysis.py -- v8 文本/情感分析(词典+模型两级)(何时查看:情感分析调优时)
  • scripts/query_engine.py -- v8 时间范围查询(--query 模式)(何时查看:窗口报告定制时)
  • tests/ -- 单元测试(299 个用例,含 v7.4/v7.5/v8/v9 缺陷修复防回归)

📝 v7.3 优化与缺陷修复记录

v7.3 重大升级:从小白"装半天跑不起来"变成"装好就开跑"。

修复的真实缺陷

| 编号 | 文件 | 现象 | 修复 | |-----|------|------|------| | 修复-1 | agents/openai.yaml:3 | 描述写"15家"陈旧 | 改为"130+家" | | 修复-2 | scripts/storage.py:331 | get_diffs 返回的载荷字段是原始字符串而非字典,调用方 .get() 会返回默认值 | 反序列化载荷JSON,损坏时降级为空字典 | | 修复-3 | scripts/diff_engine.py:74 | 仅在模块表有数据时,差异项的应用名称错误地用标识当作值 | 改为合并时按标识集合去重,仅作兜底 | | 修复-4 | scripts/storage.py:339 | get_latest_runlist_runs 用连接查询帧表过滤,只有产品没有帧的运行找不到 | 改用联合查询三表 | | 修复-5 | scripts/_auto_install.py:119 | 写死浏览器无头外壳-1228 路径,浏览器升级后检测失败 | 改为动态扫描 chromium_headless_shell-* 目录 | | 修复-6 | scripts/run.py:90 | --strict 严格模式标志定义了但永远没被使用(死参数) | 把标志传给自动安装逻辑 | | 修复-7 | scripts/scheduler.py:85 | 循环等待阻塞非真定时 | 重写为真定时 + 指数退避 + 健康文件 + 死信保护 | | 修复-8 | scripts/word_exporter.py | 4 板块缺"对比趋势" | 新增 4 个板块添加函数 | | 修复-9 | scripts/run.py | 无数据库持久化,无增量采集模式 | 新增加量模式(写数据库 + 对比差异) | | 修复-10 | scripts/app_registry.py | 和讯未在册;基金销售类 9 家缺主流 | 补 9 家(和讯 + 诺亚 + 宜人 + 嘉实 + 易方达 + 华夏 + 南方 + 博时 + 富国) | | 修复-11 | scripts/_auto_install.py | 首次跑需手动装 | 首次 run 命令自动装齐所有依赖 | | 修复-12 | scripts/errors.py | 通用异常打印不友好 | 替换为友好错误(原因 + 下一步 + 自动修复入口) |

新增能力

  • 能力-1 SQLite 存储scripts/storage.py):运行 / 帧 / 产品 / 页面模块 / 差异 5 张表
  • 能力-2 对比趋势板块scripts/diff_engine.py):广告语变化、新增帧、消失帧、新增产品、消失产品
  • 能力-3 Word 自定义章节(预留接口 extra_sections
  • 能力-4 趋势折线图(matplotlib 嵌入思源字体,避免中文乱码)
  • 能力-5 OCR 低置信度自动视觉--with-vision 开关)
  • 能力-6 小白友好 7 件套
    • 一键环境(scripts/setup.py
    • 预设套餐(--preset beginner 8 家)
    • 人话报错(友好错误)
    • 5 分钟向导(--guide
    • 默认全开(无头模式、字体嵌入、含趋势 三者默认均为真)
    • 进度可视化(待 rich 库接入)
    • 小白词典(10 行术语表)

修复 v7.2 历史缺陷防回归

(v7.2 修复保留:修复-1 字体嵌入死代码 / 修复-2 爬虫失败标志 / 修复-3 简称映射 / 修复-4 未使用变量 / 修复-5 文档对齐)

测试统计

  • 单元测试 95 个用例(v7.2 时代 47 → v7.3 时代 95;最新统计见文末 v7.5 记录段)
  • 新增 v7.3 回归测试 9 个(test_bugfix_v73.py):覆盖载荷反序列化、产品独占运行查找、模块独占运行查找等

测试模块清单:

  • test_storage.py(8 用例)— SQLite 增删改查 + 索引 + 事务
  • test_diff_engine.py(6 用例)— 5 种差异类型
  • test_page_module_extractor.py(4 用例)— 模块分类
  • test_friendly_errors.py(5 用例)— 5 个错误码
  • test_word_exporter.py(14 用例)— 5 板块断言(v7.5 补齐板块 5「自动点评」6 子节 + 模块 diff 渲染)
  • test_scheduler.py(5 用例)— 定时解析 + 退避
  • test_bugfix_v73.py(9 用例)— v7.3 缺陷修复回归
  • test_commentary_engine.py(23 用例,v7.4 新增)— 点评引擎
  • test_scraper_logic.py(18 用例)— scraper 纯逻辑
  • 保留 v7.2 47 用例(应用注册 22 + 字体嵌入 7 + 爬虫逻辑 18)

📝 v7.4 升级与缺陷修复记录(2026-07-31)

v7.4 重大升级:① 修复阻断性 SyntaxError ② Word 报告新增第 5 板块「自动点评」③ APP 名单从 137 → 151 家。

修复的真实缺陷

| 编号 | 文件 | 现象 | 修复 | |-----|------|------|------| | 修复-13 | scripts/scraper.py:797 | _scrape_with_browser 的 try/finally/except 嵌套错,导致整个模块无法 import,run.py 全流程崩溃(阻断性 P0) | 重构为单层 try/except/finally:外层管异常+关 context,内层 try-finally 删除 | | 修复-14 | scripts/run.py:386/415 | 视觉校验逻辑混乱:未指定 --with-vision 也会调视觉模型(与参数语义不符) | 统一为 if with_vision and vision_available and ocr["needs_vision_verify"] | | 修复-15 | scripts/diff_engine.py:80 | 模块表 app_name 兜底用 key 当显示名,导致 diff 输出"tdx_zq"等丑陋 key | 改为 app_registry.get_app(k).name 查中文名,注册表中无则降级 | | 修复-16 | SKILL.md:189/237/253 | 测试数写"95"陈旧 | 改为"118"(v7.4 实际) | | 修复-17 | agents/openai.yaml:3 | 描述写"130+家"陈旧 | 改为"150+家" | | 修复-18 | references/app_selectors.md:6 | "第一轮 15 家深度调研"已过时 | 改为"150+ 家,按类别自动填充选择器模板" | | 修复-19 | references/scrapability_report.md:3 | "全量清单 python scripts/app_registry.py"与实际 CLI 命令不符 | 改为 python scripts/run.py --list-apps |

新增能力

  • 能力-7 APP 名单扩展(137 → 151)
    • 互联网保险(4 家):众安保险、水滴保、慧择、微保WeSure
    • 券商补充(4 家):东方财富证券、华鑫证券、湘财证券、中银证券
    • 期货补充(3 家):海通期货、银河期货、徽商期货
    • 财富管理(3 家,新类别):钜派、恒天财富、普信资产
    • 类别数 12 → 14
  • 能力-8 自动点评引擎scripts/commentary_engine.py):
    • 统计型:同类别横向对比(股份制 vs 国有大行的推广热点)+ OCR 关键词聚类(10 大推广主题)+ 产品类型分布
    • 趋势型:基于 diff 数据归纳(变化最频繁 APP、变化类型分布、营销节奏判断)
    • LLM 点评:--with-llm-comment 启用,需 VISION_API_KEY;未配置自动降级
  • 能力-9 Word 报告 5 板块化:原 4 板块基础上新增第 5 板块「自动点评」,含 6 个子节(人话要点/推广热点/产品类型/横向对比/趋势/LLM)
  • 能力-10 CLI 增强:新增 --with-llm-comment 参数;run_scrape_and_export / collect_mode 均支持
  • 能力-11 测试增强:新增 test_commentary_engine.py(23 用例),覆盖统计/趋势/LLM 三个点评来源 + 综合入口

修复 v7.3/v7.2 历史缺陷防回归

(v7.3 修复保留:修复-1~12;v7.2 修复保留:字体嵌入死代码 / 爬虫失败标志 / 简称映射 / 未使用变量 / 文档对齐)

测试统计

  • 单元测试 118 个用例(v7.2 时代 47 → v7.3 时代 95 → v7.4 时代 118
  • 新增 v7.4 测试 23 个(test_commentary_engine.py
  • 因阻断性 P0 修复,2 个之前 collect error 的测试文件(test_scraper_logic.py 18 用例 + test_word_exporter.py 8 用例)现在全跑通

运行测试:

cd D:\claude 开发\skill of me\app-home-monitor
python -m pytest tests/ -v
# 目标:>= 161 个测试通过(最新统计见文末 v7.5 记录段)

📝 v7.5 升级与缺陷修复记录(2026-08-01)

v7.5 重大升级:集中修复 P0×5 / P1×10 / P2×7 共 22 项已核实缺陷(含 5 项数据丢失级 P0),新增页面模块 diff(模块增删改),单元测试从 118 → 161

修复的真实缺陷

P0(数据丢失 / 功能失效)

| 编号 | 文件 | 现象 | 修复 | |-----|------|------|------| | 修复-20 | scripts/scraper.py | 多页采集时 frame_index 每页从 1 重新编号 → 跨页重复,写库撞键、diff 静默丢帧 | 按已收集帧数做全局偏移 index_offset,保证跨页唯一 | | 修复-21 | scripts/scraper.py | BLOCKED_URL_KEYWORDS 误含 advertising → 把要采的广告横幅 CDN 自己拦掉 | 移出拦截词;保留 doubleclick / google-analytics 等真实广告联盟 | | 修复-22 | scripts/app_registry.py | heavy_spa 含不存在的 key(cmbchina / huatai)→ 31 家券商渲染等待不足采不到 | 改为真实 key:招商证券 cmschina、华泰证券 htsc | | 修复-23 | scripts/run.py | --list-apps / --guide / --check-env 分派排在 auto_install 之后 → 纯信息命令卡几分钟下浏览器 | 信息命令分派提到 auto_install 之前 | | 修复-24 | scripts/carousel_extractor.py | _filter_decorative 异常时 fail-closed → 整页真实轮播帧被当装饰图丢弃 | 改为 fail-open:取不到尺寸时保留帧 |

P1(输出失真 / 开关失效)

| 编号 | 文件 | 现象 | 修复 | |-----|------|------|------| | 修复-25 | scripts/commentary_engine.py | 视觉模型识别出的 product_type 分支是 pass 死代码 → 产品类型分布丢视觉结果 | 补全统计逻辑;'其他'/空不计入 | | 修复-26 | scripts/commentary_engine.py | success_count 用恒不存在的 __all__ 键 → 失败样本不反映到"数据完整度" | 改为真实统计键,失败时人话要点体现完整度 | | 修复-27 | scripts/run.py | --strict 异常被外层 except 吞掉 → 承诺的"环境缺失即 raise"失效 | strict 分支显式 raise | | 修复-28 | scripts/errors.py | check_fonts 硬编码 CN 命名,与 font_embedder 的 SC 别名集不一致 → 误报 FONT_MISSING | 同步支持 SourceHanSansSC-* 命名,空目录仍报错 | | 修复-29 | scripts/deps.py | 依赖清单三份不一致,auto_install 漏装 openai → --with-llm-comment 运行时崩 | deps.py 单一真源;openai 归 OPTIONAL;auto_install 装 ALL_DEPS;requirements 去掉无 import 的 schedule | | 修复-30 | scripts/app_registry.py | resolve_apps 从不查 PRESET_ALIASES → 口语化别名(推荐/小白/主流)解析失败 | 补预设别名解析,且不劫持类别名('基金销售' 仍返回整类) | | 修复-31 | scripts/app_registry.py | dfzq_zq 与 eastmoney URL 相同 → 同页抓两遍出重复帧 | 注册表 URL 去重(回归测试强制无重复 URL) | | 修复-32 | scripts/page_module_extractor.py | [role='tab'] 同时在 NAV/TAB 选择器 → 同一元素模块双计 | role=tab 只留在 TAB_SELECTORS,两列表强制无重叠 | | 修复-33 | scripts/page_module_extractor.py | extract_modules_safe 的 timeout 声明后从未使用(死参数) | 真正 set_default_timeout 生效 | | 修复-34 | scripts/vision_verify.py | is_vision_available 未 strip → 空白 key 判为可用,每帧吃 401 | strip 后判空 |

P2(健壮性 / 性能)

| 编号 | 文件 | 现象 | 修复 | |-----|------|------|------| | 修复-35 | scripts/word_exporter.py | detail_url=None(DB NULL 回读)时 len(None) 崩 | 判空兜底 | | 修复-36 | scripts/diff_engine.py | 产品比对各按 app 重复查库,多打 2×N 条 SQL | 复用已取全量结果,内存过滤 | | 修复-37 | scripts/storage.py | bulk_insert_* 每条一个事务 → 慢 + 写放大 | 改 executemany 单事务,空输入不报错 | | 修复-38 | scripts/storage.py | frames 对 OCR 全文整列建索引 → DB 膨胀且无查询用得上 | 收窄为 substr(ocr_text, 1, 64) 前缀索引 | | 修复-39 | scripts/carousel_extractor.py | 图片去重不归一化 URL(?v=1?v=2 算两张) | _normalize_image_url 去 query / 协议 / 片段后判重 | | 修复-40 | scripts/vision_verify.py | 视觉返回空内容仍标 verified=True → 空结果被当已校验、不重试 | 空返回不标 verified | | 修复-41 | scripts/storage.py | _hash_image 失败路径全部返回 "" → 不同失败帧互相碰撞 | 失败返回空,成功哈希加宽到 32 位 |

新增能力

  • 能力-12 页面模块 diff:对比维度从帧/产品扩展到页面模块,新增 module_added / module_removed / module_changed(同名同类但跳转地址变,如活动换期)三类变化;中文名统一走 CHANGE_TYPE_CN 单一真源;word_exporter 板块 4 趋势文本与 commentary_engine 同步渲染,不吐英文 key
  • 能力-13 测试增强:新增 test_bugfix_v75.py(37 用例)逐条对应已核实缺陷 + 模块 diff 6 用例;test_storage.py 补齐事务化批量/前缀索引/哈希加宽回归

修复 v7.4/v7.3/v7.2 历史缺陷防回归

(v7.4 修复保留:修复-13~19;v7.3 修复保留:修复-1~12;v7.2 修复保留:字体嵌入死代码 / 爬虫失败标志 / 简称映射 / 未使用变量 / 文档对齐)

测试统计

  • 单元测试 161 个用例(v7.2 时代 47 → v7.3 时代 95 → v7.4 时代 118 → v7.5 时代 161
  • 新增 v7.5 回归测试 37 个(test_bugfix_v75.py):覆盖 22 项缺陷 + 页面模块 diff

测试模块清单(当前准确):

  • test_storage.py(8)— SQLite 增删改查 + 事务化批量 + 前缀索引 + 哈希加宽
  • test_diff_engine.py(8)— 5 类差异 + v7.5 页面模块 diff 3 类
  • test_page_module_extractor.py(4)— 模块分类
  • test_friendly_errors.py(6)— 6 个错误码
  • test_word_exporter.py(14)— 5 板块断言(板块 5 6 子节 + 模块 diff 渲染)
  • test_scheduler.py(5)— 定时解析 + 退避
  • test_bugfix_v73.py(9)— v7.3 缺陷修复回归
  • test_bugfix_v75.py(37)— v7.5 缺陷修复回归
  • test_commentary_engine.py(23)— 点评引擎
  • test_scraper_logic.py(17)— scraper 纯逻辑
  • test_app_registry.py(23)— 应用注册
  • test_font_embedder.py(7)— 字体嵌入

运行测试:

cd D:\claude 开发\skill of me\app-home-monitor
python -m pytest tests/ -v
# 目标:>= 161 个测试通过

📝 v8 升级与新增能力记录(2026-08-03)

v8 重大升级:从「金融 APP 首页监控」扩展为「金融机构专属公告广告监控与分析」。数据源从 151 家 APP 扩展到 210 个(+ 机构官网 + 财经媒体 + 财经论坛 + 自媒体),广告形式从图片扩展到图片 + 文字 + 视频,新增跨源横向对比、时间范围查询、舆情与情感分析。

新增能力(v8.0 / v8.1)

多数据源架构

  • 能力-14 统一数据源抽象AppConfigsource_type(app/website/media/social/forum)+ 可选字段(website_of/list_selector/item_selector/content_selector/date_selector/search_url/max_items/ad_types/account),全部带默认值 → 现有 151 条配置零改动
  • 能力-15 统一采集管线collector.py 按 source_type 分派 → 各采集器产出归一化 ScrapeResult → 下游 OCR/存储/diff/点评/报告共用一条管线
  • 能力-16 官网深爬website_collector.py):banner 轮播 + 文字广告 + 产品 + 公告/资讯页,website_of 复用既有 151 家 URL 避免重复
  • 能力-17 财经媒体新闻news_collector.py):12 家权威媒体 + 门户财经,列表→详情抓新闻标题/摘要/时间/作者
  • 能力-18 财经论坛舆论forum_collector.py):股吧/基金吧/雪球/知乎/贴吧,帖子 + 回复/浏览热度 + parse_count("1.2万"→12000)
  • 能力-19 自媒体公开部分social_collector.py):B站/美篇公开端点 + 登录墙 manual_hint 手动补充(复用蚂蚁财富模式)

广告形式扩展

  • 能力-20 文字广告text_ads 表 + 提取器):页面广告话术关键词命中提取
  • 能力-21 视频广告深度(v9 状态:计划,未实装;v9 已删除 video_extractor.py 占位脚本,待阶段2 接入采集主链路):yt-dlp/浏览器下载 → ffmpeg/opencv 抽帧 → OCR 帧内容 → whisper ASR 转文字(工具全部可选,缺失降级)

分析能力

  • 能力-22 跨源横向对比cross_source_summary):公司维度(广告投放量=帧+文字+视频)vs 平台维度(APP/官网/媒体/论坛/自媒体活跃度)
  • 能力-23 舆情热点public_opinion_hotspots):帖子关键词聚类 + 热帖榜
  • 能力-24 情感分析sentiment_analysis + text_analysis.py):词典级离线兜底 + 模型级(OpenAI 兼容,复用 VISION_API_KEY),--with-llm-analysis
  • 能力-25 时间范围查询--query --since/--until + query_engine.py,从数据库读窗口数据出对比报告
  • 能力-26 diff 扩展:CHANGE_TYPE_CN 从 8 → 20 类(news_added/removed/changed、post_added/removed/post_hot_changed、text_ad_added/removed/changed、video_added/removed/changed)
  • 能力-27 Word 10 板块:新增六(媒体新闻)/七(舆论监控)/八(文字广告)/九(视频广告)/十(跨源横向对比)

工程

  • 能力-28 存储迁移_migratePRAGMA table_info 守卫 ALTER TABLE 幂等加列(兼容老 db);news/posts/text_ads/videos 4 张新表 + bulk 单事务;list_runs/get_latest_run 三表 UNION → 七表
  • 能力-29 依赖/错误扩展:deps.py OPTIONAL 加 cv2/yt_dlp/whisper;errors.py 加 VIDEO_TOOL_MISSING/MEDIA_BLOCKED/SOCIAL_LOGIN_WALL

修复的真实缺陷(v8 实测发现)

| 编号 | 文件 | 现象 | 修复 | |-----|------|------|------| | 修复-42 | scripts/scraper.py | PostItemurl 字段,论坛采集器传 url 直接崩 | 加 url 字段(posts 表同步加列) | | 修复-43 | scripts/word_exporter.py | 新闻表格用 n.source_name,而 NewsItem 无此属性 → Word 生成崩 | 改 getattr(n, "source_name", "") or r.app_name | | 修复-44 | scripts/commentary_engine.py | v8 新函数直接 r.source_type,旧 FakeResult 测试无此属性 → 旧测试崩 | 改 getattr(r, "source_type", "app") | | 修复-45 | scripts/storage.py | save_results 直接访问 n.url 等属性,字段不全的桩数据崩 | 全改 getattr 兜底 | | 修复-46 | scripts/registry_websites.py | 6 家基金公司官网 URL 与既有 151 家 APP 重复,触发 URL 唯一断言 | 改 website_of 关联复用(如 nffund→southernfund) |

测试统计

  • 单元测试 313 个用例(v7.5 时代 161 → v8 时代 311,新增 150 + v8.2 回归 2)
  • v8 测试文件 12 个:
    • test_source_registry.py(26)— 多数据源注册表 + resolve_sources
    • test_news_collector_logic.py(12)— 新闻标题清洗/日期/正文提取
    • test_forum_collector_logic.py(12)— parse_count 万/亿/k + 热度启发式
    • test_storage_v8.py(20)— 新表 CRUD/bulk/迁移/时间范围/七表 UNION
    • test_diff_v8.py(14)— 新闻/帖子/文字广告/视频 diff + 热度阈值
    • test_commentary_v8.py(16)— 跨源对比/舆情热点/情感分析
    • test_word_exporter_v8.py(9)— 10 板块空安全 + 各数据源渲染
    • test_run_query_mode.py(12)— --since/--until/--query 窗口查询
    • test_text_analysis.py(14)— 词典情感/主题/批量/无 key 降级
    • test_video_extractor_logic.py(5)— 视频采集 mock 全链路
    • test_social_collector_logic.py(6)— 自媒体注册表 + manual_hint
    • test_cli_dispatch.py(2)— collector APP 分派 + --query 不触发自动安装

运行测试:

cd D:\claude 开发\skill of me\app-home-monitor
python -m pytest tests/ -v
# 目标:>= 313 个测试通过

📝 v8.2 实测优化记录(2026-08-03)

本轮通过完整单元测试 + 真实 CLI 冒烟(媒体源、APP 源、查询模式、环境检测)发现并修复:

| 编号 | 文件 | 现象 | 修复 | |-----|------|------|------| | 修复-47 | scripts/collector.py | collector.py 把 APP 分组传成 list,scrape_apps 期望 dict → 任何 APP 采集直接崩溃 | 分派时改传 {c.key: c for c in cfgs},其他采集器仍传 list | | 修复-48 | scripts/run.py | --query 是纯读库命令,却在 auto_install 之后分派 → 空查询实测卡 100 秒并尝试下载字体 | 把 --query 提前到 auto_install 之前,实测降至约 0.2 秒 | | 修复-49 | scripts/_auto_install.py / scripts/errors.py | Tesseract 已装在默认目录但不在 PATH,环境检测误报缺失 | 检测逻辑增加 Windows 常见安装路径兜底,--check-env 实测识别为 5.4.0 |

验证结果

  • python -m pytest tests/ -q:313 passed + 151 subtests passed
  • python scripts/run.py --apps 天天基金 --skip-auto-install:正常出 Word,32 个产品、3 帧
  • python scripts/run.py --query ...:0.19 秒返回,不触发自动安装
  • python scripts/run.py --check-env:Tesseract OCR 识别成功

另发现:--with-video--with-llm-analysis 目前仍是 v8 阶段2 预留参数,尚未真正接入采集主链路;本轮按最小范围未扩展该功能。


📝 v9 升级与缺陷修复记录(2026-08-03)

本轮承接同一日的 v8:用户报告 Word 报告 字体图表显示错误,同时要求 增强与用户的互动对话能力,并补充 优化性能 + 清理无法使用的文件

修复的真实缺陷

| 编号 | 文件:行 | 现象 | 修复 | |---|---|---|---| | 修复-50 | scripts/word_exporter.py:_add_trend_chart | 趋势图注册中文字体用 fcfg.get("path") 取路径,但 font_embedder.get_default_font_configs() 返回的 dict 键是 regular/bold/italic/bold_italicfpath 永远 Nonefont_manager.addfont 从未被调用 → 图中的中文标签(时间/标题/轴)全是豆腐框(□□□) | 抽出 _register_mpl_chinese_fonts() 模块级缓存函数,正确遍历 4 个权重键调 addfontrcParams["font.sans-serif"] 用实际 family name(Source Han Sans SCNoto Sans CJK SC);已注册的思源字体下也兼容 Noto 命名 | | 修复-51 | scripts/word_exporter.py:884 | 封面写死 "130+家金融APP(12类别:...)",但 v8 已扩到 151 家 + 5 类 source_type(app/website/media/forum/social) | 改为动态文案:从 app_registry.APPSlen(APPS) + len({cfg.source_type for cfg in APPS.values()}),输出形如 "监控范围:151 家金融APP(5 类数据源:APP首页、机构官网、财经媒体、财经论坛、自媒体)" | | 修复-52 | scripts/word_exporter.py:_add_trend_chart | _add_trend_chart 对空 runs 入参会进 plt.subplots 后报诡异错误;用 NamedTemporaryFiletry 之外 close 偶发 Windows unlink 失败 | 加 empty-timestamps 守护;改 tempfile.mkstemp + os.close(fd)finally 强制 unlink;dpi 120→150 | | 修复-53 | scripts/word_exporter.py:set_cell_font | 原实现 cell.text = "" 销毁默认段落并新建,151 APP × 5 表 × N 单元格时累计浪费可观 | 改为对默认段落 cell.paragraphs[0] 直接清旧 runs 再 add_run,省掉段落重建开销 |

清理的死代码

| 文件 | 类型 | 删除理由 | |---|---|---| | scripts/video_extractor.py(188 行) | 生产脚本占位 | v8 标为"阶段2 计划",整库 0 生产调用(collector.py 不分派到它);social_collector.py 仅以 docstring 提及 | | tests/test_video_extractor_logic.py(76 行) | 上述脚本的测试 | 母文件删除后测试失效 | | tests/test_bugfix_v73.py(147 行) | 旧回归测试 | 其覆盖的载荷反序列化/产品查找/模块查找 9 个用例已被 test_bugfix_v75.pytest_word_exporter_v8.pytest_storage.py 全部替代 |

合计删除 411 行 无用代码 + 同步清理 SKILL.mdregistry_social.pysocial_collector.py 中对 video_extractor 的引用(改为"阶段2 计划"措辞)。

新增能力

  • 能力-22 趋势图字体注册独立模块化_register_mpl_chinese_fonts() 配合模块级 _MPL_FONTS_REGISTERED 缓存,第一次跑注册一次字体,所有后续 trend chart 复用,避免 matplotlib fontmanager 反复 IO + 重建。_register_mpl_chinese_fonts() 返回已注册字体文件名列表(用于诊断)
  • 能力-23 对话式交互模式:完整重写 scripts/run.py:interactive_mode()3 步向导(范围→浏览器→附加能力),关键设计:
    • 每步都附「📋 等价命令」:用户可直接复制到命令行运行,减少学习成本
    • CATEGORY_ALIASES 别名映射:内置"基金销售/银行/券商/保险/期货/第三方销售/互联网理财/财富管理"中英文别名
    • 输入兜底识别:用户随便输入(逗号/类别/套餐名)都能识别
    • 表格框 + emoji:让终端易扫读
    • 启动前摘要:范围/模式/附加 三项先确认再跑
  • 能力-24 趋势图运行时埋点_add_trend_chartprint(" 趋势图渲染: X.YYs (N KB)") 耗时输出,便于后续 profile

性能优化(汇总)

| 项 | 文件 | 效果 | |---|---|---| | matplotlib 字体注册模块级缓存 | word_exporter.py | 多次生成趋势图免重 IO + 避免 fontmanager 重建 | | 单元格写入微优化 | word_exporter.py:set_cell_font | 干掉 cell.text = "" 段落重建,151 APP × N 单元格累计可观 | | 趋势图 dpi 120→150 | 同上 | 视觉清晰度提升 | | 趋势图临时文件强清理 | 同上 | mkstemp + finally 保证 PNG 留不下 | | 趋势图耗时埋点 | 同上 | 输出每次渲染耗时,便于后续分析 |

基准(Python 3.11 + python-docx):30 APP × 5 产品 × 3 帧 Word 生成 ~1.7s;151 APP 等比 ~8s——网络爬取才是真正瓶颈。

修复 v8/v8.2/v7.5/v7.4/v7.3/v7.2 历史缺陷防回归

(v8 修复保留:修复-42~49;v7.5 修复保留:修复-20~41;v7.4 修复保留:修复-13~19;v7.3 修复保留:修复-1~12;v7.2 修复保留:字体嵌入死代码 / 爬虫失败标志 / 简称映射 / 未使用变量 / 文档对齐)

测试统计

  • 单元测试 299 passed / 3 skipped / 151 subtests(v8.2 时代 313 → v9 时代 299,删除 16 个 v7.3 老用例被重复覆盖的,新增 5 个 v9 回归 + 3 个依赖 matplotlib 的用例在未装环境 skip)
  • v9 测试文件新增 + 删除:
    • 新增 tests/test_word_exporter_v9_bugfix.py(5 用例):
      • test_register_uses_regular_key_not_path —— 守住修复-50(addfont 必须被调到,键必须是 regular/bold/italic/bold_italic
      • test_register_handles_no_fonts —— 空 fc 时不崩(修复-50 守护)
      • test_add_trend_chart_handles_empty_runs —— 修复-52(空 runs 不崩)
      • test_word_scope_text_not_hardcoded —— 修复-51(不再含 "130+家" 字面量)
      • test_word_scope_text_reflects_real_source_types —— 修复-51(含真实 source_type 集合)
    • 删除 tests/test_bugfix_v73.py(9 用例,其覆盖的载荷反序列化/产品查找/模块查找 9 个用例已在 test_bugfix_v75.pytest_word_exporter_v8.pytest_storage.py 等更现代测试中)
    • 删除 tests/test_video_extractor_logic.py(5 用例,母文件 video_extractor.py 已删)

当前测试模块清单(22 个文件,299 用例):

| 文件 | 用例数 | 说明 | |---|---|---| | test_storage.py | 8 | SQLite 增删改查 + 事务化批量 + 前缀索引 + 哈希加宽 | | test_storage_v8.py | 20 | 新表 CRUD / bulk / 迁移 / 时间范围 / 七表 UNION | | test_diff_engine.py | 8 | 5 类差异 + v7.5 页面模块 diff 3 类 | | test_diff_v8.py | 14 | 新闻/帖子/文字广告/视频 diff + 热度阈值 | | test_page_module_extractor.py | 4 | 模块分类 | | test_friendly_errors.py | 6 | 6 个错误码 | | test_word_exporter.py | 14 | 5 板块断言(板块 5 6 子节 + 模块 diff 渲染) | | test_word_exporter_v8.py | 9 | 10 板块空安全 + 各数据源渲染 | | test_word_exporter_v9_bugfix.py | 5(新) | v9 修复回归:字体注册 + 动态文案 + 空 runs 守护 | | test_scheduler.py | 5 | 定时解析 + 退避 | | test_bugfix_v75.py | 37 | v7.5 缺陷修复回归 | | test_commentary_engine.py | 23 | 点评引擎 | | test_commentary_v8.py | 16 | 跨源对比/舆情热点/情感分析 | | test_scraper_logic.py | 17 | scraper 纯逻辑 | | test_app_registry.py | 23 | 应用注册 | | test_source_registry.py | 26 | 多数据源注册表 + resolve_sources | | test_news_collector_logic.py | 12 | 新闻标题清洗/日期/正文提取 | | test_forum_collector_logic.py | 12 | parse_count 万/亿/k + 热度启发式 | | test_social_collector_logic.py | 6 | 自媒体注册表 + manual_hint | | test_text_analysis.py | 14 | 词典情感/主题/批量/无 key 降级 | | test_font_embedder.py | 7 | 字体嵌入 | | test_run_query_mode.py | 12 | --since/--until/--query 窗口查询 | | test_cli_dispatch.py | 2 | collector APP 分派 + --query 不触发自动安装 | | 删除 ~~test_bugfix_v73.py~~ | ~~9~~ | v9 移除(已被 v7.5/v8 测试覆盖) | | 删除 ~~test_video_extractor_logic.py~~ | ~~5~~ | v9 移除(母文件已删) |

运行测试:

cd D:\claude 开发\skill of me\app-home-monitor
python -m pytest tests/ -v
# 目标:>= 299 个测试通过(matplotlib 装好后 302 全过)

验证结果

  • python -m pytest tests/ -q299 passed, 3 skipped, 151 subtests passed
  • python scripts/cleanup_cache.py:清理 11 个 .pyc 缓存项

后续可能跟进(v9 没做、值得跟)

  1. 装 matplotlib 后跑一次现状报告,肉眼验证中文标签正常(当前环境 matplotlib 未装,bug-1 测试 skip)
  2. set_cell_font 进一步走 style.font + add_run 批量模式(python-docx 支持;先 benchmark 再决定)
  3. 视频广告深度采集(--with-video)阶段 2 实装——删除 video_extractor.py 后该能力彻底未接;后续要做时建议先补 stub + 测试再写实现,避免再次变成永久占位
  4. 交互模式向导目前是纯 input() 串行,未来可考虑走 AskUserQuestion 提升体验

📝 v9.1 升级记录(2026-08-10)

聚焦「广告/公告信息获取增强 + 竞品分析对比能力」。

新增模块(2 个)

1. scripts/ad_fetcher_enhance.py(325 行)

  • AD_HINT_KEYWORDS_V2:广告话术关键词 30 → 100+(9 大类:促销/拉新/福利/收益/行动/节日/品牌/教育/投资)
  • is_ad_text() / extract_ad_score():广告强度识别与打分
  • extract_video_posters_from_html():视频海报帧提取(v8 阶段 2 部分实装)
  • extract_bg_images_from_css() / extract_bg_images_from_html():背景图 CSS 解析增强
  • compute_hot_score() / classify_hot_level():综合热度评分(点赞×1 + 回复×5 + 浏览×0.1)
  • parse_date_flex() / format_relative_date():灵活日期解析(相对+绝对)
  • classify_ad_intent():4 类广告意图分类(拉新/促活/留存/挽回)

2. scripts/competitor_comparator.py(380 行)

  • compute_metric():单竞品指标计算
  • compare_by_category():同类别横向对比(成员数 < min_members 跳过)
  • compare_by_platform():跨平台投放对比
  • cross_platform_summary():跨平台汇总(Word 报告用)
  • compute_ad_similarity() / compare_ad_similarity():广告语 Jaccard 相似度
  • intensity_leaderboard():全市场投放强度 TOP N
  • full_competitor_report():完整竞品分析报告(一键产出 4 大板块)

数据类(4 个)

  • CompetitorMetric:单竞品指标(轮播/产品/文字广告/模块/新闻/帖子 + 推广热点 + 产品类型 + 强度分)
  • CategoryComparison:同类别对比报告(含 hotsales_top3 / product_types_top3 / intensity_leader / highlights)
  • PlatformComparison:跨平台对比报告
  • AdSimilarityReport:广告语相似度(含 jaccard / common_phrases / only_a / only_b)

BUG 修复(6 类)

  • 🐛 BUG-001 广告关键词不足:30 → 100+
  • 🐛 BUG-002 视频海报帧未实装(v8 阶段 2 遗留)→ v9.1 部分实装
  • 🐛 BUG-003 背景图 CSS 仅支持单引号 → 三引号 + data:URI/关键字过滤
  • 🐛 BUG-004 日期解析只支持 ISO 格式 → 新增相对时间("X 分钟前"/"昨天")
  • 🐛 BUG-005 帖子热度无综合评分 → 点赞×1 + 回复×5 + 浏览×0.1 加权
  • 🐛 BUG-006 广告意图无分类 → 4 类意图(拉新/促活/留存/挽回)

测试覆盖

  • ✅ 新增 tests/test_v91.py81 个测试):
    • ad_fetcher_enhance:关键词/视频海报/背景图/热度/日期/意图 6 个 TestClass
    • competitor_comparator:单指标/同类别/跨平台/相似度/排行榜/完整报告 6 个 TestClass
    • BUG 修复回归:6 个 BUG
    • 集成测试:增强→对比完整链路
  • 全套 441 passed 1 skipped(v9 360 + v9.1 新增 81)

使用示例

from competitor_comparator import full_competitor_report

# 完整竞品分析报告
report = full_competitor_report(scrape_results)
for h in report["highlights"]:
    print(h)

# 同类别对比
for cat_rpt in report["by_category"]:
    print(f"{cat_rpt['category']}: {cat_rpt['member_count']} 家,强度第一 {cat_rpt['intensity_leader']}")

# 投放强度 TOP 10
for m in report["intensity_leaderboard"][:10]:
    print(f"{m['app_name']}: {m['intensity_score']:.0f}")

# 广告语相似度
for pair in report["similarity_pairs"]:
    print(f"{pair['app_a']}{pair['app_b']}: Jaccard={pair['jaccard']:.2f}")
from ad_fetcher_enhance import (
    is_ad_text, extract_ad_score,
    compute_hot_score, parse_date_flex,
    classify_ad_intent,
)

# 广告强度打分
score = extract_ad_score("限时抢购 新户专享 立减100")
# → 6(命中 6 个关键词)

# 热度综合评分
hot_score = compute_hot_score(like_count=10, reply_count=20, view_count=5000)
# → 610.0

# 灵活日期解析
dt = parse_date_flex("3 小时前")
# → 当前时间 - 3 小时

# 广告意图分类
intent, score = classify_ad_intent("新户专享 立减100")
# → ("拉新", 2)

📝 v10.0 优化与缺陷修复记录

核心修复(4 大断点)

  • 🐛 v10-BUG-001 ad_fetcher_enhance(158 词库/意图/视频海报/bg 解析)是死代码,零调用 → 全面接入 scraper + website_collector 主路径;文字广告入库附 ad_score + ad_intent
  • 🐛 v10-BUG-002 competitor_comparator(竞品强度榜/相似度/品类矩阵)从未被 run.py 调用 → 接入报告流水线,Word 新增板块 11「竞品投放对比」(强度 TOP10 柱状图/品类矩阵/相似对/素材复用)
  • 🐛 v10-BUG-003 frames 表无 image_url 列(原始广告图 URL 入库即丢) → 迁移补列 + insert/bulk SQL 修正 + 下载失败帧可重试
  • 🐛 v10-BUG-004 视频广告被 BLOCKED_RESOURCE_TYPES 的 "media" 全拦(素材加载被拦死) → 移除 media 全拦,改为第三方广告域白名单拦截 + extract_videos producer 实装

分析升级(10 项)

  • 强度分四维加权(数量 40% + 素材多样性 20% + vision 质量 20% + 意图覆盖 20%)+ 品类内 z-score
  • 素材复用检测 detect_shared_assets(image_hash 跨 APP 聚类"同图多投")
  • 广告语相似度 Jaccard → TF 加权 cosine + n-gram 共现短语
  • diff:text_changed 相似度阈值防 OCR 抖动误报、frame_image_changed(同位置图变)、 video_changed 实装、换序降误报(frame_added 标注"疑似轮播换序")
  • 时间趋势 diff_trend(N-run 序列环比:帧数/产品数/主题热度)
  • OCR:OSD 方向回正 + PSM 多通道重试 + 逐词置信度 + NFKC 归一化 + image_hash 缓存
  • 视觉校验:verify_batch 并发(5 线程)+ 图片压缩(长边≤1568)+ 指数退避重试 + 结果缓存 + schema 校验
  • LLM 整页点评专用四段式 prompt(布局/主推产品/营销策略/风险提示)
  • 情感词典 200+ 金融词 + 否定词翻转("未出现违规"不再误判负面)+ 模型并发 + 文本缓存
  • 平台对比口径统一(total_items 不再混入 news/posts,与强度分一致)

性能提升(3 项)

  • 图片并发下载(4 线程)替代串行(30 帧最坏 15 分钟 → 秒级)
  • save_results_to_storage 主路径统一 bulk 单事务(200 帧 200 事务 → 1 事务)
  • 单 APP 软超时保护(默认 180s,防一个卡死拖垮整批)

测试覆盖

  • ✅ 新增 tests/test_v10.py31 个测试):ad_fetcher 集成 / 存储迁移 / 图片质量 / 强度分多维 / 素材复用 / TF-cosine / diff 阈值与帧图变 / diff_trend / OCR 归一化与缓存 / vision 压缩与并发 / 文本否定词 / Word 竞品板块 / 视频结构
  • 全套 472 passed 1 skipped(441 + v10 新增 31)

📝 v10.1 优化与缺陷修复记录

轮播抓取盲区修复(7 项)

  • 🐛 v10.1-BUG-001 background 轮播只扫 3 类 class + 单 url()(多背景 url(a),url(b) 丢第 2 张) → 重写 _CAROUSEL_SCAN_JS:全页面大尺寸块级启发式 + _split_bg_urls 多 url 拆分
  • 🐛 v10.1-BUG-002 CSS 伪元素 ::before/::after 背景图完全不可见 → 扫描 JS 增加 getComputedStyle(el, '::before'/'::after') 分支
  • 🐛 v10.1-BUG-003 iframe / shadow DOM 内轮播完全不可见 → page.frames 遍历 + shadowRoot 递归 pierce
  • 🐛 v10.1-BUG-004 canvas 绘制轮播无指示器时仅截 1 帧顶部 400px → _autoplay_burst_shots 自动连拍(2s×8 + 字节去重)+ _CAROUSEL_BOX_JS 容器精确定位
  • 🐛 v10.1-BUG-005 JS 动态渲染 swiper(IO 懒渲染/虚拟列表)帧缺失 → _wait_swiper_stable(slide 数量 3 次采样稳定)
  • 🐛 v10.1-BUG-006 指示器缺失/不可点时无切换手段 → INDICATOR_SELECTORS 增加左右箭头 + _SWIPER_NEXT_JS(slideNext 驱动)
  • 🐛 v10.1-BUG-007 151 家 carousel_selector 全模板,文档 15 家精配从未进代码 → _CAROUSEL_OVERRIDES 字典落地(天天基金 .banner_box/#top_banner 等)

分析强化(3 项)

  • 🐛 v10.1-BUG-008 帧去重只到 URL 归一化,内容级重复帧全链路浪费 → _dhash_image / _dedup_frames_by_dhash(dHash 汉明距离 ≤4 视为同素材)
  • 🐛 v10.1-BUG-009 截图兜底帧整页 400px 噪声大 → _CAROUSEL_BOX_JS 精确定位轮播容器 clip
  • 🐛 v10.1-BUG-010 截图帧 vision 按"单张广告图"prompt 误判 → verify_image(is_page_shot=True) + PAGE_SHOT_PROMPT

链路强化(2 项)

  • _retry_download_frame:下载失败帧 OCR 阶段按 URL 重试
  • run.py 两处 OCR 循环并发化(6 线程)

测试覆盖

  • ✅ 新增 tests/test_v101.py27 个测试):多 url 拆分 / dHash 去重(同图/异图/缺失 fail-open)/ 扫描 JS 常量(伪元素/多url/data-bg/shadow/性能上限)/ 容器定位 JS / slideNext JS / 箭头指示器 / 连拍参数 / swiper 稳定等待 / 配置精配覆盖(key 存在性+模板生效+未精配不变)/ 失败帧重试 / vision 页面模式
  • 全套 499 passed 1 skipped(472 + v10.1 新增 27)