--- title: "00-parsegpt" created: 2026-04-02 tags: - 项目 aliases: - parsegpt --- # parsegpt > 这是一套**校招/社招公告的全链路解析系统**,把爬取到的原始 HTML 页面转化为结构化 JSON,供后续搜索、展示、推荐使用。整体由五个模块分工协作,有一条明确的主干流程,也有两条独立的分支路径。 ![[image-42313e76.png]] ### [[06-html_to_text|html_to_text]] — 底层 HTML 清洗 最底层的工具,被多个上层模块调用。核心逻辑是把 HTML 转成干净的纯文本,但它对 `` 有特殊处理——不是简单地 `get_text()`,而是把多列单元格按行合并,尽量保留表格的语义结构(比如"岗位名称 / 工作地点 / 招聘人数"这种横向排列的信息不会丢失)。同时清理掉 CSS、JS、隐藏元素、多余空白和 ` ` 等噪音字符。 ### [[01-ann_img|ann_img]] — 图片处理与 OCR 处理公告里嵌入的图片,流程分五层: 1. 下载图片,计算 MD5 和感知哈希(`average_hash`),用于内容去重和黑名单匹配 2. 二维码检测(`detect_qr_code`):识别是否是纯二维码(`Y`)、混合图(`H`)还是普通图(`N`) 3. 对非纯二维码图片做 PaddleOCR 文字识别,提取出文字供后续搜索全文使用 4. 多层过滤:按尺寸、透明度、OCR 文字量、MD5 黑名单、相似哈希黑名单、学校 Banner 黑词表等条件剔除无效图片 5. 把有效图片上传华为云 OBS,替换 HTML 里原来的 `src` 地址 关键设计:对混合图(既有普通内容又有二维码),会把二维码区域裁切出来单独上传,便于前端展示"扫码投递"入口。 ### [[02-ann_md|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 岗位信息区块格式做正则定制处理,是写死的特殊逻辑。 ### [[03-ann_model|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 模型文件。 ### [[04-ann_model_job|ann_model_job]] vs [[05-cjob_model|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` 接口,而非普通补全接口 --- **项目分区导航**:[[04-spider_sch.py|spider_sch.py]] ⬅️ | 00-parsegpt | ➡️ [[01-ann_img|ann_img]]