### 关联与状态 路线图 #2,一期。状态:**进行中**,@JunieXD:Draft PR #100,入口、日志、停止和 Dockerfile 都做好了,抽取等 #96 合并后接上,再转为待审。读列表(#6)、初筛(#42)和读正文(#40)已合并。有问题直接在这里留言。 ### 目标 抓取节点要能作为一个进程长期跑:启动时读配置,每分钟向网站领一次活,把到期的来源各跑一轮,出了错记日志、不拖垮别的来源([总体设计 §16](https://github.com/mousebaoyan/mouseclock/blob/main/docs/design.md#16-部署与运维))。这个任务写入口,以及部署用的 Dockerfile。 ### 已经有的 - **项目骨架**:`crawler/` 是 Python 3.14 + uv 的项目,装依赖 `uv sync`,跑全部检查 `./check.sh`(格式、lint、Pyright 严格模式、测试)。命令见 [AGENTS.md](https://github.com/mousebaoyan/mouseclock/blob/main/AGENTS.md#命令)。 - **一轮的流程**:[`crawl/rounds.py`](https://github.com/mousebaoyan/mouseclock/blob/main/crawler/src/crawler/crawl/rounds.py) 的 `crawl_source` 已经把一个来源的一轮串好:读列表 → 初筛 → 读正文和附件 → 抽取 → 交结果。四步作为 `Steps` 传进来,签名和交接的数据写在那里,测试的写法见 `rounds_test.py`。抓不成时抛 `FetchError` 或 `StepError`,流程会把原因记进抓取记录([开发约定 §2](https://github.com/mousebaoyan/mouseclock/blob/main/docs/development.md#2-抓取和判别))。 - **请求层**:所有对来源网站的请求都经过 [`crawl/fetch.py`](https://github.com/mousebaoyan/mouseclock/blob/main/crawler/src/crawler/crawl/fetch.py) 的 `Fetcher`,它管 UA、同一网站一次一个请求和间隔,不要自己用 httpx 发请求。 - **和网站交接的类型**:[`crawl/contract.py`](https://github.com/mousebaoyan/mouseclock/blob/main/crawler/src/crawler/crawl/contract.py) 由网站的接口定义生成,不手改([接口 §6](https://github.com/mousebaoyan/mouseclock/blob/main/docs/api.md#6-抓取节点))。 - **网站接口的客户端**:[`crawl/website.py`](https://github.com/mousebaoyan/mouseclock/blob/main/crawler/src/crawler/crawl/website.py),`work()` 领活。 - **本地联调**:网站那边 `pnpm dev` 起网站、`pnpm seed` 填示例数据、`pnpm crawler-token <名字>` 生成令牌。 ### 范围 1. **配置**:环境变量 `MOUSECLOCK_URL`(网站地址)和 `MOUSECLOCK_TOKEN`(抓取节点令牌),启动时用 Pydantic 校验,缺了就报错退出。模型的 key 由 #42、#44 加。AGENTS.md「写代码」里的「配置」一条现在只列了网站的环境变量,把这两个加进去。 2. **日志**: - 每行一个 JSON,和网站一样; - 一轮的日志都带来源编号和开始时间,能对上抓取看板([开发约定 §4](https://github.com/mousebaoyan/mouseclock/blob/main/docs/development.md#4-日志));§4 写的是「抓取记录的编号」,但这个编号要等交了这一轮才有,`crawl_runs` 里来源编号加开始时间是唯一的,在这个任务里把 §4 一起改过来; - 不写正文、模型的输入输出和任何密钥。 3. **循环**: - 每分钟领一次活,到期的来源并发地各跑一轮,同一个网站的规矩由共用的 `Fetcher` 保证; - 一个来源出了意外的异常,记日志,别的照常; - 试抓交给 #46; - 收到 SIGTERM 时,等手上的这一轮做完再退出。 4. **运行**: - `pyproject.toml` 里加入口命令,比如 `uv run crawler`; - 写 Dockerfile,镜像尽量小,用浏览器抓取时要装 Chromium 的无头精简版(#41); - AGENTS.md 的命令表里加上怎么在本地对着 `pnpm dev` 跑。 5. **接上四步**:在入口里用 #6、#40、#42、#44 的实现拼出 `Steps`。 部署到服务器由维护者做,不在范围里。 ### 建议的第一步 1. 在本 Issue 留言认领。 2. 先写配置和日志,再写循环,用假的四步对着本地的网站跑一轮,开一个 Draft PR。 ### 验收标准 - [ ] `uv run crawler` 能对着本地的网站一直跑,到期的来源各跑一轮,结果出现在抓取看板上 - [ ] 一个来源出错不影响别的;日志是 JSON,带来源编号,没有密钥和正文 - [ ] Dockerfile 能构建,`./check.sh` 通过
Activity