使用 Python 3.9 通过 EDGAR 从 sec.gov 下载文件

Downloading files from sec.gov via EDGAR using Python 3.9

我是编码领域的新手,所以如果我误用术语或通常不知道我在说什么,请多多包涵。我正在做一个研究项目,我试图通过 EDGAR 从 sec.gov 中抓取 public 公司 10-Ks。我阅读了各种资源,观看了各种视频,但我发现以下参考与我的项目最相关,坦率地说,我很容易理解。我的代码的解释从第 194 页开始,代码从第 195 页开始。我首先尝试下载索引文件(下图),这将帮助我编写代码来专门获得 10-Ks。所以,我正处于项目的早期阶段。

这只是我正在使用的论文的参考。它目前在 SSRN 上,所以我意识到每个人都可能无法访问。我会上传 PDF,但我不认为这是一个选项。我列出这个纯粹是为了表明我有我正在做的事情的来源。如有需要,我可以提供截图。

Anand, V., Bochkay, K., Chychyla, R., & Leone, A. J. (2020)。在会计研究中使用 Python 进行文本分析。即将出版,会计基础和趋势。

索引文件示例:

目前,我有两个问题:我的代码没有按预期工作,我似乎被 sec.gov 阻止了。我将首先讨论前者,最后讨论后者。 当我在下面 运行 时,它应该在 down_direct 路径下载 2018 年和 2019 年的索引文件。但是,此代码仅抓取 2018 索引文件。

下面的log/IDLEshell结果显示了“成功”和不成功运行。不成功的运行让我觉得我被sec.gov屏蔽了。据我了解,某些网站会查找来自 urllib.request 的请求,并可能会自动对其进行筛选。然而,sec.gov 是研究人员友好的,只要你在下班后尝试下载 spaced 次尝试,这两种尝试我都做过(我昨晚从晚上 7 点到晚上 10 点一直在研究这个,并在两次尝试之间等待了 10 分钟左右). 所以,我的问题是

  1. 我应该如何调整我的代码以使其 运行 符合预期? (即,拉出 start_year 和 end_year 的所有 4 个季度)

  2. 我被sec.gov屏蔽了吗?如果是这样,我可以调整我的代码来解决这个问题吗?

    import os
    import urllib.request
    from pathlib import Path
    
    def get_index(start_year:int, end_year:int, down_direct:str):
    
        start_year = 2018
        end_year = 2019
        down_direct = r"C:/Users/Documents/Student Files/~Current Student/~RESEARCH/~First Summer Paper/Data/EDGAR/"
    
        print('Retrieving data')
    
        if not os.path.exists(down_direct):
            os.makedirs(down_direct)
    
        for year in range(start_year, end_year+1):
            for qtr in range(1,5):
    
                url = r"https://www.sec.gov/Archives/edgar/full-index/" + str(year) + '/' + 'QTR' + str(qtr) + '/master.idx' 
                dl_file = down_direct + 'master' + str(year) + str(qtr) + '.idx'
                urllib.request.urlretrieve(url, dl_file)
    
            print('Downloaded', dl_file, end = '\n')
            print('Data retrieved')
            return
    
    down_direct = os.path.join(Path.home(), 'edgar', 'indexfiles')
    
    get_index(2018, 2019, down_direct)
    

成功运行

Retrieving Data

Downloaded C:/Users/Documents/Student Files/~Current Student/~RESEARCH/~First Summer Paper/Data/EDGAR/master20184.idx

Data retrieved

不成功运行(为了space,我只包含错误行)

Retrieving Data

urllib.error.HTTPError: HTTP Error 403: Forbidden

我见过类似的 posts,人们建议将以下代码添加到代码中以解决此错误,但我太新手了,我真的不知道如何将其合并。感谢任何帮助,如果我需要用更多信息编辑我的 post,请告诉我。

req = Request(url, headers={'User-Agent': 'Mozilla/5.0'})

import requests
heads = {'Host': 'www.sec.gov', 'Connection': 'close',
         'Accept': 'application/json, text/javascript, */*; q=0.01', 'X-Requested-With': 'XMLHttpRequest',
         'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.163 Safari/537.36',
         }
def download(year):
    for qtr in range(1, 5):
        url = f"https://www.sec.gov/Archives/edgar/full-index/{year}/QTR{qtr}/master.idx"
        response = requests.get(url, headers=heads)
        print(url)
        response.raise_for_status()
        down_direct = r"C:/Users/Documents/Student Files/~Current Student/~RESEARCH/~First Summer Paper/Data/EDGAR/"

        with open(f'{down_direct}/master{year}QTR{qtr}.idx', 'wb') as f:
            f.write(response.content)

start_year =2018
end_year = 2019
for i in range(start_year,end_year+1):
    download(i)

您不需要下载 .idx 索引文件。相反,您可以使用 SEC API 以编程方式查询所有 10-K 文件。

Python 示例

query 接受 Lucene 查询语法 (see 1 min tutorial here) 来构建过滤条件,例如return 2019 年至今提交的所有 10-K 文件。您可以按行业、部门、公司代码和 +20 个其他参数进行过滤。

from sec_api import QueryApi

queryApi = QueryApi(api_key="YOUR_API_KEY")

query = {
  "query": { "query_string": { 
      "query": "formType:\"10-K\" AND filedAt:{2019-01-01 TO 2021-06-20}" 
    } },
  "from": "0",
  "size": "10",
  "sort": [{ "filedAt": { "order": "desc" } }]
}

filings = queryApi.get_filings(query)

print(filings)

您可以使用 render API to get the entire 10-K filing (or exhibits, eg XBRL). Or you can use the item extraction API 从标准化明文或 HTML 文件中获取特定项目。