帮助文档转需求文档
给一个帮助文档网址,还你一份能直接开工的需求规格说明书。 遍历 → 认产品 → 抽功能 → 成文档,四步全自动,纯标准库零依赖。
核心能力
- 站点遍历 — 从入口 URL 出发按层级爬取文档页;先识别页面上的目录栏(TOC),用目录链接的公共前缀反推文档根目录,入口给的是深层页面也能覆盖兄弟分类;并发优先(2 线程),遇限流自动降级串行,持续失败则报错终止
- 产品名识别 — 先用 meta / 标题公共部分 / 概述句式确定「这份需求写的是哪个产品」,再以产品名作为锚点筛选功能章节
- 功能点抽取 — 按标题切分章节,用「动作动词 + 界面元素 + 流程标记 + 约束词 + 产品名命中」打分,正文只保留文字(去图片/视频/外链)
- 需求结构化与成文 — 渲染成标准需求规格说明书 Markdown:产品识别依据、功能需求 FR-xxx、验收标准 checklist、非功能线索、需求追踪矩阵、页面覆盖清单、待确认事项
快速开始
流程1:一键生成(推荐)
用户说:把这个帮助文档转成需求文档 / 根据这个网址写需求文档
python scripts/run_pipeline.py --input '{"url": "https://example.com/help/", "product_name": "XX产品", "max_depth": 3, "max_pages": 200, "out_dir": "./output"}'
产物(在 out_dir):
| 文件 | 内容 |
| --- | --- |
| 需求规格说明书.md | 唯一交付物,最终结果只输出这一份 |
| (默认清理)01_crawl.json / 02_product.json / 03_features.json / 04_requirements.json | 中间产物,成功后自动删除;传 "keep_intermediate": true 可保留 |
输出示例:
{
"status": "ok",
"files": { "requirements_md": "./output/需求规格说明书.md" },
"cleaned_intermediates": ["01_crawl.json", "02_product.json", "03_features.json", "04_requirements.json"],
"crawl_config": { "root": "/enterprise/", "root_inferred_from": "目录栏公共前缀", "toc_source": "版面目录区域" },
"product": {"name": "阅流", "confidence": "high", "evidence": ["标题公共后缀「阅流」", "页面标题命中 31 次"]},
"summary": { "pages_ok": 31, "features": 58, "requirements": 58, "nfr": 2, "elapsed_ms": 21400 }
}
product_name可以不传:脚本会先自动识别,识别结果写在02_product.json与需求文档第 0 节。 若识别置信度为low,文档「待确认事项」会提醒人工确认。
流程2:分步执行(需要调参时)
# 1) 遍历
python scripts/crawl_help.py --input '{"url": "...", "max_depth": 3}' --output crawl.json
# 2) 识别产品名(可选,用于确认锚点)
python scripts/detect_product.py --input '{"crawl_file": "crawl.json"}' --output product.json
# 3) 抽取(传 product 做产品锚定;strict 会丢弃未提及产品名的页面)
python scripts/extract_features.py --input '{"crawl_file": "crawl.json", "product": {"name": "云图协作平台", "aliases": ["云图协作"], "strict": true}, "min_score": 4}' --output features.json
# 4) 成文
python scripts/gen_requirements.py --input '{"features_file": "features.json", "crawl_file": "crawl.json", "product_name": "XX产品"}' --output 需求规格说明书.md
参数多时用 --input-file params.json 代替 --input,避免命令行转义地狱。
流程3:只抽取功能点(不要成文)
用户说:这个文档都有哪些功能 / 列一下功能清单
python scripts/run_pipeline.py --input '{"url": "...", "sections": ["functional"]}'
或直接看 03_features.json 的 features[].name 与 summary.modules。
流程4:只遍历不抽取(要原文存档)
python scripts/crawl_help.py --input '{"url": "...", "max_depth": 3, "include_content": true}' --output crawl.json
遍历深度怎么选?(关键参数)
max_depth 计的是链接层级(入口页 = L0),不是目录层级。
| 文档站结构 | 建议深度 | 典型站点 |
| --- | --- | --- |
| 单页长文档(左侧锚点目录) | 1 | 一个页面讲完全部功能 |
| 扁平:入口 → 功能页 | 2 | 小型产品、小团队文档 |
| 分类 → 子分类 → 功能页(最常见) | 3(默认) | GitBook / Docusaurus / VuePress / 语雀 |
| 多级目录、按版本分册 | 4 | Confluence、大型 SaaS 帮助中心 |
| 不确定 | 先 2 试跑,看结果再加 | — |
调节方法:跑完看 summary 判断
pages_ok远小于站点实际文档数 → 加深max_depth或把scope改成"domain"links_skipped里「超出目录范围」特别多 → 说明入口所在目录太窄,改用scope: "domain"或传prefixpages_ok撞上max_pages→ 提高上限,或用include正则锁定目标路径
经验值:中小产品帮助中心 max_depth=3 + max_pages=150 通常能覆盖 80% 以上的功能页;
超过 4 层后新增页面多为细节页与重复内容,收益递减、噪声上升,不建议盲调。
其它常用遍历参数:
| 参数 | 默认 | 说明 |
| --- | --- | --- |
| scope | path | path=入口所在目录及子目录;domain=整站;prefix=自定义前缀 |
| max_pages | 200 | 页面数硬上限,防止爬爆 |
| include / exclude | - | URL 正则白/黑名单;传 exclude 会覆盖默认噪声规则 |
| concurrency / delay | 4 / 0.2 | 并发数与礼貌延迟,慢站调大 delay |
| timeout | 15 | 单页超时(秒);国内站点慢时调到 30 |
| keep_query | false | 是否保留 query 参数(带 ?id= 的文档站要开) |
抓取策略(并发 → 降级 → 终止)
默认 2 线程并发抓取,礼貌抓取优先,遇到限制自动让步:
并发(≤2 线程,间隔 delay)
↓ 命中 429 / 503 / 403 / 验证码页
串行(每次请求前随机延迟 10~50ms,失败静默重试 1 次)
↓ 连续 max_failures(默认 5)个页面仍失败
报错终止(保留已抓到的页面,返回 status="aborted")
| 参数 | 默认 | 说明 |
| --- | --- | --- |
| concurrency | 2 | 最大并发线程数(硬上限 2) |
| delay | 0.2 | 并发阶段的请求间隔(秒) |
| serial_delay | [0.01, 0.05] | 串行阶段的随机延迟区间(秒)= 10~50ms |
| max_failures | 5 | 连续失败多少次后终止 |
| timeout | 15 | 单页超时(秒) |
在 summary 里回显:fetch_mode(最终模式)、rate_limit_events(限流次数)、degrade_reason(降级原因)。
被限速的站点建议直接把 delay 调到 0.5~1、concurrency 设为 1。
目录栏识别与根目录推断
入口 URL 常常是深层页面(如 /enterprise/产品简介/产品概述.html),按"所在目录"推断范围会漏掉
兄弟分类(/enterprise/管理后台功能/…)。因此遍历器这样定根目录:
- 先抓入口页,从版面目录区域(nav/aside/带 toc|sidebar|menu 等 class 的容器)提取链接; 不足 3 条时回退用整页链接
- 用「入口 + 目录链接」的公共路径前缀反推文档根目录(如
/enterprise/); 目录链接跨多个一级目录时,保守取入口路径第一段 - 目录栏里的链接全部作为种子页面进入第一层遍历,不依赖入口页上的链接
中文 percent-encoded 路径(/enterprise/%E7%AE%A1%E7%90%86...)在范围判断、排除规则中
均按解码后的形式处理,/常见问题/ 这类目录能被正确排除。
推断结果在 config 里可核查:root(根目录)、root_inferred_from(推断依据)、
toc_source(目录栏来源)、toc_candidates(目录候选数)。
自动推断不合适时用 prefix 显式指定,或 scope: "domain" 抓全站。
产品锚定(提高准确度的关键)
纯关键词打分会把「帮助中心里挂着的第三方产品说明」也抽成需求。因此流水线先识别产品名,再用它过滤:
| 阶段 | 做法 |
| --- | --- |
| 识别 | meta site_name → 标题公共前后缀 → 标题高频词 → 概述句式("X是一款…")→ 产品类后缀词,加权投票,输出置信度 |
| 加分 | 章节文本命中产品名/别名 → +1 分 |
| 过滤 | strict_product: true 时,整页都未提及产品名的页面直接跳过(产品名识别为 low 置信度时自动失效,防止误杀) |
实测:帮助中心混有第三方产品页时,开启 strict 可精确剔除无关功能点,本产品需求不受影响。
脚本说明
scripts/run_pipeline.py
- 输入:url + product_name(可选)+ 遍历/抽取/成文的可选参数
- 输出:5 个产物文件 + 汇总 JSON
- 逻辑:遍历 → 识别产品 → 抽取(带产品锚点)→ 成文,任一步失败会明确报错并保留中间产物
scripts/detect_product.py
- 输入:crawl 产物(或 pages 数组)+ 可选 hint
- 输出:product{name, aliases, confidence, evidence, overview, keywords} + candidates
- 逻辑:多线索加权投票 → 清洗噪声词/版本号 → 定置信度 → 推别名
scripts/crawl_help.py
- 输入:url + max_depth/max_pages/scope/include/exclude/并发降级参数
- 输出:pages[{url,title,depth,headings,content}] + summary
- 逻辑:BFS 分层抓取 → 编码探测 → HTML 转纯文字 Markdown → 提链接 → 范围过滤 → 去重
scripts/extract_features.py
- 输入:crawl 产物(或 pages 数组)+ product(产品锚点)+ 阈值参数
- 输出:features[] + skipped[] + summary
- 逻辑:按标题切章节 → 排除非功能章节 → 多维打分(含产品命中)→ 抽步骤/规则/界面元素 → 按「模块+名称」合并
scripts/gen_requirements.py
- 输入:features + crawl(用于溯源与覆盖清单)+ product_name + 产品识别信息
- 输出:Markdown 需求文档 + 结构化 JSON
- 逻辑:定优先级 → 编号 FR-xxx → 生成验收标准 → 汇总非功能线索 → 追踪矩阵 → 附录
scripts/_common.py
公共库:HTTP 抓取(含限流识别)、编码检测、HTML→纯文字 Markdown(去图片/视频/外链)、标题大纲、链接提取、URL 归一化。被上面四个脚本复用,不单独运行。
Agent 工作流(脚本 + 模型的分工)
脚本负责确定性的部分(抓取、切分、打分、成文),模型负责语义的部分。建议这样配合:
- 确认输入 — 问清:帮助文档入口 URL、产品名称(不知道就留空,让脚本识别)、目标读者(不确定就按默认值跑,最后在文档里标
[待确认]) - 试跑 — 先用
max_depth=2, max_pages=30跑一遍,看summary.pages_ok和模块清单,判断范围和深度是否合适 - 正式跑 — 调整参数后完整执行,得到
03_requirements.md - 语义精修(必须做) — 读
01_crawl.json的原文,对初稿做:- 合并脚本误拆的同质需求、拆分一章多功能的章节
- 把"文档口吻"("你可以点击…")改写成"需求口吻"("系统应提供…")
- 删掉抽取噪声:非功能性的说明、示例代码讲解、营销内容
- 补全脚本标了
[待确认]的验收标准、补充异常与边界场景 - 校准优先级(脚本按关键词和完整度打分,业务优先级仍需人工判断)
- 交付 — 精修后的 Markdown 写到用户指定路径,并说明覆盖率、待确认项、建议评审顺序
脚本产出的是可评审的初稿,不是终稿。
03_requirements.md里凡标注[待确认]的地方,都是原文档没写、必须产品侧补充后才能开发的项。
调优指南
| 症状 | 处理 |
| --- | --- |
| 抽到的需求太少 | min_score 降到 4;max_depth 加深;scope 改 domain |
| 覆盖的分类不全 / summary 有 narrow hint | 用 prefix 显式指定文档根目录(如 /enterprise/) |
| 抽到的噪声太多 | min_score 提到 6~7;用 exclude 加 URL 黑名单 |
| 混进了别的产品/第三方工具的功能 | 开启 strict_product: true(丢弃未提及产品名的页面) |
| 产品名识别错了 | 显式传 product_name 覆盖;或开启 keep_intermediate 看 02_product.json 的 candidates |
| 抓取被限流/超时 | 调大 delay(0.5~1)、concurrency 设 1、timeout 设 30;脚本会自动降级串行 |
| 某类产品词没被识别 | 传 extra_verbs(动作词)/ extra_ui(界面元素)补充关键词 |
| 重要章节被误排除 | 传 keep_titles: ["安装", "配置"] 放行默认的排除标题 |
| 站点是 SPA / JS 渲染 | 本工具只取静态 HTML,改用浏览器渲染后再喂 --input-file,或直接读 02_features.json 手工补 |
| 需要登录才能访问 | 脚本不带 Cookie,先在浏览器登录后导出 HTML 再处理 |
| 抽取规则想改 | 改 extract_features.py 顶部的关键词表,或见 references/extraction_rules.md |
设计原则
- 纯标准库 — 只用 urllib / html.parser / json / re,零安装、拿来就跑
- 范围可控 — 同站 + 同目录双重约束 + 页面数硬上限,绝不爬爆
- 礼貌抓取 — 并发上限 2 线程,被限速立即降级串行 + 随机延迟,绝不硬刚反爬
- 先认产品再抽功能 — 产品名作为锚点参与打分与过滤,避免把第三方内容写进需求
- 只留文字 — 图片、视频、音频、下载资源、站外链接一律只保留文字,正文干净利于抽取
- 噪声优先过滤 — 更新日志、FAQ、法务、下载、博客、导航侧栏等默认排除,减少后期人工清理
- 可溯源 — 每条需求都带来源 URL,追踪矩阵与覆盖清单让评审有据可依
- 诚实标注 — 文档没写/没认准的绝不臆造,一律标
[待确认]并汇总到附录 - JSON 标准化 — 输入输出全 JSON,脚本可组合、Agent 好对接
微信扫一扫