これまでのシリーズでは、EDINET APIを利用してXBRLファイルを取得し、そのファイルを辞書化してJSON形式で保存する方法について解説してきました。今回は、その延長線上で、過去5年間の有価証券報告書を自動で取得し、XBRLデータを解析して辞書形式に変換し、JSONファイルとして保存するコードを解説します。
この記事は以下のシリーズに続く内容です。
- 第1章:EDINET APIからXBRLファイルを取得する基本的な方法
- 第2章:XBRLファイルを辞書化し、JSONファイルとして保存する方法
- 第3章:過去5年間の有価証券報告書をEDINET APIから取得するためのPythonコードの解説
今回は、これらの記事で紹介した知識を組み合わせて、より高度なデータ処理を行う方法を紹介します。
プロジェクトの目的
今回のプロジェクトでは、特定の企業に関する過去5年間の有価証券報告書をEDINET APIから自動で取得し、それらのXBRLファイルを解析してJSON形式に変換し、保存することを目指してきました。この方法は、長期間の財務データを効率的に収集し、投資分析や経済的な洞察を得るための重要なステップになります。
最終的なソリューションコード
完成形のコード全体は以下のようになります。
import requests
import zipfile
import os
import io
from dotenv import load_dotenv
from datetime import datetime, timedelta
from lxml import etree
import json
# 環境変数の読み込み
load_dotenv()
# APIキーを環境変数から取得
api_key = os.getenv("API_KEY")
# xbrl_filesフォルダが存在しない場合は作成
os.makedirs("./xbrl_files", exist_ok=True)
# XBRLファイルをダウンロードする関数
def download_xbrl_file(doc_id):
download_url = f"https://api.edinet-fsa.go.jp/api/v2/documents/{doc_id}"
params = {"type": 1, "Subscription-Key": api_key}
download_response = requests.get(download_url, params=params)
if download_response.status_code == 200:
zip_file_path = f"./xbrl_files/{doc_id}.zip"
with open(zip_file_path, "wb") as f:
f.write(download_response.content)
print(f"XBRLファイルを保存しました: {zip_file_path}")
return zip_file_path
else:
print(f"XBRLファイルのダウンロードに失敗しました: {doc_id}")
return None
# XBRLファイルをZIPから抽出する関数
def extract_xbrl(zip_file_path):
with zipfile.ZipFile(zip_file_path, 'r') as zip_ref:
xbrl_files = [f for f in zip_ref.namelist() if f.endswith('.xbrl')]
if xbrl_files:
return zip_ref.read(xbrl_files[0]) # 最初のXBRLファイルを返す
return None
# XBRLファイル内のタグに対応する数値と属性を取得する関数
def get_values_and_attributes_from_xbrl(root):
tag_to_value_and_attrs = {}
for element in root.iter():
ns_prefix = element.prefix
ns_tag = etree.QName(element).localname
full_tag = f"{ns_prefix}:{ns_tag}" if ns_prefix else ns_tag
value = element.text.strip() if element.text else None
attributes = {attr: val for attr, val in element.attrib.items()} if element.attrib else None
tag_to_value_and_attrs[full_tag] = {
"value": value,
"attributes": attributes
}
return tag_to_value_and_attrs
# 辞書をJSON形式に変換して保存
def save_to_json(data, year, doc_id):
# jsonファイルをxbrl_filesフォルダに保存
file_name = f"./xbrl_files/xbrl_data_{year}_{doc_id}.json"
with open(file_name, 'w', encoding='utf-8') as json_file:
json.dump(data, json_file, ensure_ascii=False, indent=4)
print(f"JSONファイルを保存しました: {file_name}")
# 過去5年間の有価証券報告書を取得する関数
def get_reports_for_past_5_years(edinet_code):
current_year = datetime.now().year
for year in range(current_year - 5, current_year + 1):
print(f"年: {year} のデータを取得しています。")
period_start = datetime(year, 1, 1)
period_end = datetime(year, 12, 31)
current_date = period_start
while current_date <= period_end:
url = "https://disclosure.edinet-fsa.go.jp/api/v2/documents.json"
params = {'date': current_date.strftime('%Y-%m-%d'), 'type': 2, "Subscription-Key": api_key}
response = requests.get(url, params=params)
if response.status_code == 200:
data = response.json()
for doc in data.get('results', []):
if doc['edinetCode'] == edinet_code and doc['docTypeCode'] == '120':
doc_id = doc['docID']
print(f"ドキュメントID: {doc_id}, 提出日: {doc['submitDateTime']}")
# XBRLファイルをダウンロード
zip_file_path = download_xbrl_file(doc_id)
if zip_file_path:
# ZIPからXBRLファイルを抽出
xbrl_content = extract_xbrl(zip_file_path)
if xbrl_content:
# XBRLファイルのルート要素を解析
root = etree.fromstring(xbrl_content)
# タグと値、属性を取得
tag_to_value_and_attrs = get_values_and_attributes_from_xbrl(root)
# JSONファイルに保存(ファイル名に決算年度とdocIDを組み合わせる)
save_to_json(tag_to_value_and_attrs, year, doc_id)
else:
print(f"{current_date.strftime('%Y-%m-%d')} のデータ取得に失敗しました。")
current_date += timedelta(days=1)
# EDINETコードを指定して過去5年間の有価証券報告書を取得
edinet_code = "E02529"
get_reports_for_past_5_years(edinet_code)
XBRLデータをJSONファイルに保存するためのステップ
それでは、今回のコードの各ステップを見ていきましょう。
1.必要なモジュールとAPIキーの読み込み
前回の記事同様、APIキーを.env
ファイルから読み込みます。これにより、EDINET APIへのアクセスが可能となります。
from dotenv import load_dotenv
import io
import os
import requests
from lxml import etree
import zipfile
from datetime import datetime, timedelta
import json
load_dotenv()
api_key = os.getenv("API_KEY")
2.XBRLファイルのダウンロード
特定の企業の書類管理番号(docID)に基づき、XBRLファイルをダウンロードします。第1章でも触れたように、EDINET APIを使用してZIP形式のXBRLファイルを取得し、それをxbrl_files
フォルダに保存します。
def download_xbrl_file(doc_id):
download_url = f"https://api.edinet-fsa.go.jp/api/v2/documents/{doc_id}"
params = {"type": 1, "Subscription-Key": api_key}
download_response = requests.get(download_url, params=params)
if download_response.status_code == 200:
zip_file_path = f"./xbrl_files/{doc_id}.zip"
with open(zip_file_path, "wb") as f:
f.write(download_response.content)
print(f"XBRLファイルを保存しました: {zip_file_path}")
return zip_file_path
else:
print(f"XBRLファイルのダウンロードに失敗しました: {doc_id}")
return None
3.ZIPファイルからXBRLファイルを抽出
ダウンロードしたZIPファイルからXBRLファイルを抽出します。この部分は第2章でも触れた内容ですが、ZIPファイル内のXBRLファイルを探し、それを抽出してメモリ上で処理します。
def extract_xbrl(zip_file_path):
with zipfile.ZipFile(zip_file_path, 'r') as zip_ref:
xbrl_files = [f for f in zip_ref.namelist() if f.endswith('.xbrl')]
if xbrl_files:
return zip_ref.read(xbrl_files[0])
return None
4.XBRLファイルの解析と辞書化
ここでは、XBRLデータを解析し、各要素の名前空間プレフィックスと要素名のペアをキーとして、値と属性を辞書に格納します。この手法は、第2章で説明した「XBRLファイルを辞書形式に変換」で使用しました。
def get_values_and_attributes_from_xbrl(root):
tag_to_value_and_attrs = {}
for element in root.iter():
ns_prefix = element.prefix
ns_tag = etree.QName(element).localname
full_tag = f"{ns_prefix}:{ns_tag}" if ns_prefix else ns_tag
value = element.text.strip() if element.text else None
attributes = {attr: val for attr, val in element.attrib.items()} if element.attrib else None
tag_to_value_and_attrs[full_tag] = {
"value": value,
"attributes": attributes
}
return tag_to_value_and_attrs
5.JSONファイルとして保存
辞書化したXBRLデータをJSON形式で保存します。ファイル名には有価証券報告書を提出した年とdocIDを含め、データ管理をしやすくしています。
def save_to_json(data, year, doc_id):
file_name = f"./xbrl_files/xbrl_data_{year}_{doc_id}.json"
with open(file_name, 'w', encoding='utf-8') as json_file:
json.dump(data, json_file, ensure_ascii=False, indent=4)
print(f"JSONファイルを保存しました: {file_name}")
6.過去5年間の有価証券報告書を取得
このコードの核となる部分です。特定のEDINETコードに基づいて、過去5年間の有価証券報告書(docTypeCodeが120)を取得します。日付ごとに検索し、報告書が見つかった場合にXBRLファイルをダウンロードし、解析、JSON形式で保存します。
def get_reports_for_past_5_years(edinet_code):
current_year = datetime.now().year
for year in range(current_year - 5, current_year + 1):
print(f"年: {year} のデータを取得しています。")
period_start = datetime(year, 1, 1)
period_end = datetime(year, 12, 31)
current_date = period_start
while current_date <= period_end:
url = "https://disclosure.edinet-fsa.go.jp/api/v2/documents.json"
params = {'date': current_date.strftime('%Y-%m-%d'), 'type': 2, "Subscription-Key": api_key}
response = requests.get(url, params=params)
if response.status_code == 200:
data = response.json()
for doc in data.get('results', []):
if doc['edinetCode'] == edinet_code and doc['docTypeCode'] == '120':
doc_id = doc['docID']
print(f"ドキュメントID: {doc_id}, 提出日: {doc['submitDateTime']}")
zip_file_path = download_xbrl_file(doc_id)
if zip_file_path:
xbrl_content = extract_xbrl(zip_file_path)
if xbrl_content:
root = etree.fromstring(xbrl_content)
tag_to_value_and_attrs = get_values_and_attributes_from_xbrl(root)
save_to_json(tag_to_value_and_attrs, year, doc_id)
else:
print(f"{current_date.strftime('%Y-%m-%d')} のデータ取得に失敗しました。")
current_date += timedelta(days=1)
まとめ
この記事では、EDINET APIから過去5年間の有価証券報告書を取得し、その報告書に含まれるXBRLデータを辞書化し、JSON形式で保存する方法について解説しました。これまでのブログ記事で学んできた内容を基に、より長期間のデータ取得と管理を実現しました。
次回の記事では、取得したXBRLデータの具体的な分析方法や、フィルタリング、可視化について取り組んでいきたいと思います。
過去のデータを効率的に取得して分析するための第一歩として、このコードを活用して、投資分析や経済データの活用に役立ててください!