使用R edgar包读取SEC Edgar库2000年左右旧13F格式txt文件问题
edgar包失效原因
edgar包仅兼容2012年之后SEC推出的标准化XML格式13F归档文件,2000年前后的旧归档为纯文本固定宽度格式,包内置的归档匹配、解析逻辑均不支持,因此会出现卡顿、无匹配结果的报错。
手动爬取+解析方案
你可以直接通过R的HTTP请求包获取文件内容,再按固定宽度规则解析为结构化数据,步骤如下:
1. 依赖包安装加载
install.packages(c("httr", "stringr", "dplyr")) library(httr) library(stringr) library(dplyr)
2. 发起请求获取文件内容
注意SEC要求所有请求必须携带真实可用的邮箱作为User-Agent,否则会被限流或拒绝访问:
# 替换为你自己的真实邮箱 ua <- "你的真实邮箱地址" # 替换为对应13F归档的txt文件地址 file_url <- "你要爬取的13F txt文件地址" res <- GET(file_url, user_agent(ua)) raw_text <- content(res, as = "text", encoding = "latin1")
3. 定位持仓数据段
旧13F的持仓表有固定表头特征,可通过关键词匹配定位起止位置:
# 按行拆分文本 lines <- str_split(raw_text, "\\n")[[1]] # 定位表头行:匹配CUSIP、PRN AMT、发行人名称等关键词同时出现的行 header_line <- which(str_detect(lines, "CUSIP.*PRN AMT|Name of Issuer.*Title of Class"))[1] # 定位表结束行:匹配签名段、总市值统计等后续章节关键词 end_line <- which(str_detect(lines, "SIGNATURE|Total.*Value"))[1] - 1 # 提取持仓数据行并去除空行 holding_lines <- lines[header_line:end_line] %>% str_squish() %>% .[. != ""]
4. 按固定宽度解析为数据框
2000年前后的13F均采用固定宽度排版,只需匹配对应列宽即可解析:
# 2000年左右13F的通用列宽,可根据你拿到的文件微调数值 col_widths <- c(30, 20, 12, 10, 10, 8, 15, 10, 10, 10) # 对应列名,可按需调整 col_names <- c("发行人名称", "证券类型", "CUSIP码", "持仓市值(千美元)", "持仓数量", "持仓类型", "决策权", "sole投票权", "shared投票权", "none投票权") # 解析文本为数据框 holdings_df <- read.fwf( textConnection(holding_lines[-1]), # 跳过第一行表头 widths = col_widths, col.names = col_names, stringsAsFactors = FALSE, strip.white = TRUE ) # 清理数值列格式 holdings_df <- holdings_df %>% mutate( 持仓市值(千美元) = as.numeric(持仓市值(千美元)), 持仓数量 = as.numeric(持仓数量), sole投票权 = as.numeric(sole投票权), shared投票权 = as.numeric(shared投票权), none投票权 = as.numeric(none投票权) )
批量处理思路
如果需要爬取同一CIK下的所有旧13F归档,可先爬取CIK对应的归档列表页,提取所有13F-HR的txt文件地址,循环执行上述解析逻辑即可。
注意事项
- 不同年份的旧13F列宽可能存在细微差异,可根据实际文件调整
col_widths参数,保证每列内容完整截取即可 - 部分发行人名称过长的行可能会被拆分为两行,可增加前置逻辑:如果当前行开头没有符合规则的CUSIP码,就将内容合并到上一行
- 旧13F中不会直接标注股票代码,可提前准备CUSIP与股票代码的映射表,匹配
CUSIP码列即可获得对应股票代码
内容的提问来源于stack exchange,提问作者ML33M
相关产品推荐
相关产品推荐

