Sign inSign up

riseopc/tapd2word

By riseopc

Updated 6 months ago

把 TAPD 内容导出为 Word(个人备份小工具)

Image
Networking
Internet of things
Developer tools
0

152

riseopc/tapd2word repository overview

tapd2word

https://github.com/riseopc/tapd2word

tapd2word Logo tapd2word Logo

Python Playwright Docx Status Docker

把 TAPD 内容导出为 Word(个人备份小工具):

  • TAPD 故事/需求详情页(tapd_story2word.py
  • TAPD Wiki(tapd_wiki2word.py

💡 支持 Windows/macOS/Linux 本地运行,也支持 Docker(更适合 CI/无 Python 环境)。


✅ 最短可用(你只需要复制这几条)
1) 单条导出 Story(在线)
python src/tapd_story2word.py \
  --url "https://www.tapd.cn/{workspace_id}/prong/stories/view/{story_id}" \
  --cookie "你的 Cookie" \
  --use-playwright \
  --output "story_{story_id}.docx"
2) 批量导出 Story(列表 API)
python src/tapd_story2word.py \
  --export-story-list \
  --workspace-id <workspace_id> \
  --conf-id <conf_id> \
  --cookie "你的 Cookie" \
  --use-playwright \
  --output-dir output \
  --dump-html-dir output/dump_html
3) 批量导出 Wiki(索引页/目录页)
python src/tapd_wiki2word.py \
  --wiki-index-url "https://www.tapd.cn/{workspace_id}/wiki/index" \
  --cookie "你的 Cookie" \
  --output-dir output_wiki
✨ 特性一览(Key Features)
  1. 一键导出 Word:输入 TAPD URL + Cookie,即可生成带图片、表格的 .docx
  2. 真实浏览器渲染:基于 Playwright 启动 Chromium,完整执行前端 JS,避免「只抓到骨架页 / 登录页」。
  3. 图片与富文本支持
    • 支持网络图片、本地图片、data:image/...;base64,... 内联图片;
    • 自动保留标题、段落、列表、表格等结构。
  4. 智能正文区域选择:默认聚焦 div.content-wrap 等内容区域,可用 --root-selector 精准控制。
  5. CLI 友好:参数清晰,适合集成到脚本、CI 或个人自动化工具链中。
  6. 跨平台运行:只要能跑 Python 3.10+ 或 Docker 的环境,都可以使用。

🚀 安装与准备(Quick Start)
本地运行(Python)
  • Python:建议 3.10+
  • 依赖安装
pip install -r requirements.txt
  • 首次使用 Playwright 时需要安装浏览器内核(只需一次):
python -m playwright install

Docker 场景一般不需要手动执行 playwright install(基础镜像已包含浏览器与依赖)。

📦 使用方式(Usage)
1. 批处理脚本(Windows 推荐)

在 Windows 下双击或命令行运行 run_tapd2word.bat,按提示选择模式并输入参数即可:

  • 模式 1:单条导出,输入需求详情 URL + Cookie,输出为单个 Word。
  • 模式 2:批量导出,输入 workspace_id、conf_id、Cookie,从列表接口分页拉取需求并逐个导出到 output/ 目录。
  • 模式 3:批量导出 Wiki,输入 Wiki 索引/目录页 URL + Cookie,导出到 output_wiki/

脚本自动设置 UTF-8 编码,减少中文乱码。

(已集成 Wiki 导出,无需单独脚本。)

1.1 直接导出 Wiki(在线模式)
python src/tapd_wiki2word.py \
  --wiki-index-url "https://www.tapd.cn/{workspace_id}/markdown_wikis/show/#{wiki_id}" \
  --cookie "你的 Cookie" \
  --output-dir output_wiki
  • --wiki-index-url:Wiki 索引页 URL,或任意包含侧边栏目录的 Wiki 页面 URL。
  • --cookie:浏览器开发者工具 Network 面板里任意 https://www.tapd.cn/... 请求头的整行 Cookie 值。
  • --output-dir:导出目录(默认 output_wiki/)。
  • --headed:显示 Playwright 浏览器窗口(即 headless=false),便于观察页面交互与定位问题。
  • --slow-mo-ms:Playwright 操作慢放(对应 slow_mo,单位毫秒)。调试时可配合 --headed 使用,例如 --slow-mo-ms 300

使用用例(批量导出 Wiki 的下载结果示例):

Wiki 批量导出结果示例

  • 输出目录:本例导出到 output_wiki/(你也可以通过 --output-dir 自定义)。
  • 文件命名规则:默认形如 001_<标题>_<wiki_id>.docx(或 .doc)。\n - 001:按目录顺序自动编号,方便按导出顺序浏览\n - <标题>:从 Wiki 标题提取并做文件名安全化(去除 \\/:*?\"<>| 等非法字符)\n - <wiki_id>:保底唯一标识,避免同名覆盖
  • 为什么有时是 .doc:如果走“页面点击下载”模式,脚本会尊重 TAPD 下载建议的扩展名,所以可能保存为 .doc;如需更一致的格式可尝试 --use-post
  • _debug/ 目录:下载失败或取 token 失败时会把截图/HTML/原始响应等调试信息放在 output_wiki/_debug/ 便于排查(正常成功时可能为空)。
2. 从本地 HTML 导出(离线模式)

适合:在浏览器里把 TAPD 页面「网页,全部」保存到本地,然后离线转换为 Word。

python src/tapd_story2word.py \
  --html-file tapd_story.html \
  --title "某个需求文档"
  • --html-file:浏览器保存下来的 HTML 文件路径。
  • --output:导出的 Word 路径;不填时默认使用文档标题作为文件名,即 <标题>.docx,若标题不可用时兜底为 tapd_story_export.docx
  • --title:Word 顶部标题(不填则使用 HTML <title>)。
3. 直接用 TAPD 需求 URL 导出(在线模式)

适合:给定 TAPD 故事详情链接,自动抓取页面、解析正文、下载图片并导出为 Word。

python src/tapd_story2word.py \
  --url "https://www.tapd.cn/{workspace_id}/prong/stories/view/{story_id}" \
  --cookie "__root_domain_v=...; tapdsession=...; t_i_token=..." \
  --use-playwright \
  --output "story_{story_id}.docx"

参数说明:

  • --url:TAPD 故事 / 需求详情页 URL。
  • --cookie:从浏览器开发者工具 Network 面板中,任意一个 https://www.tapd.cn/... 请求头里的整行 Cookie 值。
    • 建议直接复制整行,例如:__root_domain_v=...; tapdsession=...; t_i_token=...
    • 脚本会自动带着这份 Cookie 去访问 HTML 和图片,保证与你浏览器看到的内容一致。
  • --use-playwright
    • 启用 Playwright,真实启动无头 Chromium,执行 TAPD 的前端 JS,把 SPA 渲染完再导出;
    • 对于 TAPD 这种前端渲染较重的页面,强烈推荐总是加上
  • --headed:显示 Playwright 浏览器窗口(即 headless=false)。用于调试/排查点击与选择器问题。
  • --slow-mo-ms:Playwright 操作慢放(对应 slow_mo,单位毫秒),调试时建议配合 --headed 使用(如 --slow-mo-ms 300)。
  • --output:输出 Word 文件名,不填时默认 <标题>.docx
4. 批量导出需求列表

从 TAPD 需求列表接口分页获取所有需求并逐个导出为 Word:

python src/tapd_story2word.py \
  --export-story-list \
  --workspace-id <你的workspace_id> \
  --conf-id <你的conf_id> \
  --cookie "你的 Cookie" \
  --use-playwright \
  --output-dir output \
  --dump-html-dir output/dump_html

API 无法获取列表时的兜底方案:使用 --list-page-url 指定需求列表页面 URL,脚本会通过 Playwright 打开页面、解析其中的需求链接,再逐个导出:

python src/tapd_story2word.py \
  --export-story-list \
  --workspace-id <workspace_id> \
  --conf-id <conf_id> \
  --cookie "你的 Cookie" \
  --use-playwright \
  --list-page-url "https://www.tapd.cn/<workspace_id>/story/list?conf_id=<conf_id>"
🧩 可选功能(Optional)
1. 同时生成页面截图

在线模式 + Playwright 下,可以顺便生成当前页面截图:

python src/tapd_story2word.py \
  --url "https://www.tapd.cn/{workspace_id}/prong/stories/view/{story_id}" \
  --cookie "你的 Cookie" \
  --use-playwright \
  --output "story_{story_id}.docx" \
  --screenshot "story_{story_id}.png"
  • 截图为整页截图(full_page=True),适合存档或快速预览。
2. 精确指定“需求正文”根节点

默认情况下,脚本会按以下优先级自动选择正文容器:

  1. div.content-wrap(TAPD SPA 主内容区域)
  2. div.rich-text
  3. div.story-content
  4. div.story-detail
  5. div#description
  6. 最后兜底 body

如果你的 TAPD 页面结构有差异,或者希望进一步收紧只导出某个区域,可以用 --root-selector 手动指定 CSS 选择器(当前实现已经支持该参数,在线 URL 模式同样生效):

python src/tapd_story2word.py \
  --url "..." \
  --cookie "..." \
  --use-playwright \
  --root-selector "div.rich-text" \
  --output "story.docx"

提示:在浏览器里选中你认为是“需求正文”的最外层元素,查看它的 id / class,例如 #story-description.rich-text 等,然后写进 --root-selector 即可。

📄 导出内容说明(What You Get)

当前版本会尽量保留 TAPD 页面中的以下信息:

  • 标题:优先使用命令行传入的 --title,否则用 HTML <title>
  • 文本结构
    • <h1> ~ <h6> → Word 标题(对应 0~5 级)。
    • <p> → 普通段落。
    • <ul>/<ol>/<li> → 项目符号列表。
  • 图片
    • 支持本地图片(本地 HTML 场景);
    • 支持网络图片(带 Cookie);
    • 支持 data:image/...;base64,... 内联图片;
    • 支持懒加载属性 data-src / data-original
    • 会自动跳过明显的站点 Logo 等无关图片(例如含 TAPD_Logo 的 URL)。
  • 表格<table> → Word 网格表,保留单元格文本。

错误/告警信息(如个别图片下载失败)不会写入 Word,只会在控制台输出 [warn] ... 便于排查,避免污染需求文档内容。

📁 输出目录与文件命名(Outputs)
  • 单条 Story:默认输出 <标题>.docx(标题为空兜底 tapd_story_export.docx)。为避免中文/特殊字符路径差异,建议显式传 --output
  • 批量 Story:输出到 --output-dir(默认 output/),文件名固定 story_{id}.docx;可选 --dump-html-dir 保存调试 HTML。
  • 批量 Wiki:输出到 --output-dir(默认 output_wiki/),文件名形如 001_<title>_<wiki_id>.(docx/doc);点击下载模式下扩展名可能按 TAPD 建议保存为 .doc
  • 调试产物:Wiki 失败/排查信息可能会写入 output_wiki/_debug/
❓ 常见问题(FAQ)
  • 导出为空 / 只有登录页

    • 检查 --cookie 是否是“当前已登录账号”的 Cookie;
    • 尝试在浏览器重新登录 TAPD 后,再从最新请求中复制 Cookie。
  • Word 里缺少部分正文 / 含有多余导航文案

    • 优先尝试加上或调整 --root-selector,把根节点锁定到具体的“需求描述区域”;
    • 如仍有问题,可以根据实际 DOM 结构微调脚本里的默认选择逻辑。
🐳 Docker(推荐用法)

我们已经在 Docker Hub 上提供了预构建的镜像,你可以直接拉取使用,无需本地配置 Python 环境或安装 Playwright 依赖。

1. 拉取镜像
docker pull riseopc/tapd2word:1.0.0
2. 运行示例(导出 Story)
docker run --rm -v /path/to/output:/app/output riseopc/tapd2word:1.0.0 \
  story --url "..." --cookie "..." --use-playwright \
  --output "/app/output/story.docx"
3. 运行示例(导出 Wiki)
docker run --rm -v /path/to/output_wiki:/app/output_wiki riseopc/tapd2word:1.0.0 \
  wiki --wiki-index-url "https://www.tapd.cn/{workspace_id}/markdown_wikis/show/#{wiki_id}" \
  --cookie "你的 Cookie" \
  --output-dir "/app/output_wiki"

提示:如果容器内 Chromium 出现超时/崩溃,建议加上 --shm-size=1g


🛠️ 本地开发与构建(备选)

如果你想自行修改代码或构建镜像,可以参考以下流程:

  1. 本地构建镜像
docker build -t tapd2word:local .
  1. 使用 Docker Compose: 推荐用法是 docker compose run 并显式传 story/wiki 子命令:
docker compose run --rm tapd2word story --help
docker compose run --rm tapd2word wiki  --help

注意:容器内能否访问 TAPD,取决于公司网络 / VPN / 容器网络配置,请按实际环境调整。

🔒 安全提示
  • --cookie 属于敏感信息:不要写进代码仓库、不要发到群里、不要贴到公开 issue。
  • 建议把 Cookie 放在本地环境变量/密码管理器里,必要时定期更新。

Tag summary

Content type

Image

Digest

sha256:dc254b472

Size

925.4 MB

Last updated

6 months ago

docker pull riseopc/tapd2word:1.0.0