# 网页文章离线下载 使用 uv 管理 Python 环境和依赖(Python 3.10 或更新版本)。将 `download_article.py` 与 `requirements.txt` 放在同一个目录,并确保已安装 uv。 ## 安装与运行 在这两个文件所在目录打开终端,执行: ```sh uv run --no-project --python 3.12 --with-requirements requirements.txt python download_article.py 'https://mp.weixin.qq.com/s/Jcu2J5YlaMdxbAUgLMd56A' ``` uv 会自动准备 Python 3.12 和所需依赖,无需手动创建或激活虚拟环境。后续运行相同命令即可复用缓存。依赖继续通过 `requirements.txt` 管理,无需创建 `pyproject.toml`。 默认在**运行命令时的当前目录**创建文章目录,也可以用 `-o /你的/保存目录` 指定父目录。 ```text 当前目录/ └── 文章标题/ ├── 文章标题.md ├── image001.png └── image002.jpg ``` 图片后缀按实际文件内容判断;同一地址的图片只下载一次。正文中的图片引用使用相对路径,离线阅读时请保留整个目录。支持微信的延迟加载图片和行内 CSS 背景图,保留常见的标题、段落、列表、链接、表格等 Markdown 格式;公众号的复杂视觉排版不会原样复刻。 Markdown 开头不添加原文链接和作者/公众号信息,文章末尾统一追加 `来源:公众号作者,如有侵权,请联系删除。`。无法获取公众号作者时使用“未知作者”。接口返回的 `source_url` 仍保留,方便调用方追踪来源。 文件名中系统不允许的字符会替换为 `_`,过长标题会截短。已有同名目录时创建 `文章标题 (2)/文章标题 (2).md`,不会覆盖已有内容。 ## 其他任务通过命令行调用 ```sh uv run --no-project --python 3.12 --with-requirements requirements.txt python download_article.py 'https://mp.weixin.qq.com/s/Jcu2J5YlaMdxbAUgLMd56A' --json ``` 也可以从标准输入读取单个 JSON 请求: ```sh printf '%s' '{"url":"https://mp.weixin.qq.com/s/Jcu2J5YlaMdxbAUgLMd56A","output_root":".","timeout":30,"allow_missing_images":false}' | uv run --no-project --python 3.12 --with-requirements requirements.txt python download_article.py --stdin-json ``` 每次进程处理一个网址。JSON 模式下,标准输出只有一个 JSON 对象,路径均为绝对路径。调用方应解析 JSON,不要依赖错误消息的具体文字。 成功返回退出码 `0`: ```json { "ok": true, "title": "文章标题", "source_url": "https://example.com/article", "directory": "/完整路径/文章标题", "markdown": "/完整路径/文章标题/文章标题.md", "images": ["/完整路径/文章标题/image001.png"], "warnings": [] } ``` 失败返回退出码 `1`: ```json {"ok": false, "error": "错误说明", "error_type": "ArticleDownloadError"} ``` 命令行参数格式错误由 argparse 返回退出码 `2`,说明写入标准错误。`--stdin-json` 使用 JSON 中的参数,不使用其他命令行下载选项。 ## 其他 Python 任务直接调用 将脚本放入调用方的 Python 模块搜索路径,并在调用方的 uv 环境中安装本脚本 `requirements.txt` 所列依赖后: ```python from download_article import save_article result = save_article( url="https://mp.weixin.qq.com/s/Jcu2J5YlaMdxbAUgLMd56A", output_root=".", timeout=30, allow_missing_images=False, ) saved_directory = result.directory # 已保存文件所在目录(绝对路径字符串) print(saved_directory) # 完整结果可调用 result.to_dict() ``` 函数失败时抛出异常,调用方可自行捕获。默认任何图片失败都会终止保存并清理半成品。若只希望尽量保存正文,可传 `allow_missing_images=True` 或命令行添加 `--allow-missing-images`,失败图片会替换为文字提示,详情写入 `warnings`。 微信可能返回验证、登录或失效页面,脚本会报告未找到正文,不会绕过访问限制。普通网页使用 article/main/body 提取,不适用于必须执行 JavaScript 才出现正文的页面。原文中的外链仍需联网,文章文字及成功下载的图片可离线查看。 如果接口对外提供服务,请由调用方限制网址及重定向目的地,只允许可信站点;此脚本本身允许访问运行机器能连接的 HTTP 地址。