首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >下载python中SEC EDGAR的所有10k文件

下载python中SEC EDGAR的所有10k文件
EN

Stack Overflow用户
提问于 2022-10-27 16:19:55
回答 1查看 224关注 0票数 1

我目前已设法刮刮所有的文件,为一个特定的代码。“‘AAPL”和每一种类型的文件及其链接都在一个庞大的字典中呈现。我只想要那些‘类型’:‘10-k’的链接,并下载所有的文件作为HTML文件。已经尝试循环遍历字典并附加到列表中,但仍然得到所有类型。

代码语言:javascript
复制
from urllib.request import urlopen
import certifi
import json

response = urlopen("https://financialmodelingprep.com/api/v3/sec_filings/AMZN?page=0&apikey=aa478b6f376879bc58349bd2a6f9d5eb", cafile=certifi.where())
data = response.read().decode("utf-8")
print (json.loads(data))
list = []

for p_id in data:
    if p_id['type'] == '10-K':
        list.append((p_id['finalLink']))

print(list)

#print(get_jsonparsed_data(url))

此代码的结果如下所示,当只需要10-k时,将输出每个类型:

代码语言:javascript
复制
{'symbol': 'AMZN', 'fillingDate': '2014-01-31 00:00:00', 'acceptedDate': '2014-01-30 21:52:38', 'cik': '0001018724', 'type': '10-K', 'link': 'https://www.sec.gov/Archives/edgar/data/1018724/000101872414000006/0001018724-14-000006-index.htm', 'finalLink': 'https://www.sec.gov/Archives/edgar/data/1018724/000101872414000006/amzn-20131231x10k.htm'}, {'symbol': 'AMZN', 'fillingDate': '2014-01-31 00:00:00', 'acceptedDate': '2014-01-30 21:49:36', 'cik': '0001018724', 'type': 'SC 13G/A', 'link': 'https://www.sec.gov/Archives/edgar/data/1018724/000119312514029210/0001193125-14-029210-index.htm', 'finalLink': 'https://www.sec.gov/Archives/edgar/data/1018724/000119312514029210/d659830dsc13ga.htm'}, {'symbol': 'AMZN', 'fillingDate': '2014-01-30 00:00:00', 'acceptedDate': '2014-01-30 16:20:30', 'cik': '0001018724', 'type': '8-K', 'link': 

如果链接被附加到列表中,理想情况下,我希望立即下载所有链接并保存在文件夹中。以前使用过sec_edgar_downloader包,但是它会在各自的年度文件夹中下载所有的10k文件。

EN

回答 1

Stack Overflow用户

发布于 2022-10-28 19:28:05

与其在Python代码中过滤客户端所有SEC文件的列表,不如在服务器端直接过滤它们。考虑到你的最终目标是在很多年内下载成千上万的10-K文件,而不仅仅是苹果的10-K文件,你可以通过在服务器端进行过滤来节省大量的时间。

只有FYI,还有其他10-K变体,即10-KT,10 K,10 KT 405,10 K 40,10-K405.我不确定你是否意识到它们,并想忽略它们,或者你是否不知道,但也想下载其他变体。

让我们运行一个成熟的10-K文件下载程序的实现。我们的应用程序将分为两个组件:

  1. 是我们应用程序的第一个组件,它在2010年到2022年期间在EDGAR文件上找到了所有10-K文件的URL。你可以根据你的需要调整时间范围。我们还考虑了其他10-K变体,即10-KT、10 KT、10 KT 405、10 KT 40、10-K 405和所有修改/更改的文件,例如10-K/A。一旦生成了所有URL的完整列表,我们将把列表保存到硬盘上的文件中。
  2. 第二个组件从文件中读取URL,并下载/保存所有文件。我们使用SEC-API包的呈现API并行下载多达20个文件,并使用Python的多处理包来加快下载过程。

1.生成10-K网址的列表

Query是一个搜索接口,允许我们通过任何文件元数据参数在整个EDGAR数据库中搜索和查找SEC文件。例如,我们可以使用滴答键和表单类型搜索(formType:"10-K" AND ticker:AAPL)找到苹果提交的所有10-K文件,或者使用布尔和括号运算符构建更复杂的搜索表达式。

query返回与搜索查询相匹配的SEC文件的元数据,包括URL到文件本身。

Query包的响应表示一个字典(简短: dict),其中包含两个键:totalfilingstotal的值本身就是一个小块,它告诉我们,除其他外,总共有多少文件与我们的搜索查询匹配。filings的值是一个dicts列表,其中每个dict表示匹配文件的所有元数据。

10-K文件的URL是每个归档数据集中linkToFilingDetails键的值,例如:https://www.sec.gov/Archives/edgar/data/1318605/000119312514069681/d668062d10k.htm

为了让我们生成一个完整的10-KURL列表,我们只需遍历所有归档数据集,读取linkToFilingDetails值并将该URL写入一个本地文件。

需要一些时间来下载和保存所有的URL。计划至少30分钟不间断地运行您的应用程序。

URL下载器在每次处理迭代时将一个新的URL附加到日志文件filing_urls.txt。如果您不小心关闭了应用程序,您可以从最近处理的一年开始,而不必再下载已经处理的URL。

如果您想一次生成所有URL,请取消代码中下面两行的注释。我故意取消注释,以提供整个代码的快速运行示例,而不必等待30+分钟才能看到结果。for year in range(2022, 2009, -1): for from_batch in range(0, 9800, 200):

代码语言:javascript
复制
from sec_api import QueryApi

queryApi = QueryApi(api_key="YOUR_API_KEY")

"""
On each search request, the PLACEHOLDER in the base_query is replaced 
with our form type filter and with a date range filter.
"""
base_query = {
  "query": { 
      "query_string": { 
          "query": "PLACEHOLDER", # this will be set during runtime 
          "time_zone": "America/New_York"
      } 
  },
  "from": "0",
  "size": "200", # dont change this
  # sort returned filings by the filedAt key/value
  "sort": [{ "filedAt": { "order": "desc" } }]
}

# open the file we use to store the filing URLs
log_file = open("filing_urls.txt", "a")

# start with filings filed in 2022, then 2020, 2019, ... up to 2010
# uncomment next line to fetch all filings filed from 2022-2010
# for year in range(2022, 2009, -1):
for year in range(2022, 2020, -1):
  print("Starting download for year {year}".format(year=year))
  
  # a single search universe is represented as a month of the given year
  for month in range(1, 13, 1):
    # get 10-Q and 10-Q/A filings filed in year and month
    # resulting query example: "formType:\"10-Q\" AND filedAt:[2021-01-01 TO 2021-01-31]"
    universe_query = \
        "formType:(\"10-K\", \"10-KT\", \"10KSB\", \"10KT405\", \"10KSB40\", \"10-K405\") AND " + \
        "filedAt:[{year}-{month:02d}-01 TO {year}-{month:02d}-31]" \
        .format(year=year, month=month)
  
    # set new query universe for year-month combination
    base_query["query"]["query_string"]["query"] = universe_query;

    # paginate through results by increasing "from" parameter 
    # until we don't find any matches anymore
    # uncomment next line to fetch all 10,000 filings
    # for from_batch in range(0, 9800, 200): 
    for from_batch in range(0, 400, 200):
      # set new "from" starting position of search 
      base_query["from"] = from_batch;

      response = queryApi.get_filings(base_query)

      # no more filings in search universe
      if len(response["filings"]) == 0:
        break;

      # for each filing, only save the URL pointing to the filing itself 
      # and ignore all other data. 
      # the URL is set in the dict key "linkToFilingDetails"
      urls_list = list(map(lambda x: x["linkToFilingDetails"], response["filings"]))

      # transform list of URLs into one string by joining all list elements
      # and add a new-line character between each element.
      urls_string = "\n".join(urls_list) + "\n"
      
      log_file.write(urls_string)

    print("Filing URLs downloaded for {year}-{month:02d}".format(year=year, month=month))

log_file.close()

print("All URLs downloaded")

运行代码之后,您应该会看到如下内容:

2.从证券交易委员会下载所有10-k

文件下载程序的第二个组件将日志文件filing_urls.txt中的所有10-KURL加载到内存中,并将20个文件并行下载到文件夹filings中。所有文件都下载到同一个文件夹中。

我们使用SEC-API Python包的呈现API接口通过提供其URL下载文件。呈现API允许我们并行下载多达40 SEC文件每秒。但是,我们没有利用API的全部带宽,因为否则很可能导致内存溢出异常(考虑到一些文件是400+ MB大的)。

download_filing函数从URL下载文件,使用URL的最后两个部分生成文件名,并将下载的文件保存到filings文件夹中。

download_all_filings是我们应用程序的核心和灵魂。在这里,Python内置的multiprocessing.Pool方法允许我们将一个函数并行地应用于一个值列表。通过这种方式,我们可以并行地将download_filing函数应用于URL列表的值。

例如,将number_of_processes设置为4将导致4个download_filing函数并行运行,其中每个函数处理一个URL。下载完成后,multiprocessing.Pool从URL列表中获取下一个URL,并使用新URL调用download_filing

我们使用了40个URL (urls = load_urls()[1:40])来快速测试代码,而不需要等待几个小时才能完成下载。取消注释处理所有URL的下一行:urls = load_urls()

代码语言:javascript
复制
import os
import multiprocessing
from sec_api import RenderApi

renderApi = RenderApi(api_key="YOUR_API_KEY")

# download filing and save to "filings" folder
def download_filing(url):
  try:
    filing = renderApi.get_filing(url)
    # file_name example: 000156459019027952-msft-10k_20190630.htm
    file_name = url.split("/")[-2] + "-" + url.split("/")[-1] 
    download_to = "./filings/" + file_name
    with open(download_to, "w") as f:
      f.write(filing)
  except Exception as e:
    print("Problem with {url}".format(url=url))
    print(e)

# load URLs from log file
def load_urls():
  log_file = open("filing_urls.txt", "r")
  urls = log_file.read().split("\n") # convert long string of URLs into a list 
  log_file.close()
  return urls

def download_all_filings():
  print("Start downloading all filings")

  download_folder = "./filings" 
  if not os.path.isdir(download_folder):
    os.makedirs(download_folder)
    
  # uncomment next line to process all URLs
  # urls = load_urls()
  urls = load_urls()[1:40]
  print("{length} filing URLs loaded".format(length=len(urls)))

  number_of_processes = 20

  with multiprocessing.Pool(number_of_processes) as pool:
    pool.map(download_filing, urls)
  
  print("All filings downloaded")

最后,运行download_all_filings()开始下载所有10-K文件。您的filings文件夹应该装满下载的10-K文件,如下所示:

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74225258

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档