Pulse Book 是一个面向已授权内容的多站点离线归档工具。2.0 版本通过统一的
pulse-book 命令管理彼此独立的小鹅通和微信公众号抓取器,并为后续网站保留扩展空间。
请仅抓取、下载和备份你有权访问的内容,并遵守平台和内容方的使用条款。
- 小鹅通课程目录提取、视频下载、介绍页课件图片抓取和 PDF 合并。
- 微信公众号合集或单篇文章的安全离线 HTML 与图片归档。
- Playwright/Chrome 登录态复用、断点续抓、资源去重和严格配置校验。
- 通用运行配置与私人合集规则分离,私人 URL、密码、筛选和选择器不会进入 Git。
- Python 3.10+
- uv
- Chrome/Edge;课件和微信抓取还需要 Playwright Chromium
ffmpeg,用于小鹅通视频下载
git clone https://github.com/1COOS/pulse-book.git
cd pulse-book
uv sync
uv run playwright install chromium项目只提供一个公开入口:
uv run pulse-book --help
uv run python -m pulse_book --help视频命令默认通过 Chrome DevTools Protocol 连接已登录浏览器:
# macOS 示例
open -a "Google Chrome" --args --remote-debugging-port=9222
uv run pulse-book xiaoe-album extract "https://example.xetslk.com/s/xxxxx"
uv run pulse-book xiaoe-album download items.json
uv run pulse-book xiaoe-album all "https://example.xetslk.com/s/xxxxx"抓取介绍页课件或生成 PDF:
uv run pulse-book xiaoe-album slides "https://example.h5.xet.pomoho.com/p/course/ecourse/course_xxxxx"
uv run pulse-book xiaoe-album slides "https://example.h5.xet.pomoho.com/p/course/video/v_xxxxx" --input-type video --pdf
uv run pulse-book xiaoe-album slides-pdf ./out/xiaoe-album/slides已配置私人合集规则时,可以省略 URL:
uv run pulse-book xiaoe-album all --collection "示例课程"
uv run pulse-book xiaoe-album slides --collection "示例课程" --headed微信默认使用独立的可见 Playwright profile。首次遇到登录或访问验证时,请在打开的浏览器中手动完成;工具不会绕过验证码。
uv run pulse-book wechat-album archive "https://mp.weixin.qq.com/mp/appmsgalbum?..."
uv run pulse-book wechat-album archive "https://mp.weixin.qq.com/s?..."
uv run pulse-book wechat-album archive --collection "示例合集"从已完成的微信离线归档按分类生成正文 PDF,不会访问微信:
uv run pulse-book wechat-album pdf --collection "示例合集"PDF 输出到合集目录的 pdf/,只包含 .rich_media_content 或
.wechat-content 下的内容;不包含离线页标题、作者、日期和来源。
筛选与正文裁剪可以临时通过命令行覆盖:
uv run pulse-book wechat-album archive "https://mp.weixin.qq.com/mp/appmsgalbum?..." \
--start-index 10 --end-index 30 \
--title-include "地理" \
--published-since 2026-01-01 \
--exclude-selector ".temporary-ad"合集正文需要在特定声明或页脚之前截断时,在忽略 Git 的私人规则中配置 JavaScript Unicode 正则:
content_start_pattern = '\d{1,6}\s*[..、]'
content_end_pattern = "版权声明"工具保留首次开始匹配至首次结束匹配之前的完整 DOM。任一标记没有匹配时回退到对应的 正文开头或末尾;无效正则及起止顺序错误会明确失败。manifest 只记录是否配置以及本篇 是否找到起止位置,不保存正则原文。
退出码:0 表示全部成功,1 表示输入、配置或抓取命令失败,2 表示归档完成但仍有 partial 或 failed 条目。
config/pulse_book.toml 是唯一被跟踪的运行配置,使用严格的版本和字段校验:
version = 1
[xiaoe_album.browser]
cdp_url = "http://localhost:9222"
profile = "/tmp/xiaoe-album-playwright-profile"
[xiaoe_album.download]
output_dir = "./out/xiaoe-album/videos"
[xiaoe_album.slides]
output_dir = "./out/xiaoe-album/slides"
[wechat_album.browser]
profile = "/tmp/wechat-album-playwright-profile"
headed = true
[wechat_album.crawl]
output_dir = "./out/wechat-album"
[wechat_album.download]
image_concurrency = 2此文件只保存浏览器、输出、超时、并发、重试和资源处理等通用参数。完整可用字段见仓库中的默认 config/pulse_book.toml。
规则优先级固定为:
命令行 > 选中的私人合集规则 > config/pulse_book.toml > 内置默认值
复制示例后填写自己的值:
cp config/xiaoe_album.rules.example.toml config/xiaoe_album.rules.toml
cp config/wechat_album.rules.example.toml config/wechat_album.rules.tomlconfig/xiaoe_album.rules.toml 和 config/wechat_album.rules.toml 都已被根目录 .gitignore 忽略。它们统一使用 version = 1 和 [[collections]],并要求 name 唯一。
小鹅通规则可保存:
course_url、可选slides_url、课程密码;- 课件输入类型与标题跳过词;
- 只供旧站点使用的视频 URL 模板。
微信规则可保存:
input_url、biz、album_id;- 文章序号、标题和发布日期筛选;
- 正文选择器、排除选择器、文章顺序和分类顺序。
- 可选正文起止正则
content_start_pattern、content_end_pattern。
--collection NAME 显式选择优先。未传名称时,小鹅通按规范化 URL 自动匹配,微信按 biz + album_id 自动匹配。命令行标量和普通筛选列表覆盖规则;内置安全排除、合集排除和命令行 --exclude-selector 会去重追加。
规则摘要只把名称、计数和 SHA-256 digest 写入 manifest,不写入密码、URL、筛选词或 CSS 选择器。修改微信规则后,已成功归档的文章仍默认跳过;使用 --refresh 才会重新应用规则。分批筛选只控制本次网络请求,聚合页会累计保留所有已经成功或部分成功归档的文章链接。
小鹅通新默认路径:
out/xiaoe-album/
├── videos/
└── slides/
旧目录不会自动移动。微信继续使用:
out/wechat-album/<合集名>/
├── index.html
├── manifest.json
├── assets/
├── articles/
└── manifests/
微信文章图片按实际字节 SHA-256 去重,文章 HTML 使用相对路径引用合集资源,移动时请保留整个合集目录。
src/
├── pulse_book/ # 统一 CLI 与 config/pulse_book.toml 路由
├── xiaoe_album/ # 小鹅通视频、课件与 PDF
└── wechat_album/ # 微信合集、文章、资源与 manifest
pulse_book 可以导入两个业务包;两个业务包互不导入。它们共用同一 Python/uv/Playwright 发行环境,但代码、配置段、私人规则、profile 和输出保持独立。
uv sync
uv run pytest -q
uvx ruff check src tests
uv run python -m compileall -q src tests
uv build
git diff --checkConnection refused:确认 Chrome 以远程调试端口启动,并检查xiaoe_album.browser.cdp_url。- 找不到
.m3u8:确认账号可正常播放详情页,并适当增加下载等待时间。 - 微信访问验证:保持 headed 模式,在独立 profile 中手动完成验证后重新运行。
- 旧站点只有资源 ID:仅在私人小鹅通规则中配置 URL 模板,不要把站点专属模板放进通用配置。