parsegpt

这是一套校招/社招公告的全链路解析系统,把爬取到的原始 HTML 页面转化为结构化 JSON,供后续搜索、展示、推荐使用。整体由五个模块分工协作,有一条明确的主干流程,也有两条独立的分支路径。

image-42313e76

html_to_text — 底层 HTML 清洗

最底层的工具,被多个上层模块调用。核心逻辑是把 HTML 转成干净的纯文本,但它对 <table> 有特殊处理——不是简单地 get_text(),而是把多列单元格按行合并,尽量保留表格的语义结构(比如"岗位名称 / 工作地点 / 招聘人数"这种横向排列的信息不会丢失)。同时清理掉 CSS、JS、隐藏元素、多余空白和 &nbsp; 等噪音字符。

ann_img — 图片处理与 OCR

处理公告里嵌入的图片,流程分五层:

  1. 下载图片,计算 MD5 和感知哈希(average_hash),用于内容去重和黑名单匹配
  2. 二维码检测(detect_qr_code):识别是否是纯二维码(Y)、混合图(H)还是普通图(N
  3. 对非纯二维码图片做 PaddleOCR 文字识别,提取出文字供后续搜索全文使用
  4. 多层过滤:按尺寸、透明度、OCR 文字量、MD5 黑名单、相似哈希黑名单、学校 Banner 黑词表等条件剔除无效图片
  5. 把有效图片上传华为云 OBS,替换 HTML 里原来的 src 地址

关键设计:对混合图(既有普通内容又有二维码),会把二维码区域裁切出来单独上传,便于前端展示"扫码投递"入口。

ann_md — HTML 预处理与 Markdown 转换

流水线的第一道关卡,处理完成后才把内容交给大模型。主要做六件事:

① 清除噪音 DOMfix_html_div):按渠道配置(detail_rm_classes / detail_rm_ids)删除导航栏、页脚、广告等无关 div。还支持按出现顺序删除特定 div(用 ^ 符号标记"第 N 个")。

② 修复链接和图片路径fix_html_a / fix_html_img_src):相对路径统一补全为绝对 URL,Base64 内嵌图片先保存本地再上传 OBS 变成外链。

③ 提取硬编码的结构化字段find_hardcode_tag):有些网站的公司名、公告标题藏在固定 CSS 类里,直接选择器抓取,不依赖大模型。还支持从完整页面(.full 文件)中提取大模型视角里看不到的字段。

④ 调用 ann_img.py 完成图片的下载、OCR、二维码检测、上传替换。

⑤ HTML 转 Markdownhtml2md_table):检测表格是否有合并单元格(colspan / rowspan),没有则用专用工具转换,有则退化到 html2text 库处理。

⑥ 渠道专项修复common_process_sch_98534):针对某所合作学校(编号 98534)的 Markdown 岗位信息区块格式做正则定制处理,是写死的特殊逻辑。

ann_model — 核心调度器(主入口)

整个系统的大脑,串联所有模块,分三个阶段处理。

第一阶段:公告级解析

把 Markdown 全文用 get_template_campus 模板调用大模型,提取公司名、应聘方式、毕业年届、公告类型等字段,然后做一系列后处理:

  • 过期检测:截止日期超过 1 个月直接丢弃
  • 多公司检测:大模型判断是多家公司联合发布时,将公司名改为"校招公告",避免归属混乱
  • 三无过滤:无投递链接 + 无应聘文本 + 无邮箱 + 无联系方式的公告直接丢弃
  • 云端去重:调用 check_cloud API 与已入库数据比对
  • 毕业届修复(fix_graduate_year):用正则从标题提取,支持"25届"、"2026"等多种写法,实在提取不到则默认当前年(8月后自动+1年)

关键分叉:

如果渠道在白名单学校内,且大模型判断公告类型为"职位",则走 ann_model_job.py 的单职位路径;否则走普通公告路径。

第二阶段:职位列表解析(普通公告路径)

get_template_job 模板调用大模型,从全文提取所有职位列表(一个公告可能含几十个职位)。做学历规范化(fix_diploma)、去重、空职位名过滤等修复。如果主文本没提取到职位,还会从 tuning_content(页面特定区域抓取的补充内容)里再试一次。

第三阶段:Markdown 格式处理

根据页面特征分四种策略:

  • 大图文章(微信长图文)/ 普通页面 → 读本地 md 文件,用豆包大模型润色格式
  • 外部链接页面 → 用大模型从全文直接提取 Markdown
  • 含复杂表格的页面 → 用大模型专门处理表格转 Markdown

最终把 ann(公告信息)+ jobs(职位列表)+ other(元数据)+ mdfile(展示用 Markdown)四个节点写入 JSON 模型文件。

ann_model_job vs cjob_model — 两条单职位解析路径

这两个文件都是处理"一个页面对应一个职位"的场景,但来源和复杂度不同:

ann_model_job.py 处理公告内的单职位(由 ann_model.py 分支调用)。流程相对简单:HTML 转纯文本 → Qwen 大模型提取 → 校验质量 → 与公告元数据合并(公司名、链接、申请方式、联系人等)→ 写入 JSON。

cjob_model.py 处理大公司招聘网站的职位详情页(独立入口,不经过 ann_model.py)。复杂得多:

  • 通过 detail_selector 配置的 CSS 选择器精准定位职位正文区域,支持正则备选方案
  • 从页面 Header 区域额外提取职位类别、工作地点、发布时间、招聘人数(通过 detail_hd 配置项区分不同网站的 DOM 结构)
  • 对职位类型做规范化:hd_hopeworktype 字段决定 DocType 取值(shixi / xiaozhao / shezhao
  • 使用带 system prompt 的 new_call_gpt 接口,而非普通补全接口

项目分区导航spider_sch.py ⬅️ | 00-parsegpt | ➡️ ann_img