返回 Skill 列表
extension
分类: 数据与分析无需 API Key

财报下载

把 A 股(上交所/深交所)与港股上市公司的定期报告(年报、半年报、季报)批量下载、按内容去重、归置到以公司命名的子文件夹,并统一命名为「公司:YYYY年X报告.pdf」。适用于用户说"下载 XX 的财报"、"批量抓定期报告 PDF"。支持增量下载(已下的不重复下)。

person作者: user_39a8b4abhubcommunity

财报批量下载与归置(A 股 + 港股)

把一家上市公司的全部定期报告 PDF 抓到本地、按 sha256 内容去重、剔除摘要/附件、按「公司:YYYY年X报告.pdf」统一命名并归置到 公司/ 子文件夹。

目标目录默认 ~/财报(用户主目录,跨平台),可用环境变量 REPORT_DIR 覆盖(例如 REPORT_DIR="E:\投资\财报" python ...)。

本 skill 的三个关键特性

  1. 位置 / 自动发现:把本 skill 文件夹直接放到 ~/.workbuddy/skills/financial-report-downloader\ 即可被 WorkBuddy 自动发现(重启会话生效)。
  2. 零手动映射
    • 深交所 orgId 自动从 szse_stock.json 按代码解析;
    • 港股 stockId 自动从港交所公开活跃股票列表 activestock_sehk_e.json 按代码查 i 字段(覆盖全部港股,无需任何手写映射表)。
  3. 增量下载(已下的不重复下):以「文件是否在盘上」为唯一真相——已落地的绝不重发请求;即使 _done.txt 记过某 URL,只要对应文件丢失就会自动重新下载补齐。重跑同一家公司时,只拉取新发布的报告。要强制全部重下,删掉 REPORT_DIR/.state/<代码>_done.txt 即可(港股还可删 _hkex_<代码>.json 缓存)。

何时使用

  • 用户要下载某只股票的全部业绩/定期报告 PDF。
  • 用户要把持仓公司的财报批量归档到本地目录。
  • 关键词:「财报」「定期报告」「年报」「半年报」「季报」「业绩报告」「下载公告」。

判定交易所(决定用哪个下载器)

| 代码特征 | 交易所 | 下载器 | 关键标识符 | |---|---|---|---| | 60xxxx(600/601/603/605)、688xxx(科创板) | 上交所 SSE | _download_stock.py | 6 位代码即可 | | 000xxx / 001xxx / 002xxx(主板+中小板)、30xxxx(创业板) | 深交所 SZSE | _download_cninfo.py | orgId(按代码自动解析) | | 0xxxx(5 位,如 00700) | 港股 HKEX | _download_hkex.py | stockId(按代码自动解析) |

央企/银行很多在 SSE,白酒/医药/传媒很多在 SZSE;不确定时按代码前缀判断,必要时先问用户。

运行环境(Python)

  • 脚本仅需 Python 3.10+ 标准库(除可选 pypdf 外无第三方依赖),任意 Python 3.10+ 均可运行
  • 推荐用 WorkBuddy 提供的受管运行时(隔离、干净):路径形如
    • Windows:C:\Users\<你>\.workbuddy\binaries\python\versions\<版本>\python.exe
    • 在 WorkBuddy 设置/终端里可查到确切路径;下文示例中的 PY="<你的Python路径>" 即指它。
  • 若用系统 Python,建议先建虚拟环境再装 pypdf(见下),避免污染全局环境。

可选的 pypdf(仅 organize_rename.py 用到)

pypdf 只用于「文件名无年份时读 PDF 首页年份」的兜底;缺失时脚本自动降级,其余功能不受影响。需要该功能时安装:

# 方式 A:用 WorkBuddy 受管运行时建 venv 并装(推荐,隔离)
<你的Python路径> -m venv <你的Python路径同级>/envs/default
<你的Python路径同级>/envs/default/Scripts/pip install -r requirements.txt

# 方式 B:用系统 python
python -m venv .venv && .venv/Scripts/pip install -r requirements.txt

若未安装,运行 organize_rename.py 时仅会跳过 PDF 年份兜底,并在 stderr 提示安装命令。

工作流程(每家公司)

Step 1 — 下载(增量,已下的自动跳过)

清单文件放哪:统一传绝对路径 REPORT_DIR/.state/_<拼音简称>_manifest.txt(如 <REPORT_DIR>/.state/_maotai_manifest.txt)。不要放在 REPORT_DIR 根目录——根目录只应有公司子文件夹,混入 txt 会干扰后续核查。

上交所(SSE)

# PY 用任意 Python 3.10+ 即可;推荐用 WorkBuddy 受管运行时(路径见上方「运行环境」)。
PY="<你的Python路径>"
"$PY" scripts/_download_stock.py <6位代码> <公司名> "<标题前缀|可多个用|分隔>" <清单路径.txt>
# 例:
"$PY" scripts/_download_stock.py 600519 贵州茅台 "贵州茅台" _maotai_manifest.txt
"$PY" scripts/_download_stock.py 601677 明泰铝业 "明泰铝业" _mingtai_manifest.txt
"$PY" scripts/_download_stock.py 600690 海尔智家 "海尔智家股份有限公司|海尔智家" _haier_manifest.txt
  • 标题前缀参数保留兼容(旧命令仍可用),但现已不参与命名:报告类型与年份直接从标题+披露日推导为规范名 公司:YYYY年X报告.pdf,因此「海尔智家股份有限公司2023年年度报告」之类旧全称也能正确归并。多个候选用 | 分隔,可留空或仍填公司名。
  • 文件直接落到 REPORT_DIR/<公司>/ 子文件夹,命名即为规范名,下载时按内容 sha256 去重。
  • 已下载过的会自动跳过(见 SUMMARY 的 already_skipped 计数);done 记录过但文件丢失也会自动重新下载补齐。

深交所(SZSE,经巨潮资讯 cninfo)

"$PY" scripts/_download_cninfo.py <6位代码> <公司名> <清单路径.txt>
# 例:
"$PY" scripts/_download_cninfo.py 000596 古井贡酒 _gujing_manifest.txt
"$PY" scripts/_download_cninfo.py 002027 分众传媒 _fenzhong_manifest.txt
  • orgId 脚本自动从 http://www.cninfo.com.cn/new/data/szse_stock.json 按代码解析(覆盖主板/中小板/创业板),无需手动传。

港股(HKEXnews)

"$PY" scripts/_download_hkex.py <5位代码> <公司名> <清单路径.txt>
# 例:
"$PY" scripts/_download_hkex.py 00700 腾讯控股 _tencent_manifest.txt
  • stockId 脚本自动解析:从 https://www1.hkexnews.hk/ncms/script/eds/activestock_sehk_e.json 按代码查 i 字段(首次会缓存到 REPORT_DIR/.state/activestock_sehk.json)。无需任何手动映射
  • 港股下载时直接归置到 REPORT_DIR/<公司>/ 子文件夹,并统一命名为 <公司>:<年份>年<类型>.pdf

Step 2 — 归置 + 统一命名 + 去重(上交所/深交所必须;港股可选)

把根目录里 <公司>:*.pdf 移入 REPORT_DIR/<公司>/,回收摘要文件,按文件名/PDF 正文年份重命名为统一格式,按内容去重并送回收站。

"$PY" scripts/organize_rename.py <公司名>
# 例:
"$PY" scripts/organize_rename.py 贵州茅台
  • 依赖 pypdf(仅用于「文件名无年份时读 PDF 首页年份」的兜底)。若缺失,脚本自动跳过 PDF 年份兜底、不影响其余重命名;安装方式见上方「运行环境 → 可选的 pypdf」。
  • 命名规则:<公司>:YYYY年(半年度报告|年度报告|第一季度报告|第三季度报告)[(修订)|(正文)|(全文)].pdf
  • 年报:文件名年份 = 披露年 − 1(因年报在次年披露);半年报/季报 = 同年。脚本已处理。
  • 旧称兼容:「中期报告」→ 半年度报告;中文数字年份「二〇〇六」可识别。

Step 3(可选)— 清理残留附件

若根目录还混有非定期报告(英文版、ESG、审计报告、更正公告等),送回收站:

"$PY" scripts/cleanup_annex.py <公司名>

移植到其他机器

本 skill 代码零机器绑定:无硬编码绝对路径(默认目录 ~/财报 可用 REPORT_DIR 环境变量覆盖),除可选 pypdf 外无第三方依赖,路径一律 os.path.join、中文文件名正常(UTF-8)。拷贝即用。

  1. 拷 skill 本体:把 financial-report-downloader/ 文件夹整体复制到目标机器的 ~/.workbuddy/skills/ 下,重启 WorkBuddy 即被发现。
  2. (可选)拷已有归档:把本地归档目录(含其内的 .state\)一并拷过去可保留增量状态,实现零重下;若目标路径不同,用 REPORT_DIR 环境变量指向新路径即可(如 REPORT_DIR="D:\财报" <PY> scripts/_download_stock.py ...)。只拷 skill 不拷归档也行,只是首跑会全量重新下载(无害,仅耗时)。
  3. Python 环境:见「运行环境」一节。核心下载无需任何安装;若要 organize_rename 的 PDF 年份兜底,按该节装 pypdf
  4. 网络:脚本直连上交所 / 巨潮资讯 / 港交所接口,目标机器需能访问这些站点(通常需大陆网络环境)。
  5. 跨平台:Windows / macOS / Linux 均可运行;公司名、文件名中的中文均正常。

输出

  • 每家公司一个子文件夹:REPORT_DIR/<公司>/<公司>:YYYY年X报告.pdf
  • 一份 <清单>.txt:每行 文件名 \t 大小 \t 披露日 \t 原标题,含 FAIL / dup(...) / already 标记,便于核查漏网。
  • 终端打印 SUMMARY:新增/已下跳过/去重/跳过非定期/失败 计数。

关键坑(务必遵守,否则会下错/命名错)

  1. 上交所 WAFstatic.sse.com.cn 直链会返回 acw_sc__v2 JS 挑战页(不是 PDF)。脚本已内置逆向算法(固定 mask + 40 项 posList 置换异或),无需人工干预。

  2. 年报披露年陷阱:SSE 早期报告文件名常带「披露日」后缀(如 年报_2015-03-25.pdf 实为 2014 年报),文件名年份比报告年份大 1。归置时以文件名 YYYY年 或 PDF 正文年份为准,不要信披露日后缀。

  3. 只留定期报告:下载器已用 PERIODIC_RE / EXCLUDE_RE 过滤,剔除英文版、ESG、审计、专项说明、独董述职、更正公告等附件。若仍有漏网,用 Step 3 清理。

  4. 借壳/更名:深交所借壳上市的公司,上市前的公告属于原壳公司。如分众传媒(002027)2015 年借壳七喜控股,2015 三季报及以前约 59 份实为七喜控股,应送回收站。

  5. cninfo 过滤:必须同时传 stock JSON 和 secid=orgId 双参数,否则会漏掉部分公告。

  6. 港股业绩公布 ≠ 定期报告:腾讯等港股有「中期/全年/九个月/三个月业绩公布」,与中期报告/年报重复,脚本已剔除重复项,只保留年报、中期报告、一/三季度业绩公告。

  7. 港股年报命名不只「年報」二字:部分港股(如阿里巴巴 09988、京东等)年报标题用财年命名「2020財政年度報告」「2023財務年度報告」,不含「年報」。脚本 classify() 已同时识别「年報 / 財政年度報告 / 財務年度報告」(且先判「中期報告」,避免「2024財務年度中期報告」被误判为年报)。实测 2026-08-20:阿里 7 份年报(2020~2026 财年)补齐,含 28~40MB 大文件,下载耗时较长(单份 30s+),Bash 超时误报 Exit 1 时检查 .pdf 是否已落盘即可。此外,阿里式季报标题用「YYYY年M月底止季度業績公告」(如「2026年六月底止季度業績公告」即 FY2027 Q1),classify() 已支持「業績公告」+「月底止季度」格式(同时兼容腾讯式「X個月業績公佈」),并按阿里财年(止3/31)做年度映射(3月底→当年FY;6/9/12月底→次年FY),保留一/三季度业绩公告、跳过与中报/年报重叠的二/四季度。实测 2026-08-21:阿里 FY2027 Q1 等 13 份季报补齐。

  8. 增量以「文件是否在盘上」为唯一真相:脚本每轮先扫 REPORT_DIR 根目录 + REPORT_DIR/<公司名>/ 下的同名 PDF;盘上已有的绝对不重发请求。REPORT_DIR/.state/<代码>_done.txt 仅作已处理 URL 的辅助记录——即使 done 里有某 URL,只要对应文件丢失/被删,下一轮就会自动重新下载补齐(实测 2026-08-20:茅台 2025 年报文件丢失,done 记着却补不回来,已修复为文件在盘才跳过)。需要强制全量重下时,删该 done 文件(港股再删 _hkex_<代码>.json)即可。

  9. 别改公司文件夹名:改名会让扫盘(第②道闸)失效;若同时 _done.txt 也被删,就会全量重下一遍(实测 2026-08-20:茅台因此重下 88 份)。下载前先确认子文件夹名与传入的 <公司名> 完全一致;发现重复目录时先做内容 sha256 比对,再决定处置,不要直接删。

  10. SSE 窗口已覆盖 2000 年起:查询窗口从 2000-01-01 开始(每段 ≤3 年),上市初期(2001~2004)的年报/季报/半年报在 SSE 电子档案里都能查到。早期公告标题常无年份(如「贵州茅台年报」),报告年份按披露日推断(年报披露年 − 1;如 2002-04-17 披露 → 2001 年报)。实测 2026-08-20:为茅台补下 2001~2004 年报及 2005 年一/三季报、半年报共 16 份,增量机制正确跳过已有 88 份。

  11. 命名保留版本标记(修订/正文/全文):同一报告在 SSE 可能有多个版本(如「贵州茅台年报(修订版)」「...季度报告正文」),下载器 canon_qual 会把版本保留到文件名((修订)/(正文)/(全文)),避免同一年份同类型退化成 (1)(2) 序号。实测 2026-08-20:茅台 2007/2010 年报(修订版)、2020 一/三季报与 2021 一季报(正文版)均正确区分。另:脚本会自动创建 <公司>/ 子文件夹,REPORT_DIR 指向全新目录也可直接全量下载。

  12. cninfo 抓取缓存(真实已实现)_download_cninfo.py 首次抓全量公告后写 REPORT_DIR/.state/_cninfo_<代码>.json,重跑直接读缓存、跳过网络抓取。实测五粮液 1594 条:首跑 ~53s → 缓存命中 ~11s(提速 ~5×)。删该 json 即强制全量刷新(与港股 _hkex_<代码>.json 同理)。

  13. 更新前/更新后 命名归一(真实已实现)organize_rename.py 对成对报告——「更新后/更正后」= 规范名(权威/最新版,无后缀),「更新前/修订前」标 (修订前);仅一份时不加后缀;不再退化成 (2)。五粮液 2025 年半年度/一/三季度报告三对已按此归置(报告.pdf + 报告(修订前).pdf)。

  14. 归置幂等性(真实已实现)compute_target 识别并保留文件已有的 (n) 后缀(如 2022 年同目标两份不同内容 → 规范名 + (2)),重跑不再 (2)→(3) 递增;(修订前)/(修订)/(正文)/(全文) 均作为稳定后缀识别,重命名完全幂等(五粮液连续两次重跑均 renamed=0)。

详见 references/identifiers.md