Skip to content

加上抓取节点的入口和镜像 - #100

Merged
JunieXD merged 5 commits into
mainfrom
crawler-entry
Nov 10, 2026
Merged

JunieXD merged 5 commits into
mainfrom
crawler-entry

Conversation

@JunieXD

@JunieXD JunieXD commented Nov 9, 2026 •

Copy link
Copy Markdown
Contributor

关联

Closes #45。Closes #42:初筛的 key 在入口启动时校验,是 #42 剩下的最后一项。

改了什么

抓取、读正文、初筛和抽取各步都有了,还差一个能常驻运行的进程把它们串起来,部署时也要一个镜像。

  • uv run crawler 启动:启动时用 Pydantic 校验 MOUSECLOCK_URL、MOUSECLOCK_TOKEN、SYSTEM_ONE_API_KEY、LLM_API_KEY,缺了或不对就报出是哪几个、不带值,然后退出
  • 每分钟领一次活,领到的来源同时各抓一轮;一轮里出意外异常只记日志,不影响其他来源,租约过期后网站会再发
  • 领活时网站连不上、或者返回的数据对不上契约(网站先升级、抓取节点还没升级时),只记错误类别和状态码,下一分钟再领,进行中的几轮照常做完;异常原文可能带着令牌,不写进日志
  • 收到 SIGTERM 不再领活,等进行中的几轮做完再退出
  • 日志每行一个 JSON 对象,一轮的日志都带 source_id 和 started_at,和抓取看板上的那一轮对得上;普通请求和浏览器下载附件也各记一条网址、状态码和耗时(原来只有浏览器打开页面时记),httpx 自己的逐条日志关掉;初筛每批、抽取每次调用各记一条模型、用量和耗时,抽取在检查输出前就记,答错的那次也有记录
  • 几十个来源同时抓时,初筛和抽取同时在调用的请求各自整个进程共用一个上限(2 个),不会一下子发出上百个请求被限流
  • 初筛不成时这一轮照样往下走:新通知记进没抓成的通知,下一轮再初筛,进行中项目的通知照常抓;原来会直接中断这一轮,也不交抓取记录
  • 抽取失败的原因写成「抽取失败: unknown_college」这样,带上具体的错误码,和初筛的「初筛失败: http_503」一致
  • crawler/Dockerfile 按 uv 推荐的两段构建,带 Chromium 无头精简版,用普通用户运行;运行时要加 --init,停止的等待时间要够进行中的几轮做完
  • AGENTS.md 写上抓取节点的环境变量和本地运行的命令;开发约定更新目录、日志的写法和模型调用的并发上限;接口文档写上初筛不成的算没抓成

怎么验证的

  • ./check.sh 全部通过(242 个测试)。新加的测试:配置出错时只报变量名、不带值;一个来源出意外异常时其他来源照常交抓取记录,停止时等进行中的几轮做完,异常的日志带 source_id 和 started_at;几轮同时初筛、同时抽取时同时在调用的不超过上限(把上限改回每轮各算各的,这两个测试会失败);初筛失败时新通知记进没抓成的通知;抽取选了不存在的学院时原因写明 unknown_college;领活先后收到不合契约的数据和带着令牌的错误时,进行中的来源照常交记录、日志里没有令牌(只捕获网络错误或把异常原文写进日志,这个测试都会失败)
  • 对着本地的 pnpm dev 跑真实的入口,来源页面是本机起的假网页,初筛换成假的,抽取用正式的 Extract、只把请求接到假的模型上(临时脚本,不在仓库里):
    • 9 个到期的来源同时开抓:7 个 .example 的来源记成 unreachable,2 个本地来源(一个普通请求、一个浏览器)列出 3 条、初筛、存快照、上传并读出 docx 附件、抽取,404 的通知标成已删除
    • 两个来源在同一个网站上,请求还是一次一个、间隔 5 秒
    • 第一页抓完时发 SIGTERM,两轮继续做完、交了记录才退出,退出码 0
    • 假模型交回一个认不出的截止「端午节前一天」:网站核对原文后建了「日期待确认」的条目;以假鼠洞的管理员登录打开审核页,显示「报名截止:端午节前一天」、原文那句话和「已补充,关闭此条」「无需补充」「前往项目补充时间」
  • 镜像:docker build 成功,解压后 1.34GB(Chromium 无头精简版 276MB、它的系统库约 355MB、Python 环境 180MB)。用 --init 对着本地网站跑:普通用户 crawler 启动 Chromium、打开页面、交了抓取记录;网站连不上时每分钟记一条警告、进程不退出;docker stop 立刻以 0 退出。不设环境变量时输出一行 JSON 报出缺的变量。接上抽取后 Dockerfile 和依赖没变,没有重新构建
  • 没有用真的 System One 和 DeepSeek 跑

影响

  • 抓取节点:新的进程入口、镜像和环境变量 MOUSECLOCK_URL、MOUSECLOCK_TOKEN;领活和交结果的接口不变
  • 初筛失败的轮次:抓取看板上不再缺这一轮,而是显示「N 条通知抓取失败」,每条写明原因
  • 接口、MCP 工具、表结构:无

留给后续

  • 模型调用失败时(初筛中途失败、抽取答错),这次调用的用量交不到网站,抓取看板的用量统计里没有它。要让 POST /runs 带上失败调用的用量,网站和抓取节点都要改,记在路线图上另开 PR 做;抽取的这部分用量现在先写进日志

抓取、读正文和初筛各步都有了,还差一个能常驻运行的进程把它们串起来,部署时也要一个镜像(#45)。

- `uv run crawler` 启动:启动时用 Pydantic 校验环境变量,缺了或不对就报出是哪几个、不带值,然后退出
- 每分钟领一次活,领到的来源同时各抓一轮;一轮里出意外异常只记日志,不影响其他来源,租约过期后网站会再发
- 收到 SIGTERM 不再领活,等进行中的几轮做完再退出
- 日志每行一个 JSON 对象,一轮的日志都带来源编号和开始时间;普通请求和浏览器下载也各记一条网址、状态码和耗时,httpx 自己的逐条日志关掉
- Dockerfile 按 uv 推荐的两段构建,带 Chromium 无头精简版,用普通用户运行
- AGENTS.md 写上抓取节点的环境变量和本地运行的命令,开发约定更新目录和日志的写法
入口让几十个来源同时抓,原来每轮各自最多 2 个初筛请求,补抓往年时可能同时发出上百个,被限流后这一轮中断,也不交抓取记录,看板上看不到。

- 同时在调用的初筛请求整个进程共用一个上限
- 初筛不成时抛 StepError,这一轮照样往下走:新通知记进没抓成的通知,下一轮再初筛,进行中项目的通知照常抓
- 接口文档写上初筛不成的算没抓成,开发约定写上模型调用的并发上限整个进程共用
#96 合并后,入口里占位的抽取换成正式的 Extract,抓取节点就能从头走到尾。

- 启动时一起校验 `LLM_API_KEY`,`Extract` 和其他客户端一样用 `async with` 打开
- 同时在调用的 LLM 请求整个进程共用一个上限,和初筛一样
- 抽取失败的原因写成「抽取失败: unknown_college」这样,带上具体的错误码,抓取看板和日志里能看出模型错在哪
网站返回的数据对不上契约时,领活抛出的校验错误没被捕获,会把正在抓的其他来源一起取消;领活失败的日志写了异常原文,可能带出令牌。开发约定 §4 要求记的模型名称、用量和耗时也还没记。

- 领活遇到网络错误或不合契约的响应,都只记错误类别和状态码,下一分钟再领
- 初筛每批、抽取每次调用各记一条日志,写明模型、用量和耗时;抽取在检查输出前就记,答错的那次也有记录
@JunieXD
JunieXD marked this pull request as ready for review November 10, 2026 02:45
@JunieXD
JunieXD merged commit 3bf0118 into main Nov 10, 2026
2 checks passed
@JunieXD
JunieXD deleted the crawler-entry branch November 10, 2026 02:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[任务] 抓取节点的入口和 Dockerfile [任务] 初筛接进一轮

1 participant