- run_dedup: 生产模式重复率仅作 WARNING 告警,不影响退出码(执行成功即 0)
- run_dedup: 新增 --strict 验收模式(重复率 > 5% 返回 1),保留 M3 验收门槛
- run_dedup: 新增统计快照 data/deduped/{date}/stats.json(原子写)
- run_dedup: 顺带修复空日场景 sources.json 写入 FileNotFoundError
- pipeline: 移除 dedup rc=1 特判,恢复'非 0 即失败'统一语义
- 新增 tests/test_run_dedup.py 7 个测试;全量 266 passed
23 KiB
continuation.md
checkpoint@ 2026-08-22
本次完成 (2026-08-22) — P1-1 修复 dedup 高重复率返回码语义
问题:run_dedup 重复率 > 5% 时返回 1;scheduler/pipeline.py 曾把 dedup 的 rc=1 无条件视为成功并打日志"无新数据场景"。结果:高重复率(可能是正常无新数据,也可能是抓取源/指纹库异常)被一刀切掩盖,真实异常无法上报。
修复(分离"执行成功"与"统计告警"):
scripts/run_dedup.py:- 生产模式(默认):重复率仅作 WARNING 告警,不影响退出码(执行成功即 0);阈值常量
_DUP_RATE_THRESHOLD = 0.05 - 新增
--strict验收模式:保留 M3 验收门槛,重复率 > 5% 时返回 1(供人工验收) - 新增统计快照
data/deduped/{date}/stats.json(原子写):unique/duplicates/total/dup_rate/layers/fingerprint_total/generated_at,供运维排查与监控 - 顺带修复:空日场景
sources.json写入前补mkdir(原会 FileNotFoundError)
- 生产模式(默认):重复率仅作 WARNING 告警,不影响退出码(执行成功即 0);阈值常量
scheduler/pipeline.py:移除deduprc=1 特判,恢复"非 0 即失败"的统一语义
测试:
- 新增
tests/test_run_dedup.py7 个(生产模式高重复返回 0 / --strict 高重复返回 1 / --strict 低重复返回 0 / 空日返回 0 / stats.json 结构与数值 / pipeline 不再掩蔽失败) - 全量 266 passed,3 个 crawler 基线失败与本次无关
生产实测:同日重跑重复率 100% → 生产模式 rc=0 + WARNING + stats.json 完整;--strict 同场景 rc=1(用非管道方式核实退出码)
待办/遗留:
- P1-2(守护进程补跑 steps 含 cninfo 三步)、P1-3(调度时区与 date.today() 一致性),待用户决策
本次完成 (2026-08-22) — P0-3/P0-4 补跑日期语义修复
P0-3(crawler 补跑历史日期静默空转):
- 原因:
crawler/storage.py落盘硬编码date.today()(engine 不传 day),pipeline --once --date {历史}时下游读历史目录为空,且run_extractor对空目录返回成功 → 全链路静默空转 - 修复:
run_step()开头加补跑保护——date_str != 今天时跳过 crawler(首页只含当天内容,历史文章已滚走,补抓不可能),WARNING 日志 +tail_msg说明,返回 success(补跑复用已有 raw 数据是正确行为);xwlb 不跳过(API 支持任意历史日期)
P0-4(report 硬编码 date.today() 忽略传入日期):
- 原因:
run_step("report")未使用入参date_str,取当前时间;补跑历史日期+--report 会生成今天的空日报并覆盖当天已有日报(唯一键 file_name='') - 修复:一行改动
report_date = date_str;reporter.generate_report(day_str)本身已支持任意日期,无需其它改动
测试:
- 新增 4 个(补跑跳过不执行子进程/当天正常执行/report 收到传入日期/全链路仅 crawler 跳过),并入
tests/test_incremental.py - 修正 3 个既有测试(
tests/test_scheduler.py)适配新行为(用当天日期测正常执行路径) - 全量 259 passed,3 个 crawler 基线失败与本次无关
待办/遗留:
P1-1(dedup rc=1 静默转成功)已修复(见上方小节);余:守护进程补跑 steps 含 cninfo_*、调度时区与 date.today() 一致性,待用户决策- 既有小问题:
tests/test_scheduler.py部分 run_pipeline 测试未传 state_path,会写真实data/pipeline/state.json(既有行为,未改)
本次完成 (2026-08-22) — xwlb 日期错位修复(方案 A)
背景问题:
- P0-1:
run_xwlb硬编码抓前一天并落盘到「数据日」目录,而下游 extractor 按「处理日」扫目录 → 60 天联播数据从未进入知识库(实测:data/processed/xwlb/仅 20260622 一天) - P0-2:
run_xwlb用open("a")裸追加,同一天被多次调度触发导致 index.jsonl 重复行(实测 20260821: 70 行仅 24 唯一)
业务约束(保持不变): 当天日报需要前一天晚上(19:00 播出)的新闻联播内容。
方案 A 实施:
scripts/run_xwlb.py重构:- 新增
--date参数(处理日,默认今天),与管道其它步骤日期语义一致 - 内部
数据日 = 处理日 - 1(业务约束:抓前一晚已播出的联播) - 落盘目录改为处理日
data/raw/xwlb/{处理日}/→ extractor/dedup/llm/embedding/qdrant 零改动即可处理 - 幂等落盘: 落盘前读已有 index.jsonl 构建
url_hash集合,已存在条目跳过;index.jsonl 重写为去重完整集(原子写),不再裸追加
- 新增
scheduler/pipeline.py: xwlb 步骤命令加--date {date}scripts/run_extractor.py: xwlb 假 HTML 无时间节点 → 新增_fill_xwlb_publish_time,从 url(xwlb://YYYY-MM-DD/sid)兜底解析真实播出日填充publish_time(否则检索时间过滤/排序失效)- 历史死数据 A1 清理: 删除
data/raw/xwlb/62 个旧目录(20260622~20260822)+data/processed/xwlb/(仅 20260622)
验证(生产端到端,20260822):
- 新增
tests/test_run_xwlb.py9 个测试(处理日目录、幂等、空数据、坏日期),全部通过 - 全量测试 255 passed(3 个 crawler 基线失败与本次无关)
- 实跑: 处理日=20260822 抓数据日 20260821 联播 23 条 → 二次运行新增 0/跳过 23(幂等)→ M2 提取 23/23 → M3 唯一 23 → M4 LLM 23/23 → M5 23/23 → M6 Qdrant 净增 23
- 检索验证:
a-share search "国务院常务会议"top2 命中 xwlb《李强主持召开国务院常务会议》,时间 2026-08-21(真实播出日)✓ - 日报路径不受影响(仍走
reporter._collect_xwlbAPI 直读)
运维规则新增: 每次代码升级完成后必须执行 sudo systemctl restart a-share-research.service
待办/遗留:
P0-3(crawler 无 --date,补跑历史日期静默空转)、P0-4(report 硬编码 date.today())已修复(见上方小节)- P1(dedup rc=1 静默/补跑含 cninfo/时区)未修,待用户决策
run_extractor --force重提取会重复追加data/processed/{src}/{date}/index.jsonl(仅影响该辅助索引,下游读 *.json 不受影响),暂不修- 历史 60 天联播未入库(按用户决策 A1 清理,不回补)
本次完成 (2026-08-22) — 文档清理与重构
目标: 清理历史上多个 AI agent 文档残留,重构项目文档为 4 个核心文件。
删除的过时/残留文件 (4 个):
project_plan.md(700 行) — 9 个 Milestone 全部完成,计划文档已无价值docs/agent_prompt.md(80 行) — Cherry Studio Agent 使用说明,非本项目核心文档docs/optimization_plan.md(144 行) — 8 项优化中 5 项已完成,剩余不再跟踪docs/report_db_design.md(330 行) — M10 中间设计稿,逻辑已下沉到代码
新建/重写的文档 (5 个):
| 文件 | 行数 | 说明 |
|---|---|---|
docs/architecture.md |
~500 | 项目架构:11 包职责与导出 API、核心数据模型、配置体系、产物目录 |
docs/user-guide.md |
~500 | 用户手册:15 个 CLI 子命令全量 + 增量/断点续跑 + MCP + systemd + FAQ |
README.md |
~120 | 精简为项目入口:简介 + 文档索引 + 命令速查 |
docs/db-schema.md |
保留 | 日报表结构(API/前端对接,无需改动) |
deploy/README.md |
删除 | 已在服务器上直接修改,无需部署文档 |
docs/ 最终目录:
docs/
├── architecture.md # 项目架构(新增)
├── user-guide.md # 用户手册(重写)
└── db-schema.md # 日报表结构(保留)
验证:
- 所有文档中文撰写,Markdown 格式,层次清晰
- architecture.md 准确反映 11 个包的实际公开 API(基于源码
__init__.py导出) - user-guide.md 覆盖全部 15 个 CLI 子命令(crawl/extract/dedup/events/embed/ingest/pipeline/search/status/report/report-import/cninfo/stock-report/watchlist/discover/add-entry)
- 无过时信息残留(不再提 M9 Agent/HTML 日报/旧版 Mac 部署等)
待办:
- git 提交本次改动(包括 2026-08-12 增量处理改动,仍未提交)
- 同步 pi5(代码 + 文档),重启 a-share-research
当前状态
| 项目 | 值 |
|---|---|
| 新闻源 | 14 个(13 Web + 1 API: xwlb 新闻联播) |
| Qdrant | 本地文件模式 data/qdrant_storage/ |
| 日报 | M10 完成并已部署 pi5: 结构化入库 MySQL;日报按当天日期生成(新闻 30h 回溯 / xwlb 取前一日 / 公告调研近 15 日) |
| DB 连接 | pi 上 systemd 服务 a-share-db-tunnel 常驻(0.0.0.0:13306 → doorcome.cn:3306);pi5 直连 192.168.1.10:13306 |
| 调度器 | APScheduler,systemd a-share-research.service(pi5);每天 07:00 首次任务生成日报(12/18/22 点不生成) |
| LLM | 场景化配置 configs/llm_models.yaml(4 场景: event_extraction/daily_report/stock_report/embedding);YAML 优先、.env 兜底;模型必须显式配置,无内置兜底 |
| 去重 | 多源记录:指纹库 source_ids 列 + uniques JSON sources 字段 + data/deduped/{day}/sources.json |
| 增量/断点 | M2/M4/M5 产物存在即跳过(--force 全量);pipeline --once --resume 断点续跑(状态 data/pipeline/state.json) |
| 服务器 | pi@192.168.1.160(生产)/ pi@192.168.1.10(DB 隧道宿主) |
| 抓取方式 | js_render=false → httpx 直连;js_render=true → Playwright |
本次完成 (2026-08-12) — 增量处理与 pipeline 断点续跑
目标: ① 全链路中断后可从断点恢复;② 各子任务排除已处理文件,避免全量重跑与重复 API 计费。
1. 各步骤增量处理(产物存在即跳过,--force 全量):
- M2
run_extractor.py:输出目录已有{url_hash}.json即跳过提取,仅回补 index 行;--force重建;成功率统计含跳过项(修复全跳过时误报 rc=1) - M4
run_event_extraction.py:data/events/{day}/{url_hash}.json已存在即跳过(不重复调用 LLM API);--force全量;failed.jsonl 只保留本次失败、index 累积追加 - M5
run_embedding.py:data/embeddings/{day}/{url_hash}.json已存在即跳过(不重复调用 embed API);--force全量 - M1(seen_urls 增量)/ M3(指纹库判重)/ M6(upsert 幂等)为既有能力,README 汇总成表
2. pipeline 断点续跑(scheduler/pipeline.py + run_scheduler.py):
- 新增
data/pipeline/state.json(按日期隔离,记录每步骤 ok/failed + 退出码 + 耗时),原子写 run_pipeline(resume=True)跳过连续成功前缀,从首个失败/未执行步骤继续执行到结尾pipeline --once --resume(默认全量不变;--resume与--steps互斥报错);定时守护模式不受影响
验证(Mac 本地,20260616 数据 100 篇):
- pytest 225 passed(新增 tests/test_incremental.py 10 个:M2/M4/M5 跳过、状态记录、resume 续跑、resume 全完成 noop、--resume+--steps 互斥);crawler 3 个基线失败仍与本次无关
- ruff 零新增(9 个基线错误不变)
- 端到端:M2 增量重跑 140 条跳过 126 条,2.5s 完成、rc=0(修复前误报失败);state.json 正确记录 extractor ok
效果评估(100 篇规模中断重跑场景):
- M4 减少约 100 次 LLM API 调用、M5 减少约 100 次 embedding API 调用 → 中断恢复不再重复计费,耗时从分钟级降至秒级
- M2 重跑从全量 GNE 提取(分钟级)降至约 2.5s
- 断点恢复操作:中断后直接重跑同一条
pipeline --once --resume命令即可
待办:
- 同步 pi5(代码 + 文档),重启
a-share-research;首次同步后 pi5 的data/pipeline/state.json不存在 → resume 按全量处理,行为安全 - git 提交(本次改动尚未提交)
本次完成 (2026-08-05) — 日报可靠性修复与取数逻辑优化
目标: 解决日报 AI 摘要偶发失败;修正日报日期与 xwlb/新闻取数语义。
1. AI 摘要可靠性(llm/client.py + scheduler/reporter.py):
- 去掉内置默认模型兜底(
deepseek-chat/qwen-plus),模型必须显式配置(DEEPSEEK_MODEL/QWEN_MODEL→LLM_MODEL),缺失即报错,避免静默用错模型 _llm_call增加指数退避重试:_LLM_RETRY_TIMES(默认 3 次)、_LLM_RETRY_BACKOFF_SEC(默认 2.0s,可 .env 覆盖),全部失败才抛异常- 确认 AI 摘要模型:
deepseek+deepseek-v4-flash(生产实测)
2. 日报取数逻辑(scheduler/pipeline.py + reporter.py):
- pipeline report 步骤:
report_date = date.today()(原为昨天+回溯 3 天) _collect_news_events:读当天+前一天事件目录,按publish_time过滤最近 30 小时(_NEWS_LOOKBACK_HOURS=30);时区统一(naive 假定本地时区);无时间戳事件保留_collect_xwlb:固定查day_str前一日(《新闻联播》19:00 播出,早间日报只能取昨晚已播出的一期);source_date同步为实际来源日- 公告/调研/互动保持原设置:近 15 日(
STOCK_REPORT_DAYS=15),irm 互动仍跳过——未受 30h 改动影响
验证(pi5):
- 单测 9 个(30h 回溯/带时区时间戳/重试/模型缺失报错/xwlb 前一日)全部通过;全量 212 passed + 3 crawler 预存在失败
- 生产端到端 report_id=191(2026-08-05):news 20 + cninfo 20 + xwlb 34(08-04 联播),AI 摘要 2076 字
- 生产服务已重启生效
本次代码尚未 git 提交(见待办)。
本次完成 (2026-08-03 22:00) — pi5 部署与生产测试
操作: M10 代码全量同步 pi5 + 生产环境验收(所有测试在 pi5 执行,Mac 不再作为测试环境)。
文件同步: rsync 本地 → pi5:/home/pi/news/(排除 .venv/data/logs/.git/.env/configs/*.yaml);清除 pi5 根目录 6 月 17 日旧版散文件(已 tar 备份 /tmp/news_backup_20260803.tar.gz);pi5 uv sync 装 pymysql。
DB 隧道修复: pi 原 autossh 参数 -L 13306:0.0.0.0:3306 未生效(0.0.0.0 被当远端目标),改为 -L 0.0.0.0:13306:127.0.0.1:3306 并持久化为 systemd 服务 a-share-db-tunnel(enabled + active)。
测试结果(pi5):
- 全量 pytest:208 passed, 3 failed(3 个失败均为 crawler retry mock 预先存在问题,与 M10 无关)
report-import幂等:已存在文件正确 skipped- 生产端到端:
a-share report --date 20260802/20260803→ report_id=181/182 入库成功(AI 摘要正常,57/58 事件) - DB 总量:finance 52 + intl 128 = 180 行(历史 177 + 端到端测试 2 + 本机 1)
- 生产服务
a-share-research已重启 active,22:00 定时任务起用新代码
已知问题:
tests/test_crawler.py3 个 retry 测试失败(预先存在,crawl4ai mock 行为)- Mac 本机 anaconda/uv python 出站到 192.168.1.10 被拦截(EHOSTUNREACH;nc/bash/系统 python 正常)——仅影响本机,pi5 不受影响;Mac 本地用
127.0.0.1+ ssh 隧道绕过 - 生产 pi5 的
.env里NEWS_DB_HOST=192.168.1.10(直连);Mac 本地.env为127.0.0.1(隧道)——两处 .env 不同,勿互相覆盖
本次完成 (2026-08-03) — M10 日报结构化入库
目标: 日报前后端分离的数据层——日报内容结构化存入 MySQL(news_ 前缀表),历史 178 份日报 HTML 解析入库;本项目不做 API/前端(用户另行实现)。
表结构(myquant 库,见 docs/db_schema.md):
news_report:主表,唯一键 (report_date, report_type, file_name);file_name=''表示新生成日报(每天每类型一行,重复生成覆盖)news_event:事件明细,section ∈ xwlb/news/cninfo/intl
新增/修改文件:
report_db/(models/schema/db):连接、建表、幂等 save_reportreport_import/(parser/importer):历史 HTML 解析(表头驱动列映射)+ 批量导入scheduler/reporter.py:generate_report()完全切换为结构化入库;_render_html/_upload标记废弃保留a_share_cli/main.py:新增report-import子命令;report命令改为入库提示pyproject.toml:uv add pymysql(唯一新增依赖).env:新增NEWS_DB_*(连接 127.0.0.1:13306,需 ssh 隧道)、REPORT_HISTORY_DIRdocs/report_db_design.md(实现逻辑)、docs/db_schema.md(表结构,供 API/前端)
验证结果:
- 历史 178 份全部入库:scanned=178 imported=7(首轮)+170 skipped=171 failed=0;DB 177 行(finance 49 + intl 128,1 个跨目录同名文件被幂等合并)+ 事件 4222 条
- 端到端:
a-share report --date 20260616→ report_id=180 入库成功,无 HTML 产出 - 单测 24 个通过(parser 19 + builder 4 + models/import 补充)
命令:
ssh -L 13306:127.0.0.1:13306 pi # Mac 开发连库隧道
uv run a-share report --date YYYYMMDD # 生成日报入库
uv run a-share report-import # 历史导入(幂等)
注意: 本机 .env 无 LLM API key,AI 摘要会降级 WARNING(不影响入库);生产 pi5 需配置 NEWS_DB_PASSWORD 且解决 13306 隧道可达性(见待确认项)。
历史 (2026-07-17) — 禁用个股日报
操作: STOCK_REPORT_TIME= 设为空,run_scheduler.py 加空值守卫。
文件:
scripts/run_scheduler.pyL127-141:STOCK_REPORT_TIME为空时跳过注册并输出已禁用个股日报- Pi
.env:STOCK_REPORT_TIME=08:00→STOCK_REPORT_TIME=
恢复方法: 改回 STOCK_REPORT_TIME=08:00,重启 a-share-research。
本次完成 (2026-07-13) — eeo 反爬修复 + 静态直连 + 超时保护
问题
eeo(经济观察网)在 Pi 上用 Playwright 连续抓取后触发反爬,服务器故意不响应导致 page.goto() 超时(30s → 60s 均超时)。而在本机 Mac 上一切正常——反爬是 IP 级别的,Pi 的 IP 已被限流。
根因
eeo 是纯静态页面(js_render: false),但 Crawl4AI 始终走 Playwright。eeo 检测到 headless Chrome 的连续请求模式后,对后续请求挂起 TCP 连接直至超时。
修复
crawler/engine.py — 三个改动:
-
新增
_fetch_static():js_render=False且无wait_for的源用httpx直连,绕过 Playwright 反爬。HTML → Markdown 用markdownify+ BeautifulSoup 清洗。 -
新增
_TimeoutGuard:同源连续超时 2 次后自动跳过剩余请求,防止整个 pipeline 被单一故障源拖死。 -
_crawl_once分流逻辑:js_render=False 且无 wait_for → _fetch_static() (httpx) 其他 → Playwright
configs/sources.yaml — eeo 源两处调整:
- 删除
wait_for: "css:body"(静态页面无需等待 CSS 选择器) page_timeout_ms: 30000 → 60000(恢复 Crawl4AI 默认值)
测试结果
| 环境 | Playwright (修复前) | httpx (修复后) |
|---|---|---|
| Mac 本地 | 全部通过 | 36 篇 / 7 秒 |
| Pi 服务器 | 前 3 个请求全部 15s 超时 | 36 篇 / 9 秒,0 失败 |
验证方法
Pi 上本地复现了反爬(Playwright 前 3 个 URL 全部超时),同批 URL 用 httpx 全部瞬间返回——证明方案有效。
历史 (2026-06-24)
1. 环境变量全面审计与修复
触发: 服务器 dedup 步骤超时 120s。
修复 6 个文件:
| # | 文件 | 修改 |
|---|---|---|
| 1 | scheduler/pipeline.py |
超时解析重写:TIMEOUT_{NAME} > PIPELINE_STEP_TIMEOUT > 硬编码 > 1800s |
| 2 | a_share_cli/main.py |
新增 _resolve_timeout(),CLI 命令超时改为读环境变量 |
| 3 | crawler/cninfo.py |
CNINFO_PDF_BASE 从硬编码改为 os.environ.get() |
| 4 | scheduler/reporter.py |
STOCK_REPORT_DAYS 默认值 7→15;max_tokens 600→1500 |
| 5 | .env |
清除 10 个死配置;EMBEDDING_MODEL→LOCAL_EMBEDDING_MODEL;补全遗漏参数 |
| 6 | .env.example |
重写为仅包含实际生效配置 |
审计结果:
| 类别 | 数量 | 处理 |
|---|---|---|
| ✅ 正常工作 | 23 | — |
| ❌ 死配置 | 10 | 已清除 |
| ⚠️ 默认值不一致 | 1 | 已统一 |
| 🔧 硬编码 | 1 | 已修复 |
2. AI 摘要截断修复
触发: 日报 AI 摘要内容极少(137 字),末尾被截断。
根因: _llm_call() max_tokens=600 太低,deepseek-v4-flash 输出被硬截断。
修复: max_tokens 三处提升 + 截断检测日志。
| 位置 | 修复前 | 修复后 |
|---|---|---|
_llm_call() 默认 |
600 | 1500 |
| 分块摘要 | 400 | 800 |
| 合并摘要 | 600 | 1500 |
验证: 手动生成日报,摘要从 137 字 → 486 字,结构完整无截断。
超时优先级(最终设计)
TIMEOUT_{NAME} 环境变量 ← 单步精确控制
↓ 未设
PIPELINE_STEP_TIMEOUT 环境变量 ← 全局兜底 (覆盖所有硬编码)
↓ 未设
STEP_TIMEOUTS 硬编码字典 ← 代码内默认值
↓ 步骤不在字典中
1800s ← 最终兜底
服务器 .env 当前配置
# ---- 调度 ----
SCHEDULE_TIMES=07:00,12:00,18:00,22:00
CNINFO_SCHEDULE_TIME=06:00
STOCK_REPORT_TIME=08:00
STOCK_REPORT_DAYS=15
# ---- Pipeline 超时 ----
PIPELINE_STEP_TIMEOUT=3600
TIMEOUT_CRAWLER=900
TIMEOUT_XWLB=60
TIMEOUT_EXTRACTOR=300
TIMEOUT_DEDUP=900
TIMEOUT_LLM=900
TIMEOUT_EMBEDDING=900
TIMEOUT_QDRANT=1800
TIMEOUT_CNINFO_CRAWL=900
TIMEOUT_CNINFO_EXTRACT=900
TIMEOUT_CNINFO_PDF=900
调度器
| 时间 | 步骤 |
|---|---|
| 06:00 | cninfo 公告管道 |
| 07:00 | crawler→xwlb→extractor→dedup→llm→embedding→qdrant→日报 |
| 08:00 | 个股日报 |
| 12:00 | crawler→xwlb→extractor→dedup→llm→embedding→qdrant |
| 18:00 | crawler→xwlb→extractor→dedup→llm→embedding→qdrant |
| 22:00 | crawler→xwlb→extractor→dedup→llm→embedding→qdrant |
常用命令
# 全链路 + 日报
uv run a-share pipeline --once --report
# 仅日报 (指定日期)
/home/pi/.local/bin/uv run python -m scripts.run_scheduler --once --date 20260623 --steps report
# 检索
uv run a-share search "关键词" --top 5
# 同步到服务器
scp <file> pi@192.168.1.160:/home/pi/news/<path>/
# 重启服务
ssh pi@192.168.1.160 "sudo systemctl restart a-share-research"
已知技术债务
| 问题 | 文件 | 状态 |
|---|---|---|
| QdrantClient HTTP 超时硬编码 10s | vectorstore/client.py:93 |
无可配环境变量 |
| DashScope HTTP 超时硬编码 60s | embedding/remote.py:81 |
无可配环境变量 |
| 超时解析逻辑在 pipeline.py 和 main.py 各一份 | 两处 | 可抽取公共函数 |
deepseek-v4-flash 概率性返回空 |
— | 分块处理 + 失败跳过 |
| wallstreetcn JS 渲染拦截 | — | 正文提取率 0% |
| eeo 列表页仍走 Playwright(仅文章页走 httpx) | crawler/engine.py |
列表页目前正常,暂不改动 |
架构备忘:静态/动态抓取分流
SourceConfig.js_render == False 且 wait_for == None
→ _fetch_static() → httpx 直连 (无浏览器, 快, 不被反爬)
→ markdownify + BeautifulSoup (清洗 script/style 后转 Markdown)
SourceConfig.js_render == True 或 wait_for 有值
→ _crawl_once() → Playwright (现有逻辑)
_TimeoutGuard:
- 同源连续超时 2 次 →
skip=True - 后续请求在
semaphore内检查guard.skip,立即返回Skipped - 一次成功即重置计数器
记忆
never-change-llm-model.md— 绝不允许修改大模型配置deploy-html.md— user_guide.html 同步到 Pi 和 Web 服务器sync-sources-yaml.md— 修改 sources.yaml 前从 Pi 拉取,改完推回update-user-guide.md— 更新 md+html+部署