parsegpt
这是一套校招/社招公告的全链路解析系统,把爬取到的原始 HTML 页面转化为结构化 JSON,供后续搜索、展示、推荐使用。整体由五个模块分工协作,有一条明确的主干流程,也有两条独立的分支路径。
html_to_text — 底层 HTML 清洗
最底层的工具,被多个上层模块调用。核心逻辑是把 HTML 转成干净的纯文本,但它对 <table> 有特殊处理——不是简单地 get_text(),而是把多列单元格按行合并,尽量保留表格的语义结构(比如"岗位名称 / 工作地点 / 招聘人数"这种横向排列的信息不会丢失)。同时清理掉 CSS、JS、隐藏元素、多余空白和 等噪音字符。
ann_img — 图片处理与 OCR
处理公告里嵌入的图片,流程分五层:
- 下载图片,计算 MD5 和感知哈希(
average_hash),用于内容去重和黑名单匹配 - 二维码检测(
detect_qr_code):识别是否是纯二维码(Y)、混合图(H)还是普通图(N) - 对非纯二维码图片做 PaddleOCR 文字识别,提取出文字供后续搜索全文使用
- 多层过滤:按尺寸、透明度、OCR 文字量、MD5 黑名单、相似哈希黑名单、学校 Banner 黑词表等条件剔除无效图片
- 把有效图片上传华为云 OBS,替换 HTML 里原来的
src地址
关键设计:对混合图(既有普通内容又有二维码),会把二维码区域裁切出来单独上传,便于前端展示"扫码投递"入口。
ann_md — HTML 预处理与 Markdown 转换
流水线的第一道关卡,处理完成后才把内容交给大模型。主要做六件事:
① 清除噪音 DOM(fix_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 转 Markdown(html2md_table):检测表格是否有合并单元格(colspan / rowspan),没有则用专用工具转换,有则退化到 html2text 库处理。
⑥ 渠道专项修复(common_process_sch_98534):针对某所合作学校(编号 98534)的 Markdown 岗位信息区块格式做正则定制处理,是写死的特殊逻辑。
ann_model — 核心调度器(主入口)
整个系统的大脑,串联所有模块,分三个阶段处理。
第一阶段:公告级解析
把 Markdown 全文用 get_template_campus 模板调用大模型,提取公司名、应聘方式、毕业年届、公告类型等字段,然后做一系列后处理:
- 过期检测:截止日期超过 1 个月直接丢弃
- 多公司检测:大模型判断是多家公司联合发布时,将公司名改为"校招公告",避免归属混乱
- 三无过滤:无投递链接 + 无应聘文本 + 无邮箱 + 无联系方式的公告直接丢弃
- 云端去重:调用
check_cloudAPI 与已入库数据比对 - 毕业届修复(
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
💬 评论