🌟

EDINETから有価証券報告書をCSVファイル形式で取得し、テキストデータを抽出する(API version2対応)

2024/05/06に公開

EDINETは、金融庁が公開している有価証券報告書などの電子開示閲覧サイトです。
EDINETのAPIを使えば、有価証券報告書をPDF形式やXBRL形式で取得できるほか、2024年4月からは、新たにCSVファイル形式での取得も可能になりました。

この記事ではEDINETのAPI(version2対応)とPythonを使って、

  1. 有価証券報告書をCSVファイル形式(複数企業対応)で取得する方法
  2. 複数企業のCSVファイルからテキストデータを抽出し、一つのファイルにまとめる方法
    の2点をご紹介していきます。

テキストデータについては、以下の非財務情報を抽出していきます。
経営方針、経営環境及び対処すべき課題等
事業等のリスク
従業員の状況
サステナビリティに関する考え方及び取組

事前準備

API_KEYの設定

GoogleコラボラトリーのシークレットにEDINETのAPI-KEYを保存しておきます。
具体的な保存の方法は以下を参照してください。
https://zenn.dev/robes/articles/04cc622f31c61b

# EDINETAPIのトークンを取得する
from google.colab import userdata

edinet_api_key = userdata.get('EDINET_API_KEY')

 
 

docID(書類管理番号)の取得

EDINETでは一つ一つの有価証券報告書をdocID(書類管理番号)で管理しています。
以下のリンクを参照して、有価証券報告書のdocIDをあらかじめ取得し、edinet_dfに格納します。
https://zenn.dev/robes/articles/f6dfcc5cfbbdb6

 
 

ライブラリーのインポート

from bs4 import BeautifulSoup
import zipfile
import io
import requests
import pandas as pd
from tqdm.notebook import tqdm
import time
import glob
import re

クラスの定義

GetCSVFromEdinetクラスを定義します。
このクラス一つで、CSVファイルの取得とテキストデータの抽出を行います。

class GetCSVFromEdinet:

    def __init__(self, keys,docid_list):
        self.keys = keys
        self.docid_list = docid_list

    def get_csv_file(self):
        for docid in tqdm(self.docid_list):
            url = f"https://api.edinet-fsa.go.jp/api/v2/documents/{docid}"
            params = {"type": 5, "Subscription-Key": edinet_api_key}
            try:
                res = requests.get(url, params=params)
                res.raise_for_status()
                with zipfile.ZipFile(io.BytesIO(res.content)) as z:
                    for file in z.namelist():
                        if file.startswith("XBRL_TO_CSV/jpcrp") and file.endswith(".csv"):
                            z.extract(file, path=f'/content/{docid}/')
                time.sleep(5)  # 適切な待機時間を設定
            except requests.RequestException as e:
                print(f"Request failed for {docid}: {e}")

    #EDINETコードの取得
    def extract_dynamic_code(self,xbrl_path):
        pattern = r'jpcrp030000-asr-001_E(\d{5})'
        match = re.search(pattern, xbrl_path)
        if match:
            return "E" + match.group(1)
        else:
            return None


    def get_text_data(self):
   
        data = []
        for docid in tqdm(self.docid_list):
            csv_path = f'/content/{docid}/XBRL_TO_CSV/*.csv'
            doc_data = [docid]
            try:
                csv_file = glob.glob(csv_path)[0]
                df = pd.read_csv(csv_file, encoding="utf-16",sep="\t")
                for value in self.keys.values():
                    matching_row = df[df["要素ID"]==value]
                    if not matching_row.empty:
                        doc_data.append(matching_row["値"].values[0])
                    else:
                        doc_data.append(None)
                dynamic_code = self.extract_dynamic_code(csv_file)
                key_text = f"jpcrp030000-asr_{dynamic_code}-000:DisclosureOfSustainabilityRelatedFinancialInformationTextBlock"
                matching_row = df[df["要素ID"]==key_text]
                if not matching_row.empty:
                    doc_data.append(matching_row["値"].values[0])
                else:
                    doc_data.append(None)

            except IndexError:
                print(f"No CSV files found for {docid}")
                doc_data += ["File Not Found"] * (len(self.keys)+1)
            except Exception as e:
                print(f"Error processing {docid}: {e}")
                doc_data += ["Error"]*(len(self.keys)+1)

                
            data.append(doc_data)
        return pd.DataFrame(data, columns=["docID"] + list(keys.keys())+["サステナビリティ方針"])

CSVファイルの取得

keys(辞書)の指定

keys = {
    "経営方針":"jpcrp_cor:BusinessPolicyBusinessEnvironmentIssuesToAddressEtcTextBlock", #経営方針、経営環境および対処すべき課題等
    "事業等のリスク":"jpcrp_cor:BusinessRisksTextBlock", #事業等のリスク
    "従業員の状況":"jpcrp_cor:InformationAboutEmployeesTextBlock", #従業員の状況
}

インスタンス化

keysとdocid_listを渡してやります。

gcfe = GetCSVFromEdinet(keys, docid_list)

クラスメソッドの実行

Googleコラボのcontentディレクトリ直下にdocidディレクトリが格納されます。

gcfe.get_csv_file()

テキストデータの抽出

gcfe.get_text_data()

以下のようなデータフレームが作成できれば成功です。

Discussion