下载地址
https://www.zhengdianxue.com/wp-content/uploads/skills/lingjiakeji--mlsbs-xiangmuchubei.zip将提示词发送给你的 AI 安装该 skills
请根据 https://skillhub.cn/install/skillhub.md,安装 @lingjiakeji/mlsbs-xiangmuchubei。标讯自动抓取建档:从公共资源交易平台抓招标公告,经类型/品类/地域/时间四关过滤后自动建档,生成标讯清单与资格对照表。
阅读全文 (展开查看完整说明)
概述
标讯自动抓取建档
本技能是实操落地版,从绿鲜源(食材配送)标讯建档真实项目中沉淀。核心流程已跑通验证:API抓取→四关过滤→详情页另存→资格逐条对照→自动建档。
解决什么问题
手动刷招标网站找项目,三大痛点:慢、漏、乱。本技能用一套 Python 脚本把流程自动化:抓取→过滤→建档→对照,跑完直接在项目储备库里生成结构化文件夹,每个项目带公告原文和资格对照表,你只需要看结论决定跟不跟。
场景
绿鲜源(食材配送公司)去投标,在河南省公共资源交易中心查标讯。大的方向两条:
- 必须是食材配送相关的
- 必须15天以内的(时间太久可能已招完,没意义)
范围内的按命名规则建文件夹、另存公告网页、做台账匹配MD文件。范围外的直接放弃。
在四库架构中的位置
0公司资料库 → 1项目储备库(本技能产出) → 2项目管理库 → 3项目复盘库
台账(xlsx) 按日期-项目名建档 S1-S6标书流程 复盘- 输入:0公司资料库的公司台账 xlsx(全部6个sheet:01资质证照 / 02人员证件 / 03业绩合同 / 04纳税社保 / 05财务资料 / 06荣誉奖项)
- 产出:1项目储备库下每个项目一个子文件夹(
01招标文件/公告原文.html+01招标文件/资格对照表.md) - 下游:确定要投的项目移入2项目管理库走S1-S6
核心流程
第一步:配参数(换行业只改这里)
脚本顶部「可配置区」6个参数:
| 参数 | 作用 | 示例(食材配送) |
|---|---|---|
SITE | 站点GUID | 河南站ID |
HOST | 站点域名 | hnsggzyjy.henan.gov.cn |
CATEGORY | 频道编号 | 002002=政府采购 |
KEYWORD | 搜索词 | 食材(越精确假阳性越少) |
RECENT_DAYS | 时间窗口 | 15(公开招标等标期最长20天,15天内绝对来得及) |
LEDGER_PATH | 公司台账路径 | xlsx文件 |
加上 RESERVE_DIR(项目储备库目录)和匹配规则正则(品类/地域)。
换行业 = 改这些参数 + 改 judge_item 的匹配分支,脚本主体逻辑不变。详见
references/huan-hangye.md。
第二步:抓取(API接口)
公共资源交易平台的公告列表有 JSON API,不用爬 HTML:
# 核心:POST 调接口(GET会405),一次拿全库再本地按时间筛
data = {"siteGuid": SITE, "categoryNum": CATEGORY,
"pageIndex": 0, "pageSize": 200, "kw": KEYWORD}
req = urllib.request.Request(url=API, data=body,
headers={**UA, "Content-Type": "application/x-www-form-urlencoded"})踩过的坑:
- GET 会 405,必须 POST
- 接口响应慢(河南站偶尔 60-90s),timeout 设 90s
- 一次拉 200 条全库,本地按时间窗口筛,避免接口分页排序不稳定漏掉最新标
找 API 的方法: 浏览器打开目标站公告列表页 → F12 → Network → 找返回 JSON 的请求 → 看 Method、URL、Payload。
第三步:四关过滤
抓回来的数据 90% 跟你无关,四道关卡层层过滤:
第1关 类型:排除结果/成交/变更/废标/终止/流标类(只留活跃可投的)
第2关 品类:标题必须含主营品类关键词(如"食材")
第3关 地域:公告地域标记必须在覆盖范围内(如"河南")
第4关 时间:发布日期必须在时间窗口内(如最近15天)过滤规则(正则):
EXCLUDE_TYPE = re.compile(r'结果|成交|变更|更正|废标|终止|补充|流标')
ACTIVE_TYPE = re.compile(r'采购公告|招标公告|竞争性磋商|询价|单一来源')
CAT = re.compile(r'食材') # 换品类改这里
HENAN = re.compile(r'河南') # 换地域改这里地域标记在哪:列表接口返回的 customtitle 字段里有 [河南省·焦作市] 格式的地域标签,用正则提取。
输出:适合投的项目列表 + 放弃清单(分四类记录被放弃原因,方便复盘有没有误杀)。
第四步:详情页另存(公告原文.html)
通过四关过滤的项目,逐个抓详情页,网页另存到项目文件夹的 01招标文件/ 子文件夹下。
实现方式(原始HTML直接存,不重新渲染):
- fetch_detail():抓详情页原始 HTML 字节流 → 注入
<base>标签(让图片/CSS等相对路径能正常加载)→ 返回(原始HTML, 纯文本) - 纯文本仅供资格提取用,跟存文件完全解耦
def fetch_detail(url):
"""抓详情页,返回 (原始HTML, 正文纯文本)。
网页另存思路:原始 HTML 直接存文件,不重新渲染、不剥噪声、不套CSS。
浏览器打开就是原版页面,表格图片格式一个不丢。
纯文本仅供 extract_qualification 提取资格要求(给机器读)。"""
raw = urllib.request.urlopen(req, timeout=60, context=ctx).read().decode('utf-8', 'ignore')
# 注入 <base> 让相对路径能加载,其余原样不动
base_tag = f'<base href="{HOST}/">'
html_to_save = raw.replace('<head>', f'<head>{base_tag}', 1) if '<head' in raw else base_tag + raw
# 纯文本提取(仅供资格对照,不用于存文件)
soup = BeautifulSoup(raw, 'html.parser')
# ... 提取正文容器 get_text
return html_to_save, text为什么直接存原始HTML:
- 简单,不重新渲染,网页另存就行
- 原版排版、表格、图片一个不丢
- 纯文本提取单独做,跟存文件解耦
详情页抓取提速:用 ThreadPoolExecutor 并发抓取(max_workers=4),避免串行逐个请求拖慢整轮建档。
第五步:资格要求逐条对照(资格对照表.md)
这是最有价值的一步:从公告原文提取每一条资格要求,逐条对照公司台账,给出明确结论。
流程:
- extract_qualification():从详情页纯文本中定位「申请人的资格要求」章节(多个标题正则兜底),用下一个章节标题定位结束位置
- split_qual_items():按序号拆分成条目。河南公告典型结构:
二、申请人资格要求 → 1(含1.1)、2、3(含3.1/3.2/3.3)、备注- 先压成单行(消除 HTML 硬换行把"2025年度"误判成序号)
- 断行只在「数字+.或、」且前置边界(段首/空白/;/。)处;顶层加
(?!d)排除1.1里的1.,避免拆成11 - 截断「备注/注:」:备注会引用"3.2"等造成误判,且本身不是资格要求
1.1这类「大杂烩」(政府采购法第二十二条六项用、并列)保留为一条,由 judge_item 内部逐子项判断
- judge_item():对每条用关键词匹配判断——台账有没有对应资质?是通用条款还是特定要求?
1.1大杂烩特殊处理:营业执照/财务审计报告/依法纳税/社保缴纳/设备专业技术能力/无重大违法记录 六项逐条判,合并成一行- 信用类(信用中国/失信)不匹配台账3A,标
○待查(开标当日网站查);财务审计匹配05财务资料sheet
- build_card():生成四段式资格对照表
结论图例:
| 标记 | 含义 |
|---|---|
| ✅ 满足 | 台账有对应资质,明确满足 |
| ⚠️ 需核实 | 台账未列,不等于不满足,需人工确认 |
| ○ 通用 | 通用条款,提交材料即满足(如纳税证明) |
| — 无要求 | 该条无特殊要求 |
| ❓ 待核实 | 关键词未命中,需人工看原文 |
铁律:不允许编造数据。 台账没有的资质标 ⚠️,绝不写 ✅。
judge_item 分支逻辑(约15个分支,按顺序匹配):
行业特定资质(换行业需改):
- 食品经营/生产许可 → 查台账01资质证照
- 营业执照/独立法人 → 查台账01资质证照
- 仓库/仓储/场地/㎡ → 查台账01资质证照
- 财务/审计 → 查台账05财务资料(审计报告)
- 业绩/配送经验 → 查台账03业绩合同
- 设备/专业技术能力/检测报告 → 查台账01资质证照
通用条款(跨行业通用,不用改):
- 政府采购法第二十二条 → ○ 通用
- 政府采购政策 → ○ 通用
- 信用中国/失信/裁判文书 → ○ 待查(开标当日网站查询,不匹配台账3A信用)
- 依法缴纳税收/社保 → ○ 通用
- 联合体 → ○ 通用(独立主体投标即满足)
- 单位负责人/控股/管理关系 → ○ 通用
- 资格后审/真实性/合规性 → ○ 通用
- 承诺/安全合格产品/食物中毒/赔偿责任 → ○ 通用(承诺类,出具承诺书即可)
- 违规/违法/处罚/行贿 → ○ 通用(承诺类,出具无违规承诺书即可)
注意:信用条款优先于税收判断——"重大税收违法失信"里有"税收"二字,如果税收分支在前会误命中。脚本里信用分支写在税收分支前面。
注意:信用类不匹配台账3A信用——3A信用证书不管用,信用审查是开标当日去信用中国网站查的,统一标 ○ 待查。
建档产出结构
1项目储备库/
20260708-焦作市马村区学校食堂食材统一采购配送项目/
01招标文件/
公告原文.html ← 网页另存(原始HTML,浏览器打开即原版排版)
资格对照表.md ← 四段式:基础匹配 / 资格对照 / 行动建议
02过程资料/ ← 先建空,后续阶段用
03投标文件/ ← 先建空,后续阶段用
04开评定标/ ← 先建空,后续阶段用
20260702-河南省公安厅高速公路交通警察总队餐厅管理服务和食材供应项目/
01招标文件/
公告原文.html
资格对照表.md
02过程资料/
03投标文件/
04开评定标/
已放弃/
放弃清单_20260714.md ← 按类型/品类/地域/时间分四类记录
今日可投标讯清单_20260714.md ← 汇总清单(适合投表格 + 放弃统计)项目建档时一次性建 4 个子文件夹(01招标文件 / 02过程资料 / 03投标文件 / 04开评定标),公告和卡片放
01招标文件/,其余先建空备用。02~04 留给后续项目管理库、项目复盘库阶段使用。
汇总清单同时同步一份到脚本所在目录(演示用)。
文件夹命名规范
YYYYMMDD-项目核心名称
YYYYMMDD = 公告发布日期(不是抓取当天)
项目核心名称 = clean_title() 严格清洗后的标题clean_title() 清洗规则(顺序执行):
- 去
[地域标签]等中括号标注 - 去尾部「采购方式+公告类型」整体(如"-公开招标公告"整体去掉)
- 兜底去孤立冗余的"-公开"
- 压缩内部多余空白
- 剔除 Windows 非法字符
/ : * ? " < > | - 不随意截断,仅 >60 字时尾部截断
资格对照表结构(四段式)
# 资格对照表:[公告标题]
- 来源 / 类型 / 地域 / 发布日期 / 详情链接
- 公告原文:见同文件夹 公告原文.html
- 匹配结论:✅ 建议投标
## 一、基础匹配(基于公告标题与接口字段,确定性强)
| 品类 | 标题含「食材」 | ✅ |
| 地域 | 河南全省在经营范围内 | ✅ |
| 时间 | 距今N天,未超等标期 | ✅ 来得及 |
## 二、资格要求逐条对照(严格按公告原文,逐条对照公司台账)
> 图例:✅满足 ⚠️需核实 ○通用条款 —无要求 ❓待核实
| # | 公告资格要求(原文) | 公司台账情况 | 结论 |
| 1 | 具有独立法人资格 | 台账有营业执照 | ✅ 满足 |
| 2 | 具有食品经营许可证 | 台账持有 | ✅ 满足 |
| 3 | 具有仓储场地 | 台账未列 | ⚠️ 需核实 |
> 小结:共N条,台账明确满足X条,需核实Y条
## 三、投标行动建议
1. 打开公告原文.html,下载招标文件,核对预算、截止时间
2. 从台账调取资质复印件
3. 从台账选取同类业绩作加分项
4. 对⚠️/❓项尽快补齐材料产出函数清单
脚本包含以下函数,每个职责清晰:
| 函数 | 作用 |
|---|---|
load_ledger() | 读公司台账xlsx,提取资质清单和业绩数量 |
fetch() | POST调API拿公告列表JSON |
clean_title() | 标题清洗→项目核心名称 |
build_folder_name() | 生成 YYYYMMDD-项目名 文件夹名 |
fetch_detail() | 抓详情页,返回(正文HTML, 纯文本) |
build_html_page() | 正文HTML套CSS+标题+meta → 公告原文.html |
extract_qualification() | 从纯文本定位资格要求章节 |
split_qual_items() | 按序号拆成条目 |
judge_item() | 单条资格对照台账,返回(台账情况, 结论) |
build_card() | 生成资格对照表.md(四段式) |
build_abandon() | 生成放弃清单.md(四类分列) |
build_summary() | 生成汇总清单.md(适合投表格+放弃统计) |
辅助脚本:refresh_original.py
已建档的项目如果需要重刷公告原文和卡片(比如脚本更新了资格对照逻辑),不用重跑全量匹配:
# refresh_original.py 的逻辑:
# 1. 遍历 RESERVE_DIR 下已有项目文件夹
# 2. 从资格对照表.md 中提取详情链接
# 3. 重新抓详情页 → 覆盖公告原文.html → 重建资格对照表.md
# 4. 不调列表接口,避免90s慢请求公司台账格式
台账是 xlsx 文件,含6个 sheet(load_ledger 全部读取):
Sheet「01资质证照」: 第2列是证照名称(营业执照、食品经营许可证、道路运输证、ISO、HACCP等)
Sheet「02人员证件」: 第3列是证件类型(健康证、食品安全管理员证等)
Sheet「03业绩合同」: 第2列是项目名称,行数即为业绩数量
Sheet「04纳税社保」: 第2列是资料名称(完税证明、社保缴纳证明等)
Sheet「05财务资料」: 第2列是资料名称(审计报告等)
Sheet「06荣誉奖项」: 第2列是奖项名称
执行原则
- 先小规模验证再全量跑:换站点/换品类时先用1个关键词跑一遍看结果对不对
- 不编造数据:台账没有的资质标 ⚠️,绝不写 ✅
- 放弃要留痕:被过滤的项目记录原因,方便复盘有没有误杀好项目
- 并发提速:详情页用 ThreadPoolExecutor 并发抓取
- 日期用公告发布日:文件夹命名的日期是公告发布日期,不是抓取当天
依赖
pip install beautifulsoup4 openpyxl
# 不需要 playwright/selenium(API接口直接返回JSON)资源引用
templates/config-template.py— 完整可运行脚本模板(含全部函数,换参数即可跑)templates/build-url.py— 指定URL建档(单项目):跳过批量抓取+四关过滤,直接对一个"已选定"的公告URL按本技能规范建档。用于木老师手动指定某项目(如别人分享的链接)。用法:改脚本顶部[本项目参数]区,python build-url.pytemplates/资格对照表模板.md— 资格对照表四段式示例references/huan-hangye.md— 换行业实操指南(怎么找API、改参数、调匹配规则)references/guolv-guize.md— 过滤规则详解与调优原则references/xinxi-yuan.md— 信息源三层分类方法论(从原技能mlsbs-xiangmuchubei吸收保留)
已知坑(已修复,记录备查):
- 河南省政府采购网
zfcg.henan.gov.cn公告正文是 JS 异步加载($.get('...htm')注入#content),fetch_detail原版 urllib 只抓到空壳 → 打开空白、资格拆 0 条。build-url.py已处理:识别$.get(...htm)抓回片段注入#content。extract_qualification结束标志误杀:原结束正则含开标时间,会命中资格条款内部"(注:…开标时间以前…)"把后续 3.9~3.11 整段切掉 → 已删除开标时间,改靠获取采购文件 / 三、截断。split_qual_items备注截断误杀:原逻辑在首个备注/注:处截断,会切掉嵌在条目中间的注之后的所有条款 → 已改为只截断"末尾"备注段(其后无编号条目才截断)。judge_item未覆盖"健康证":人员证件(台账02)里的健康证无匹配分支,含"健康证"的条款会落❓待核实。待打磨:加一个查02人员证件的分支。