Skip to content

[任务] 读列表:通用抓取、配置和往回翻页 #6

Closed

Description

@JunieXD

关联与状态

路线图 #2,一期。状态:已完成,@Xi1495:PR #83 已合并。有问题直接在这里留言。

这个 Issue 原来是「抓取节点原型:从列表页抓到快照」。抓取节点的骨架已经搭好,原来的范围拆成了几个任务:读列表(这里)、读正文和附件 #40、浏览器抓取 #41、图片的文字识别 #47。

目标

鼠钟要从各学院官网的「通知公告」页里找出保研通知。这个任务写一轮里的第一步 Steps.list_items:从来源的列表页取出每条通知的标题、链接和日期。第一次抓时往回翻页,补上前两年的通知;结构特殊的网站按配置取(总体设计 §7.1、§7.2)。

已经有的

  • 项目骨架:crawler/ 是 Python 3.14 + uv 的项目,装依赖 uv sync,跑全部检查 ./check.sh(格式、lint、Pyright 严格模式、测试)。命令见 AGENTS.md。
  • 一轮的流程:crawl/rounds.py 的 crawl_source 已经把一个来源的一轮串好:读列表 → 初筛 → 读正文和附件 → 抽取 → 交结果。四步作为 Steps 传进来,签名和交接的数据写在那里,测试的写法见 rounds_test.py。抓不成时抛 FetchError 或 StepError,流程会把原因记进抓取记录(开发约定 §2)。
  • 请求层:所有对来源网站的请求都经过 crawl/fetch.py 的 Fetcher,它管 UA、同一网站一次一个请求和间隔,不要自己用 httpx 发请求。
  • 和网站交接的类型:crawl/contract.py 由网站的接口定义生成,不手改(接口 §6)。
  • 选定的库:用 lxml 按 CSS 或 XPath 取(总体设计 §5.1)。

范围

要做(可以一项一项做,每项一个 PR):

  1. 通用抓取:
    • 不用配置,从规整的列表页取出每条通知的标题、绝对网址和日期(YYYY-MM-DD),返回 ListedItem 的列表;
    • 先拿厦大信息学院的招生信息练手,再多试几个 [任务] 第一批来源清单 #5 里的来源;
    • 按建站系统总结常见的写法,一种写法能管一批网站。
  2. 往回翻页:WorkSource.backfill 为真时,顺着「下一页」往回翻,翻到两年前的通知或者没有下一页为止;平时只读第一页。
  3. 配置:
    • 通用抓取取不对的来源,用几行配置指明列表、标题、链接、日期和翻页在哪;
    • 配置的格式由这个任务定:写进开发约定 §2,用 Pydantic 校验,就是 WorkSource.config 的内容;
    • 管理员在网站上填([任务] 管理院校清单和来源 #37),试抓时 LLM 也按它生成([任务] 试抓:抓取节点这边 #46);
    • 网站只把它当 JSON 存,不认得格式。配置不合法时(填错了,或者格式后来改了)抛 StepError("error", "配置不对:…"),记进抓取记录,管理员在抓取看板上看得到;不要让校验的异常直接抛出去,那样这一轮不交记录,租约过期后反复重来。
  4. 只能用 HTTP 的:浙大计算机学院的 HTTPS 连不上,在配置里能指定用 HTTP 抓。
  5. 失败:列表页返回 4xx、5xx 时抛 StepError("http_status", "HTTP 403") 这样的错误,读不到条目就返回空列表,一轮的流程会记成 no_items。

不做:浏览器抓取(#41)、正文和附件(#40)、初筛和抽取。

需要知道的

  • 测试不连外网,用保存下来的列表页。仓库里只放页面结构,通知的标题可以换成自己编的。
  • 手动试抓真实网站只抓需要的几页(AGENTS.md · 底线)。

建议的第一步

  1. 在本 Issue 留言认领。
  2. 把厦大的列表页存一份到测试数据目录,在 crawler/src/crawler/parse/ 下写通用抓取和它的测试,跑通 ./check.sh,开一个 Draft PR。

验收标准

  • 至少 5 个不同建站系统的来源能用通用抓取或配置取对标题、链接和日期
  • 第一次抓能往回翻到两年前,平时只读第一页
  • 配置的格式写进开发约定,有校验,不合法的记进抓取记录;只能用 HTTP 的来源能抓
  • 测试只用保存下来的页面,./check.sh 通过

Activity

  1. added
    enhancementNew feature or request
    task可以认领的具体工作
    crawler抓取节点:抓取、初筛、抽取
    and removed
    enhancementNew feature or request
    on Oct 27, 2026
  2. JunieXD commented on Oct 27, 2026

    @JunieXD
    ContributorAuthor

    (已更新)这里的建议已经写进 Issue 正文:原型直接写在 crawler/ 里,按正式代码合入;电科计算机学院改用浏览器抓取,设置见开发约定 §2。正文和附件用哪些库,在这个任务里比较后写回总体设计 §5.1。

  3. changed the title [-][任务] 抓取节点原型[/-] [+][任务] 抓取节点原型:从列表页抓到快照[/+] on Oct 27, 2026
  4. changed the title [-][任务] 抓取节点原型:从列表页抓到快照[/-] [+][任务] 读列表:通用抓取、配置和往回翻页[/+] on Oct 27, 2026
  5. Xi1495 commented on Nov 6, 2026

    @Xi1495
    Contributor

    我来认领 #6,接着已有来源清单做 Steps.list_items。先从厦大信息学院招生列表开始,按不同建站系统的结构准备固定测试页面,再完成首次两年回补和配置抓取。

    配置拟使用 XPath,分别定位条目、标题、链接、日期和下一页;另提供显式 HTTP 选项,写进开发约定 §2,用 Pydantic 校验,非法配置转换为 StepError。本任务只做列表,不混入正文、浏览器、初筛或抽取。

    依赖使用 Issue 已选定的 lxml,另加开发依赖 types-lxml 供严格类型检查,均通过 uv add 管理。所有源站请求继续通过共用的原版 Fetcher;测试只用保留页面结构、替换通知内容的本地样例。会先开 Draft PR,按 Issue 验收项逐条列出证据,配置格式如需调整可在 PR 中继续对齐。

  6. JunieXD commented on Nov 6, 2026

    @JunieXD
    ContributorAuthor

    感谢认领,已经指派给你!方案和 Issue 对得上:lxml 按 XPath 取,配置用 Pydantic 校验、不合法时转成 StepError,只能用 HTTP 的来源(范围第 4 项)在配置里指定。

    提醒一点:先做范围第 1 项不用配置的通用抓取,按建站系统总结写法,一种写法管一批网站;配置只留给通用抓取取不对的来源。验收要求的 5 个建站系统,能用通用抓取取对的就不写配置。

    #80、#81、#82 我们正在审,意见会分别发在各自的 PR 里。

  7. Xi1495 commented on Nov 7, 2026

    @Xi1495
    Contributor

    #83 已按两轮审查意见修改,最新提交为 a7aa799,现为待审。

    • 通用列表按重复结构识别,日期从整行及日期元素取得,不按通知网址片段或建站系统 class 选模板;读页面与回补放在 crawl,parse 只解析一页,时间用可注入的 clock。
    • 本轮修复标题损坏:把发布日期的位置交给标题提取,只删对应的发布日期及紧邻的一对括号,保留标题原有括号和活动日期,补上链接内分栏日期、嵌套活动日期和直接由链接组成列表的回归测试。
    • 空历史页及指回已读页的分页链接均结束回补并返回已取条目;HTTP、网络失败仍报错。页面解析错误直接显示原错误,不再一律标为配置错误。
    • 配置 link、next 选中元素时取 href,配置文档已简化,XPath 返回类型用 isinstance 判断。

    验证:格式、lint、严格类型、生成类型检查及 170 项离线测试通过,远端 crawler、web CI 通过。复用此前按 Fetcher 规矩取得的 30 个非浏览器来源首页,离线复算仍为 390 条、390 条都有日期,修正 40 个标题,未新增源站请求;逐来源条数仍列在 PR 描述中。需浏览器的 15 个来源继续归 #41,#77 的 PageSession 改动按审查说明由该 PR 衔接。

    请复审 #83;本 Issue 等维护者验收后关闭。

  8. JunieXD commented on Nov 7, 2026

    @JunieXD
    ContributorAuthor

    PR #83 已合并,验收标准逐条做到了,这个 Issue 随之关闭。感谢 Xi1495!

    • 通用抓取和配置:博达(VSB)、WebPlus、TRS、Drupal、GPower 等建站系统的页面都保存成了测试数据。合并前我们用这一版把 30 个普通来源的首页各读了一次,390 条都取到了标题、链接和日期,括号和标题里本来的日期都保留着。
    • 往回翻页:第一次抓顺着下一页翻到两年前为止,平时只读第一页;翻页链接指回读过的页时停下,交已经取到的。
    • 配置:格式写在开发约定 §2.1,用 Pydantic 校验,不合法的记进抓取记录;只能用 HTTP 的来源用 force_http。
    • 测试:只用保存下来的页面,./check.sh 通过。

    要执行脚本才能打开的 15 个来源(北邮 8 个、电科 7 个)归浏览器抓取 #41。下一步是读正文和附件 #40,待认领。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

crawler抓取节点:抓取、初筛、抽取help wantedExtra attention is neededtask可以认领的具体工作

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions