HKEX 展示文件下载 (v2.1 合并版)
Overview
从港交所披露易检索新上市公司的公告,定位其"展示文件"(Documents on Display)栏目,下载除指定类型外的全部文件。本版合并了两个实战验证方案:
- JSON API 方案:
titleSearchServlet.do结构化检索 + 断点续传 + 指数退避 + 防封 - 本项目方案:
prefix.do快速 stockId + 用户命名规则 +dod/tc.html删除检测
提供可复用脚本 scripts/hkex_fetch_docs.py,含 4 个子命令一键完成全部任务。
触发场景
- 用户要求查询港交所主板新上市公司(名称+股份代号)
- 用户要求下载某家/某批新上市公司的展示文件
- 每周二/五定时查询"披露易-新上市-新上市资料"板块
- 用户给出股份代号(如 02261)要求下载其上市文件
- 批量下载港股公告(年报/中报/通函)
脚本用法
# 1. 搜索某股票的公告(默认最近2个月)
python scripts/hkex_fetch_docs.py search --stock 02261
# 2. 搜索指定日期范围
python scripts/hkex_fetch_docs.py search --stock 02261 --from 2026-07-01 --to 2026-08-05
# 3. 批量下载公告文档
python scripts/hkex_fetch_docs.py download --stock 02261 --from 2026-07-01 --to 2026-08-05 --output ./pdfs
# 4. 抓取新上市资料板块(主板/GEM)
python scripts/hkex_fetch_docs.py new-listings --board main
# 5. 下载展示文件(核心, 按用户命名规则+排除清单)
python scripts/hkex_fetch_docs.py display-files --stock 02261 --name 拿森智能科技 --output ./exhibits
# 6. 展示文件下载,自定义排除关键词
python scripts/hkex_fetch_docs.py display-files --stock 02261 --exclude "章程,会计师,财务报表,备考,服务合约" --output ./exhibits
依赖: pip install requests beautifulsoup4 opencc-python-reimplemented
展示文件命名格式(用户约定,必须遵守)
- 格式:
股份简称+股份代号+文件名称.pdf,中间不加任何分隔符(不用下划线) - 文件名称: 繁体转简体(opencc t2s),去除序号前缀(如 "a." / "A.")和换行
- 示例:
拿森智能科技02261重大合约.pdf、拿森智能科技02261中国知识产权法律意见书.pdf - 脚本已内置此逻辑;
--name指定股份简称,缺省用 HKEX 解析的简称
排除清单(文件名含以下关键词即排除,中英文均可)
| 类别 | 关键词(繁体/英文) | |------|-------------| | 组织章程细则 | 組織章程細則 / 公司組織章程 / Articles of Association | | 会计师报告 | 會計師報告 / Accountants' Report | | 经审计综合财务报表 | 經審計綜合財務報表 / 經審核綜合財務報表 / Audited Consolidated Financial | | 未经审计备考财务资料报告 | 未經審計備考財務 / 未經審核備考財務 / Unaudited Pro Forma | | 服务合约 | 服務合約 / Service Contract (含"服務合約及委任函") |
处理规则
- 展示文件被删除: 检索结果中"展示文件"链接指向
/dod/tc.html(页面显示"文件已被上市發行人刪除")→ 脚本自动终止该公司任务并输出 ⛔ 提示 - 已处理公司不重复下载: 02261 拿森智能科技、02523 永康控股、03308 中際旭創(被删除) 已处理过,跳过
技术原理(JSON API 流程)
Step 1: GET https://www1.hkexnews.hk/search/titlesearch.xhtml → 提取 ViewState
Step 2: POST 表单设置日期范围(from/to YYYYMMDD) → 必须,否则 API 返回空
j_idt10=j_idt10 j_idt10:loadMoreRange=100 javax.faces.ViewState=<step1> from=... to=...
Step 3: GET https://www1.hkexnews.hk/search/titleSearchServlet.do
?sortDir=0&sortByOptions=DateTime&category=0&market=SEHK&stockId=<内部ID>
&documentType=-1&fromDate=YYYYMMDD&toDate=YYYYMMDD&title=&searchType=0
&t1code=-2&t2Gcode=-2&t2code=-2&rowRange=5000&lang=ZH
Headers: X-Requested-With: XMLHttpRequest, Referer: 搜索页
- lang 参数: 必须用
ZH返回中文版展示文件链接和标题;用C返回英文版(文件名为英文,不满足命名规则) - stockId 获取: 优先
prefix.do轻量 API(?lang=ZH&type=A&name={代码}&market=SEHK&callback=callback,JSONP 返回 stockInfo[].stockId),兜底下载activestock_sehk_c.json全量 JSON - 展示文件页: 从检索结果中找标题含"展示文件"或"Documents on Display"的记录,其链接为
.htm页面,内含 A-K 项文档(PDF),每项独立链接
关键坑点(必读)
- 编码: HKEX 页面是 UTF-8 但响应头无 charset,requests 的
r.text会乱码 → 必须r.content.decode("utf-8")或传给 BeautifulSoup 自动探测 - 内部ID: 表单/API 用内部 stockId,不是股份代号(02261 → 1000312571)
- HEAD 请求: 对 .htm 文件返回 503,用 GET
- 限流/WAF: 并发探测或下载过快会触发限速(超时/空响应) → 务必串行,下载间隔 ≥3s,失败指数退避重试
- 大文件: >5MB 可能中断,脚本已内置断点续传(Range) + PDF 完整性校验
- 已处理公司: 02261、02523、03308(被删除) 已处理过,无需重复
Resources
scripts/hkex_fetch_docs.py— 一键下载脚本(4 子命令: search/download/new-listings/display-files)references/hkex_api_notes.md— HKEX 检索 API 完整技术要点(接口清单、参数、编码、限流等)
Scan to join WeChat group