task1 完成 #3

Merged
202400507129 merged 8 commits from task1 into main 2026-09-08 00:42:31 +08:00
Owner
No description provided.
功能
- crawl_gate.py:跨进程爬取互斥门闩(SQLite BEGIN IMMEDIATE 单行 lease +
  preempt 表;心跳 20s / 假死 75s 强抢 / 协作式让出)
- tracker_store.py / tracker_worker.py:话题跟踪状态库与独立 worker 进程
  (每 60min 空闲抢占一轮,preempt 检测中止让出手动分析)
- pipeline.run_staged_crawl:抽取公共编排(Stage① sweep 并发 + 屏障 +
  Stage② enrich),手动 run_dual 与 worker 复用;SSE 事件形状不变
- crawler_runner:crawl_session(kind) 双层锁 + abort_event 支持
- /api/tracker/{start,stop,status}(仅 1 话题,新话题自动替换,立即首轮)
- AnalyzeRequest.autoCrawl 透传:false = 读库直出(run_enrich 纯读库 + LLM,
  跟踪态汇总用),友好错误文案
- 前端:SearchPanel 跟踪开关(按钮变「开始跟踪」)、TrackStatusBar 状态卡/
  细条、LoadingState readonly 分支、App 10s 轮询集成
- start-local.bat/.sh 集成 worker 窗口;新增 start-tracker.bat

修复与卫生
- SearchPanel 输入=正在跟踪话题时自动勾选(watch 双向同步)
- README/backend-README 消除遗留 git 冲突标记并更新至双模+跟踪现状
- .gitignore:MediaCrawler sqlite 运行库(db/wal/shm/journal)与 .workbuddy/
- 解除误跟踪的 sqlite_tables.db-wal/-shm

测试:新增 33(gate/store/worker/autocrawl 离线夹具),全量 85 passed
按多轮拍板方案实施,普通分析以快为主、跟踪累积详实数据:

档位分层(阶段1)
- config 新增 manual_sweep_notes=24/manual_enrich_notes=3/manual_enrich_comments=20
  (手动快档削 enrich 深度、保留 5 平台广度,目标 3-5 分钟)
- pipeline 新增 CrawlProfile/PROFILE_FULL/profile_from_settings;run_staged_crawl/
  run_dual 支持 profile(字段优先、None 回落 settings),进度事件带 profile:fast|full
- crawler_runner.run_crawl 支持 notes/comments 覆写;analyzer 手动路径走 fast 档
- tracker_worker 显式 PROFILE_FULL(回落 30/4×30 深度档)

近期缓存 + GC(阶段3/4)
- tracker_store 新增 topic_cache 表与 touch/is_topic_active/list/remove/tracked_keyword
- 新建 services/topic_cache.py:delete_topic_from_media_db(source_keyword 精确匹配+
  评论级联+fuzzy 失配中止防误删)+ gc_topics(TTL 30 天/LRU 上限 20/跳过 tracked/
  30min 节流),analyze 成功与 worker tick 惰性触发
- analyzer 缓存判定:active 7 天内再搜 → 爬新 + 读库大窗合并;读库直出恒大窗
- loader 支持 lookback_days 时间窗(无时间/解析失败行保留);run_dual/run_enrich
  delta.mergedDays 透出;analyzer 响应 delta.scope=fast|readonly(schemas 放宽含 str)

修复与前端
- crawler_loader._parse_ts 字符串分支按输出长度 19/16/10 切片(旧按 len(fmt) 切,
  文本时间戳恒解析失败——影响时间窗与真实趋势覆盖)
- ResultHero:快速模式/跟踪直出/已合并近N天历史 徽标 + meta 文案;LoadingState
  文案对齐 fast 口径;Icon 新增 bolt/database
- 测试:新增 test_topic_cache(17)/test_profile_budgets/test_loader_lookback +
  dualmode 集成 3 例 + scope 契约断言;全量 117 通过;前端 build 通过
按三条反馈实施:
1) 趋势明确「近期」防误导——标题改「近期热度趋势与预测」,按
   delta.mergedDays+scope 给三种真实口径(跟踪直出/合并历史/本次新爬),
   附「近 N 天」徽标与 tooltip 解释;footer「已发生」→「已发生(近期)」。
2) 全局平台 icon——新增 composables/platforms.js(PLATFORMS+ALIAS+byName
   唯一源,覆盖完整/短码/中文名三向)与 PlatformIcon.vue(品牌主色+单字
   微/B/书/抖/快/吧/知 徽标)。PlatformDist/ReferenceList/LoadingState
   平台行/ResultHero 来源 chips 全部接入。
3) 手动/追踪 UI 优化——TrackStatusBar「累计报道」→「最近一轮」并按
   cycles=0 提示首轮未完成;ReferenceList 顶部/底部过时「360/头条/百度
   热搜」改为「微博/小红书/B站/抖音/贴吧」+ 官方置顶;ResultHero 来源
   改 icon chips 由真实 platformDist 驱动;LoadingState 平台行圆点换
   PlatformIcon + 三态柔色环,失败行置灰区分。

构建通过;Playwright 截图冒烟(11 区块,临时 demo-ui 已清)视觉一致。
- PlatformIcon.vue: prop key → platform(模板 :key 为 vnode 保留指令,作 prop 名
  永远收不到值 → 图标全走灰「讯」兜底),同步修正注释
- platforms.js: RAW 主键改完整平台码(weibo/xhs/bilibili/...),短码 wb/bili/dy/ks
  收进 ALIAS 映射,对齐 loader 产物 source 与 platformDist[].key
- ReferenceList.vue: 参考集包进 .ref-scroll 限高 396px 内滚动,底部 note 左右分栏
  +「共 N 条 / 框内滚动查看更多」提示,杜绝长列表把卡片无限拉高
- CommentsList.vue: 评论包进 .comment-scroll 限高 424px 内滚动,平台标签改
  PlatformIcon 品牌图标 + 中文名,底部 comment-foot 计数与滚动提示
- 其余 3 处使用点同步 :key → :platform
需求:高频词统计显示换成词云(选合理词数);「大家怎么看」板块细分情绪
尚未落地——前端 SentimentDonut 早已写好 sentiment.emotions 渲染,但后端
从未产出该字段,Pydantic 默认丢弃 → 板块恒空。

后端:
- nlp.extract_keywords_weighted:jieba TF-IDF withWeight 透出分数,
  topK 放量 2 倍再滤停用词/单字,保证取满 24
- stats.compute_stats:① 对每条文本 detect_emotions(词典 8 类,可多标签)
  Counter 聚合 → emotions[{label, value, color}](命中占比 1-100、按命中数降序
  取前 6、色取词典预置主题色);② 产出 keywordCloud[{word, weight}] ≤24,
  保留 keywords 字符串供 summarizer/旧契约
- schemas:SentimentSummary 加 emotions: list[EmotionItem](value 0-100 +
  color);StatsBlock 加 keywordCloud: list[KeywordCloudItem](word+weight)
- analyzer:StatsBlock 组装透传 keywordCloud(SentimentSummary(**senti)
  自动带上 emotions)
- tests:细分情绪分布 + 词云带权两个专项测试(占比降序/<=100/#色/权重降序/
  与 keywords 同源首词一致),全套 118 passed

前端:
- OpinionTags:高频词块改词云——字号 12-26px 随 sqrt(weight/max) 映射(平方根
  压缩 TF-IDF 长尾避免 90% 词挤最小字号),4 档主题色阶(深青→墨→中灰→浅灰),
  hover 上浮变主题色;旧 keywords 字符串自动回落兜底
- SentimentDonut:emotions 空时显示「暂无细分情绪」空态(旧数据/无命中不白屏)
- mockAnalysis normalize 透传 keywordCloud 与 emotions 默认值

冒烟(Playwright DOM 断言):24 词取满、10 档字号梯度、最高权词 26px+主题色、
情绪 6 条占比降序渲染、空态文案正常、无 console error
背景:细分情绪初版以全部文本作分母,语料中大量中性/陈述评论把占比稀释
成个位数(120 条里 6 条担忧 → 5%,视觉上像没信号),用户反馈存疑。

改动:
- stats.compute_stats:先逐条 detect_emotions 收集命中,分母改为
  emo_carriers(命中≥1 情绪词的文本数)——语义变为「在有情绪表达的评论
  中带该情绪的占比」,量级可读(6/40≈15%);一条文本可带多标签,占比
  合计可>100(又愤怒又担忧两边都算),条形各自独立
- nlp.py:EMOTION_LEXICON 值改 (polarity, words),颜色由 POLARITY_COLORS
  统一(pos 绿 #2f9e6f / neu 灰 #a29c94 / neg 红 #d95d4a,与环图图例一致);
  祈福归 neu(灾难语境的关切祝愿,非事件正面评价——避免负面事件下祈福
  刷绿误导)、支持/期待归 pos、愤怒/质疑/担忧/讽刺归 neg;
  新增 EMOTION_POLARITY 导出
- schemas:EmotionItem 增 polarity 字段(pos/neu/neg)
- SentimentDonut:情绪名与条形同按极性色渲染(name 内联 color),
  hover/title 带极性文案(如「担忧(负面情绪)」)
- tests:新增分母语义回归用例(10 条文本仅 2 条带情绪 → 各≈50% 而非
  被稀释成 20%;断言 polarity ∈ pos/neu/neg),全套 119 passed

冒烟(Playwright DOM):愤怒/担忧/质疑=红 rgb(217,93,74)、祈福/吃瓜=灰、
支持=绿;name 色=条色;title 极性文案正确;无 console error
需求:词云不够生动——色彩单调(灰阶 4 档)、排布是 flex 折行(长方形
无云感)、字号 12-26px 区分不明显。

实现(纯手写,无外部词云库):
- 云形布局:560×272 画布(viewBox 等比自适应卡片宽度),按权重降序
  依次用阿基米德螺旋(r=4+1.9×step、角步 0.28rad)+ 矩形碰撞检测放置;
  y 方向压缩 0.78 让整体呈椭圆云朵;大词先落中央成为视觉锚点,小词
  沿螺旋向外绕;碰撞矩形与展示数据分离(否则全部判定不重叠堆在中心)
- 字号:13~40px 随 sqrt(w/max) 映射(11 档梯度,高低权均值差 22px),
  三档降级 1/0.86/0.72 保证画布塞满前必能落位、不越界
- 色彩:8 色盘(深青/珊瑚/蓝/琥珀/绿/紫/玫红/青灰)按放置序轮转,
  相邻词不同色;fill-opacity 0.72~0.98 随权重,重词实轻词透
- measureText 用惰性 canvas 精确量词宽(中文 ≈1em、数字/字母更窄)
- tooltip 用 <g><title> 包裹(title 不能直接嵌 text,会让 textContent
  重复);hover 上浮 + 提亮;aspect-ratio 保持 SVG 高宽比

冒烟(Playwright DOM 断言):24 词 0 重叠 0 越界、归一化最大半径 0.95
(铺满椭圆)、最大词居中 norm=0.01、字号 13-40px 11 档、8 色全用、截图
目检呈椭圆云朵形态;vite build 通过
- 特性:双模管线补档位分层(手动 fast / 跟踪 full)+ 近期话题缓存冷热分层与惰性 GC;
  可视化补云形词云(8 色螺旋铺排/字号随权重)、细分情绪 8 类按极性三色、平台单字徽标体系
- 架构:run_dual 数据量按 fast 档标注、补 topic_cache 层;结果页改三步结构说明(含参考集/来源分布/评论滚动收纳)
- 新增「分析档位与近期话题缓存」机制表
- 配置表:补 YUJIAN_MANUAL_* 与 YUJIAN_TOPIC_* 系列
- 测试:85 → 119 passed,覆盖清单补档位/缓存/统计边界(细分情绪占比、词云带权)
- 项目结构:补 composables/platforms.js、services/topic_cache.py、nlp.py
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
202400507129/yujian!3
No description provided.