C# 操作EDGAR SEC文件 C#如何自动下载和解析上市公司的财务报告

6次阅读

edgar下载需设合法user-agent(如”myapp contact@example.com”)、遵守速率限制、用httpclient配超时;解析master.idx须用正则匹配定宽字段并trim;.gz响应需手动解压,ASCII财报优先关键词定位,金额需清洗后解析。

C# 操作EDGAR SEC文件 C#如何自动下载和解析上市公司的财务报告

EDGAR 下载失败:不是网络问题,是 SEC 的反爬机制在拦你

SEC 的 EDGAR 系统明确禁止未声明 User-Agent 或高频请求的客户端。直接用 HttpClient 发 GET 请求,大概率拿到 403 或空响应,甚至被临时封 IP 段。

  • 必须设置合法的 User-Agent,格式为“机构名 + 邮箱”,例如 "MyApp contact@example.com",否则 httpstatusCode.Forbidden
  • 下载索引文件(如 master.idx)前,先访问 https://www.sec.gov/edgar/searchedgar/accessing-edgar-data.htm 确认当前速率限制(通常 ≤10 次/second)
  • 别用 WebClient —— 它不支持异步超时控制,容易卡死;改用 HttpClient 并显式设 Timeout = TimeSpan.FromSeconds(30)
  • 索引文件路径固定但带年份:比如 2024 年 Q2 是 https://www.sec.gov/Archives/edgar/full-index/2024/QTR2/master.idx,注意 URL 大小写敏感

解析 master.idx 文件:字段错位比编码问题更致命

master.idx 是定宽文本(不是 CSV),用 Split(' ') 会崩。它用多个空格分隔字段,且公司名里含空格——靠切分必然错位。

  • 正确做法:用正则 ^s*(?<cik>d{10})s+(?<company>[^ ](?:[^ ]|s(?! {2}))*?)s{2,}(?<form>[^s]+)s{2,}(?<date>d{8})s{2,}(?<url>.+)$</url></date> </form></company></cik> 逐行匹配
  • 注意 company 字段结尾可能有连续空格,url 开头可能有空格,务必 .Trim()
  • 只取 form"10-K""10-Q""8-K" 的行;"SC 13G""DEF 14A" 不是财务报告
  • 日期字段是 YYYYMMDD 字符串,别直接转 DateTime.Parse —— 有些老数据含无效值(如 "00000000"),先校验再转换

下载并解压 .gz 文件:.NET 6+ 要手动启用 GZipStream

EDGAR 返回的 .txt 文件实际是 gzip 压缩流,Content-Encoding 是 gzip,但 HttpClient 默认不自动解压(尤其 .NET 6+ 默认关了这个开关)。

  • 要么在 HttpClientHandler 中设 AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate
  • 要么手动读取响应流:using var gz = new GZipStream(responseStream, CompressionMode.Decompress),再用 StreamReader
  • 别用 response.Content.ReadAsStringAsync() 直接调 —— 如果没开自动解压,你会得到乱码二进制
  • 解压后内容是纯 ASCII,用 Encoding.ASCII 读最稳;UTF-8 可能因 bom 或特殊符号报错

从原始文本提取财务数据:别信“xml 就好解析”这种话

SEC 允许提交 HTML、ASCII、XML 三种格式,但多数公司仍用 ASCII(尤其是老财报)。XML 版本存在但结构松散:XBRL 标签嵌套深、命名空间多,且常混着 HTML 注释和脚本。

  • 优先查 content-type 响应头:是 text/html 就别硬 XML 解析;是 application/xhtml+xml 再上 XDocument
  • ASCII 报告里关键数据藏在固定位置:比如“CONSOLIDATED BALANCE SHEETS”下方第 5 行开始是资产项,靠关键词 + 行偏移比正则更可靠
  • 金额字段含逗号、括号(负数)、货币符号,用 decimal.TryParse(s.Replace(",", "").Replace("(", "-").Replace(")", ""), out var v) 更鲁棒
  • 别忽略 EX-101.INS 这类附件 —— 它才是 XBRL 实例文档,主文件只是封面;得从 HTML 中提取 <a href="https://www.php.cn/link/670fb2f689bec017e618ab7ec99c2308">...</a> 再单独下载

真正难的不是下载或解压,是同一份 10-K 在不同年份、不同公司间结构差异极大。一个正则撑不过三家,得准备 fallback 规则链,而不是指望一次写对。

text=ZqhQzanResources