首页 > 解决方案 > 用 python 从(Edgar 13-F 文件)TXT(2013 年之前)中提取控股表

问题描述

我正在从 EDGAR 上的 13-F 表格中提取一份持股表。2013 年之前的馆藏以 txt 文件的形式提供(参见示例)。我的目标是一个 pd.DataFrame,其形状与 txt 文件中的“Form 13F 信息表”相同(10 列,每行在单独的行中)。

我曾尝试使用 BeautifulSoup,它将表格转换为标签对象,但我无法弄清楚如何将其格式化以进入数据框,如上所述。

这是我的代码尝试:

soup2 = BeautifulSoup(requests.get(filing_url_13f).content, 'lxml')
holdings = soup2.find_all('table')

#This is my attempt to turn the content into a list:
lixt=[]
for x in soup2.find_all(['c','c','c','c','c','c','c','c','c']  ):
    for line in x:
        lixt.append(line)
x=lixt[1]
l=[]
for string in x.strings:
    l.append(repr(string))
el=l[7]

当el返回以下内容时,这就是我卡住的地方。我不能用 \n 来拆分它,因为公司名称中经常有 \n (AMERICAN\n EXPRESS CO)。

\ namerican \ n Express CO com 025816109 112,209 1,952,142共享定义4 1,952,142-- \ \ Namerican \ n Express CO CO com 025816109 9909 990,116 990,116 17,225,400共享4,5 17,317,17,17,119,48 \ n 8,9,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4 n n n v n n \ n.4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4 n n n n n n n v , 7 839,832 - -\nAMERICAN\n EXPRESS CO COM 025816109 111,689 1,943,100 Shared-Defined 4, 8, 11 1,943,100 - -\nAMERICAN\n EXPRESS CO COM 025816109 459,532 7,994,634 Shared-Defined 4, 10 7,994,634 - -\nAMERICAN\n EXPRESS CO COM 025816109 6,912,308 120,255,879 共享定义 4, 11 120,255,879 - -\n美国\n EXPRESS CO COM 025816109 80,456 1,399,713 共享定义 4, 13 1,399,713 - -\nARCHER DANIELS\n Midland CO COM 039483102 163,151 5,956,600 共享定义 4, 5, 5, 95 纽约银行\n CORP COM 064058100 206,661 8,041,300 共享定义的 4 8,041,300 - -\n纽约梅隆银行\n 纽约梅隆银行\n CORP COM 064058100 46,104 1,793,915 共享定义的 2, 4, 11 1,793,915 纽约梅隆银行 -\n\n CORP COM 064058100 251,827 9,798,700 共享定义 4, 8, 11 9,798,700 - -\nCOCA COLA CO COM 191216100 29,000 800,000 共享定义的 4 800,000 - -\n

我将非常感谢任何建议。

标签: parsingbeautifulsouppython-requestsedgar

解决方案


是的,这些旧的 EDGAR 文件很糟糕(并不是说新的文件要好得多)。这个特别糟糕,因为较长的输入行被分成单独的行以使它们适合页面。

所以以下应该让你足够接近你想要的:

import pandas as pd
from bs4 import BeautifulSoup as bs
import requests

req = requests.get('https://www.sec.gov/Archives/edgar/data/1067983/000119312512470800/d434976d13fhr.txt')

#next is a helper function to put back those longer entires
def lst_bunch(l,lenth=4):
    i=0
    while i < len(l):
        if len(l[i])<lenth:
            l[i] += l.pop(i+1)
        i += 1
    for item in l:
        if len(item)<lenth:
            lst_bunch(l,lenth)
    else:
        return l

tabs = req.text.replace('<TABLE>','xxx<TABLE>').split('xxx')
for tab in tabs[2:]:
    soup = bs(tab,'lxml')
    table = soup.select_one('table')
    lines = table.text.splitlines()
    lst_bunch(lines,30)
    for line in lines:
        print(line.strip())

Output:
Name of Issuer  Class  CUSIP     (In Thousands)   Amount      Discretion   Managers     Sole      Shared  None
AMERICAN  EXPRESS CO    COM    025816109      110,999     1,952,142 Shared-Defined 4           1,952,142       -   -
AMERICAN  EXPRESS CO    COM    025816109      979,436    17,225,400 Shared-Defined 4, 5       17,225,400       -   -

等等


推荐阅读