Advent Calendar 4回目の投稿では、EDINETで開示されているXBRLで記述されたデータをプログラムで集めてみます。
(本記事のプログラムは、一切の保証なく、現状で提供されるものであり、XBRLJapanは、本プログラムの利用に伴って発生した不利益や問題について、原因のいかんを問わず、一切の責任を負わないものとします。)
※2024/04/09:
本記事で紹介しているEDINET API(Version1)が2024年3月29日で利用が終了になりました。
代わりに、EDINET API(Version2)が2024年4月1日から利用が開始されています。
CSVファイルでの提供機能追加などで便利になりましたが、使い方はVesion1とほぼ同じです。また、認証登録が必要です。お手数ですが、詳しくはEDINETサイト等をご確認ください。
1. EDINET APIとは
EDINET APIは、EDINETの画面からではなく、プログラムを介してEDINETのデータベースから効率的に(XBRL)データを取得できるAPI
です。EDINET APIにより、EDINET利用者は効率的に開示情報を取得することが可能となります。APIの利用時には、EDINETのページにある**利用規約**を事前にご確認ください。
2. EDINET APIでXBRLデータを集めてみる
2.1 プログラム概要
本プログラムは、収集期間を指定することで、当該期間にEDINETで開示された有価証券報告書に対応するXBRLデータを、EDINET APIを介してダウンロードするPython言語のプログラムです。(「3. ソースコード」に全コード記載)EDINET APIの詳細仕様は、EDINETサイトからご確認ください。なお、四半期/半期報告書、訂正有価証券報告書には対応していません。
2.2 事前準備
以下内容について、プログラム実行前に対応してください。また、その他ライブラリ(requests、datetimeなど)のインストールなども事前に実施が必要です。
2.2.1 エンドポイントの設定
エンドポイントは2019年12月時点のものです。最新のバージョン(ex. v1)であるかは、その都度確認ください。
https://disclosure.edinet-fsa.go.jp/api/v1/documents.json
2.2.2 XBRL収集期間の設定
XBRLデータを収集したい期間に応じて、start_date
(収集開始日)とend_date
(収集終了日)の日付を変更してください。start_dateは、プログラム実行日から5年前までの日付を指定することができます。
start_date = datetime.date(2019, 11, 1)
end_date = datetime.date(2019, 11,30)
2.2.3 Proxyの設定
ネットワーク環境を踏まえProxyを設定します。Proxyが不要であれば、proxies=proxies
は削除してください。
"http_proxy" : "http://username:password@proxy.example.com:8080"
"https_proxy" : "https://username:password@proxy.example.com:8080"
2.2.4 出力フォルダの決定
XBRLデータがダウンロードされるフォルダ先を決めましょう。
C://Users//xxx//Desktop//xbrlReport//SR//
2.3 実行結果
収集開始日と収集終了日を定めることで、day_list
が作成されます。
start_date = datetime.date(2019, 11, 1)
end_date = datetime.date(2019, 11,30)
day_list [datetime.date(2019, 11, 1), datetime.date(2019, 11, 2), datetime.date(2019, 11, 3), datetime.date(2019, 11, 4), datetime.date(2019, 11, 5), datetime.date(2019, 11, 6), datetime.date(2019, 11, 7), datetime.date(2019, 11, 8), datetime.date(2019, 11, 9), datetime.date(2019, 11, 10), datetime.date(2019, 11, 11), datetime.date(2019, 11, 12), datetime.date(2019, 11, 13), datetime.date(2019, 11, 14), datetime.date(2019, 11, 15), datetime.date(2019, 11, 16), datetime.date(2019, 11, 17), datetime.date(2019, 11, 18), datetime.date(2019, 11, 19), datetime.date(2019, 11, 20), datetime.date(2019, 11, 21), datetime.date(2019, 11, 22), datetime.date(2019, 11, 23), datetime.date(2019, 11, 24), datetime.date(2019, 11, 25), datetime.date(2019, 11, 26), datetime.date(2019, 11, 27), datetime.date(2019, 11, 28), datetime.date(2019, 11, 29), datetime.date(2019, 11, 30)]
2
day_list
を使ってループ処理を行い、各日付ごとに、url
(エンドポイント)、params
(日付情報)、必要に応じてproxies
(Proxy情報)を設定し、requests.get(url, params=params ,proxies=proxies)
を実行することで、res
(Responseオブジェクト)を取得します。url
は書類一覧APIに該当するエンドポイントを指定します。params
で"type": 2
を指定し提出書類一覧を取得している理由は、後続の処理で、有価証券報告書を特定するためです。
for index,day in enumerate(day_list):
url = "https://disclosure.edinet-fsa.go.jp/api/v1/documents.json"
params = {"date": day, "type": 2}
proxies = {
"http_proxy" : "http://username:password@proxy.example.com:8080/",
"https_proxy" : "https://username:password@proxy.example.com:8080/"
}
res = requests.get(url, params=params ,proxies=proxies)
res
はEDINET API仕様書.pdfの2-1-2-1 書類一覧API(メタデータ)で構造が定義されています。以下は、2019.11.1のday
に対応したres
の中身です。
2019-11-01
{
"metadata": {
"title": "提出された書類を把握するためのAPI",
"parameter": {
"date": "2019-11-01",
"type": "2"
},
"resultset": {
"count": 315
},
"processDateTime": "2019-12-05 00:00",
"status": "200",
"message": "OK"
},
"results": [
{
"seqNumber": 1,
"docID": "S100H5LU",
"edinetCode": "E12422",
"secCode": null,
"JCN": "4010001046310",
"filerName": "しんきんアセットマネジメント投信株式会社",
"fundCode": "G03385",
"ordinanceCode": "030",
"formCode": "07A000",
"docTypeCode": "120",
"periodStart": "2018-08-07",
"periodEnd": "2019-08-06",
"submitDateTime": "2019-11-01 09:00",
"docDescription": "有価証券報告書(内国投資信託受益証券)-第17期(平成30年8月7日-令和1年8月6日)",
"issuerEdinetCode": null,
"subjectEdinetCode": null,
"subsidiaryEdinetCode": null,
"currentReportReason": null,
"parentDocID": null,
"opeDateTime": null,
"withdrawalStatus": "0",
"docInfoEditStatus": "0",
"disclosureStatus": "0",
"xbrlFlag": "1",
"pdfFlag": "1",
"attachDocFlag": "1",
"englishDocFlag": "0"
},
resのresults
で提出書類一覧がリスト管理されているので、results
を使ってループ処理を行います。その後、resultsの提出書類ごとに、ordinanceCode
(府令コード)と form_code
(様式コード)を取得します。今回は有価証券報告書を対象とするため、ordinanceCode
が010、form_code
が030000の提出書類のみ処理を行うようにしました。該当した提出書類の、docID
(書類管理番号)を取得し、securities_report_doc_list
(有価証券報告書のリスト)に格納しておきます。
for num in range(len(json_data["results"])):
ordinance_code= json_data["results"][num]["ordinanceCode"]
form_code= json_data["results"][num]["formCode"]
if ordinance_code == "010" and form_code =="030000" :
securities_report_doc_list.append(json_data["results"][num]["docID"])
これにより、有価証券報告書に対応するdocID
のリストが作成できました。
number_of_lists: 77
get_list: ['S100H8TT', 'S100HE9U', 'S100HC6W', 'S100HFA0', 'S100HFBC', 'S100HFB3', 'S100HG9S', 'S100HG62', 'S100HGJL', 'S100HFMG', 'S100HGM1', 'S100HGMZ', 'S100HGFM', 'S100HFC2', 'S100HGNQ', 'S100HGS3', 'S100HGYR', 'S100HGMB', 'S100HGKE', 'S100HFJG', 'S100HGTC', 'S100HH1G', 'S100HH9I', 'S100HGTF', 'S100HHAL', 'S100HHC0', 'S100HFIB', 'S100HH1I', 'S100HH36', 'S100HHDF', 'S100HH9L', 'S100HHGB', 'S100HHGJ', 'S100HHCR', 'S100HHJJ', 'S100HHH0', 'S100HHLH', 'S100HHL6', 'S100HHD4', 'S100HHM7', 'S100HHL9', 'S100HHN6', 'S100HHO8', 'S100HHHV', 'S100HHE3', 'S100HGB5', 'S100HHQ0', 'S100HHP5', 'S100HHMK', 'S100HHE6', 'S100HHPR', 'S100HHDA', 'S100HHR7', 'S100HHSB', 'S100HHML', 'S100HH9H', 'S100HH2F', 'S100H8W1', 'S100HHRP', 'S100HHTM', 'S100HHAF', 'S100HHUD', 'S100HHK9', 'S100HHT4', 'S100HHCI', 'S100HHXQ', 'S100HHO8', 'S100HHSS', 'S100HHRL', 'S100HI19', 'S100HHXS', 'S100HI1W', 'S100HHSP', 'S100HHN4', 'S100HI3J', 'S100HI3K', 'S100HI4G']
次は、当該リストを用いて、XBRLデータをダウンロードするコードです。securities_report_doc_list
を使ってループ処理を行います。url
は書類取得API(書類一覧APIではないことに注意)に該当するエンドポイントを指定します。params
で"type": 1
を指定することで、提出本文書及び監査報告書を取得することが可能です。res
のステータスコード
が200(リクエスト成功時)のみ、XBRLデータをダウンロードしています。なお、5年以上前など、EDINETが保持する期間対象外の日時を指定した場合などに、404(リソースが存在しない)のステータスコードが返却されたりします。
for index,doc_id in enumerate(securities_report_doc_list):
url = "https://disclosure.edinet-fsa.go.jp/api/v1/documents/" + doc_id
params = {"type": 1}
filename = "C:\\Users\\XXX\\Desktop\\xbrlReport\\SR\\" + doc_id + ".zip"
res = requests.get(url, params=params ,stream=True)
if res.status_code == 200:
with open(filename, 'wb') as file:
for chunk in res.iter_content(chunk_size=1024):
file.write(chunk)
実行後、指定フォルダにzipファイルが77件ダウンロードされました。
zipファイルを解凍すると、お馴染みのAuditDocとPublicDocフォルダが出現します。以上で、XBRLデータのダウンロードが完了しました。
3. ソースコード
# -*- coding: utf-8 -*-
import requests
import datetime
def make_day_list(start_date, end_date):
print("start_date:", start_date)
print("end_day:", end_date)
period = end_date - start_date
period = int(period.days)
day_list = []
for d in range(period):
day = start_date + datetime.timedelta(days=d)
day_list.append(day)
day_list.append(end_date)
return day_list
def make_doc_id_list(day_list):
securities_report_doc_list = []
for index, day in enumerate(day_list):
url = "https://disclosure.edinet-fsa.go.jp/api/v1/documents.json"
params = {"date": day, "type": 2}
proxies = {
"http_proxy": "http://username:password@proxy.example.com:8080",
"https_proxy": "https://username:password@proxy.example.com:8080"
}
res = requests.get(url, params=params, proxies=proxies)
json_data = res.json()
print(day)
for num in range(len(json_data["results"])):
ordinance_code = json_data["results"][num]["ordinanceCode"]
form_code = json_data["results"][num]["formCode"]
if ordinance_code == "010" and form_code == "030000":
print(json_data["results"][num]["filerName"], json_data["results"][num]["docDescription"],
json_data["results"][num]["docID"])
securities_report_doc_list.append(json_data["results"][num]["docID"])
return securities_report_doc_list
def download_xbrl_in_zip(securities_report_doc_list, number_of_lists):
for index, doc_id in enumerate(securities_report_doc_list):
print(doc_id, ":", index + 1, "/", number_of_lists)
url = "https://disclosure.edinet-fsa.go.jp/api/v1/documents/" + doc_id
params = {"type": 1}
filename = "C://Users//xxx//Desktop//xbrlReport//SR//" + doc_id + ".zip"
res = requests.get(url, params=params, stream=True)
if res.status_code == 200:
with open(filename, 'wb') as file:
for chunk in res.iter_content(chunk_size=1024):
file.write(chunk)
def main():
start_date = datetime.date(2019, 11, 1)
end_date = datetime.date(2019, 11, 30)
day_list = make_day_list(start_date, end_date)
securities_report_doc_list = make_doc_id_list(day_list)
number_of_lists = len(securities_report_doc_list)
print("number_of_lists:", len(securities_report_doc_list))
print("get_list:", securities_report_doc_list)
download_xbrl_in_zip(securities_report_doc_list, number_of_lists)
print("download finish")
if __name__ == "__main__":
main()
4. 有価証券報告書以外の報告書の集め方
今回は有価証券報告書を対象にしましたが、ordinanceCode
とform_code
を変更することで、他のXBRLで記述された報告書のデータも自動で収集することができます。例えば、四半期報告書であれば、ordinanceCode
が010、form_code
が043000の提出書類のみ処理を行う仕組みに変更すればよいです。以下に訂正も含め簡単に整理をしました。
〇有価証券報告書
if ordinanceCode == "010" and formCode =="030000" :
〇訂正有価証券報告書
if ordinanceCode == "010" and formCode =="030001" :
〇四半期報告書
if ordinanceCode == "010" and formCode =="043000" :
〇訂正四半期報告書
if ordinanceCode == "010" and formCode =="043001" :
全様式の府令コードと様式コードについては、EDINET API関連資料(平成31年3月17日公開)の[EDINET API仕様書]からダウンロードされるzipファイルに含まれている別紙1_様式コードリスト.xlsx
を参照ください。
5. 問合せ先
本記事に関する問い合わせは、以下のメールアドレスまでお願いします。
e-mail:xbrl-tech-qa@xbrl.or.jp
(もちろん、qiita上でのコメントも歓迎します)
本メールアドレスは、qiitaの記事を執筆しているXBRLJapanの開発委員会の問合せ窓口になります。
そのため、組織に関する一般的な問合せなどは内容によって回答できかねますが、XBRLに関する技術的な質問、意見、要望、助言等はお気軽にご連絡ください。
なお、委員会メンバが有志で対応しているため、回答に時間がかかることもありますが、ご了承ください。