EDINETから10年分のXBRLデータをスクレイピング
■2023年4月現在で使えるコードです■
環境:windows10
jupiter notebook python3にて動作確認
このコードは、EDINETのWebページから10年分の短信を取得するものです。 requests ライブラリを用いてWebページにアクセスし、
年ごとにループを回してデータを取得しています。
取得したデータはZipファイルとして取得され、 zipfile ライブラリを使用して展開されます。
10年分のデータはPC性能や環境にもよりますが約60分程度かかります。
※通信ビジー時にもリトライするコードですが50回を上限として設定しています
・cnでEDINETコードを指定して約10年分を遡って書類を取得します。
※EDINETコードは証券コードと同じではありません
・〇部分は指定してください
import requests
import json
import datetime
import os
import time
os.chdir("C:\\〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇〇")
#指定後の絶対パスの出力
print(os.getcwd())
dt = datetime.date.today()
#検索する会社のEDINETコードを入れる
cn = "〇〇〇〇〇〇"
kessan = []
for i in range(0,3000):
d = dt - datetime.timedelta(i)
# 書類一覧APIのエンドポイント
url = "https://disclosure.edinet-fsa.go.jp/api/v1/documents.json"
# 書類一覧APIのリクエストパラメータ
params = {
"date" : d,
"type" : 2,
"count": 1,
"start": st
}
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# APIを呼び出す関数
def call_api(url, params,max_retry=50):
retry_count=0
while retry_count < max_retry:
response = requests.get(url, params=params)
if response.status_code == 200:
response.raise_for_status()
return response.json()
else:
retry_count += 1
time.sleep(1)
raise Exception(f"Failed to get a response after {max_retry} attempts")
# 書類情報の総件数を取得する
# params['count'] = '1'
result = call_api(url, params)
total_count = result['metadata']['resultset']['count']
print(d)
print(total_count)
# 書類情報を取得する
# params.pop('count')
params['length'] = '200'
results = []
#書類の数が200を超えているかどうかの条件分岐
if total_count < 200:
# 200件未満の場合は1回のAPI呼び出しで結果を取得する
res = requests.get(url, params=params, verify=True,timeout=30)
try:
res_text = json.loads(res.text)
except json.JSONDecodeError:
data = None
results= res_text["results"]
else:
# 200件以上の場合は複数回のAPI呼び出しで結果を取得する
st = 0
for start in range(0, total_count, 200):
res = requests.get(url, params=params, verify=True, timeout=30)
try:
res_text = json.loads(res.text)
except json.JSONDecodeError:
data = None
results= res_text["results"]
st = st + 200
#DL書類の検索
for result in results:
filename = ""
if result["edinetCode"] is not None:
if cn in result["edinetCode"]:
if '四半期' in result["docDescription"] or "有価証券報告書" in result["docDescription"]:
kessan.append(result)
docid =result["docID"]
#日付の/がエラーの原因となっているので取り除く対応を行った 23/2/26
result["docDescription"] = result["docDescription"].replace("/", "")
#指定のZIPファイルを保存
url = "https://disclosure2.edinet-fsa.go.jp/api/v1/documents/" + docid
# 書類取得APIのリクエストパラメータ
params = {
"date" : d,
"type" : 1
}
# 出力ファイル名 resultの結果を追うようにIDは変数として取り込む
filename = result["secCode"]+"_"+result["filerName"]+"_"+result["docDescription"]+"_"+result["docID"]
filename = f"{filename}_{d.strftime('%Y%m%d')}"+".zip"
print(filename)
# 書類一覧APIの呼び出し
res = requests.get(url, params=params, verify=True)
if res.status_code == 200:
#wbはバイナリ書き込みモード
with open(filename, 'wb') as f:
for chunk in res.iter_content(chunk_size=1024):
f.write(chunk)
print(len(kessan))
APIの仕様書等は下記を参考ください。
・APIは2種類存在し
書類一覧API:日付のみ指定可能
書類DLAPI:上記APIで取得した書類IDを指定してダウンロード
・200件が上限設定されているとのことなので 念のため200件ずつ検
索をかけています。
200件を超える恐れがない場合は条件分岐と200件ごとの検索分を削
除することで各段に完了までの時間が短縮されます。