はじめに
世の中の上場企業は自身の会社の状況を決算短信や有価証券報告書などを用いて説明する義務があります。株主や投資家は有報などを見て、企業を分析し、投資を決心をします。
しかし、有報は1社につき約100ページ程度、提出数は年間4000件程度あります。そのすべてチェックするというのはいささか現実的ではありません。
そこで財務報告書のファイル形式であるXBRLについて知り、知りたい情報だけをより簡単に取って来ることが出来ると楽ですよね。
なるべく楽によりたくさんの情報を集め、分析できるようになることが本シリーズの共通の目的となります。
本連載では、
- 有報など見るけど、必要な情報を自分の目で見に行っている人
- XBRLについて今は全く知らないけれど理解を深めたいと思っている人
- 有報の分析を楽にしたい人
こういった人に向けて執筆しています。
前稿までは、XBRLについて概要や特徴、取得する対象である有報について知識をつけてもらいました。さらに分析に必要な有報を大量にダウンロードする方法についても扱ってきました。
まだ前稿を読まれてない方はこちら
まるっとわかるXBRL入門シリーズ
本稿はXBRLを用いて有価証券報告書よりテキストデータをテキスト解析にかけられるような状態で抽出する方法についてまとめています。
取り扱っている題材がニッチであるため少しエンジニア向けの記事になってしまっています。そこはご了承ください。基本的にコードは写すだけで同じようなことができるものになっているのでまずは手を動かして実際に体験していただければと思います。
これによってXBRLの興味関心が高まっていただけると嬉しいです。
動作環境
OS: Windows 11
Python 3.12.4
edinet_xbrl 0.2.0
beautifulsoup4 4.12.3
Github
https://github.com/ryou-naruki/XBRL_Foundnation_from_Ontology
有報から事業等のリスクのみを自動で取得する
では本稿の一番の目的であるテキストデータを取得していきます。
XBRLで情報を抽出するおおまかな仕組みとしてはタクソノミという決まった鍵のようなものがあります。
これは2つの鍵を指定することで任意の情報を一つに絞り込むことができます。絞り込んで見つけさえすれば情報は取れるということです。
タクソノミを調べよう
今回抽出する情報は「事業等のリスク」です。これは企業ごとによって記載内容が大きく異なるもので投資家をはじめ多くの注目を集める項目です。
以前の記事で紹介した方法の2つ目の方法を使用します。テキストデータはXBRLファイル内で直接タグで囲まれて記述されているため、実際に検索にかけてタクソノミを調べましょう。
▼タクソノミの参照方法について詳しくはこちら
まるっとわかるXBRL入門:(2)タクソノミと有報
ソースコード
from edinet_xbrl.edinet_xbrl_parser import EdinetXbrlParser
from bs4 import BeautifulSoup
import glob
import re
parser = EdinetXbrlParser()
# 対象のXBRLファイルを指定
xbrl_file_paths = glob.glob(r"xbrl_file\\*2024*\\*\\XBRL\\PublicDoc\\*.xbrl")
# 対象企業のタグを取得
key = "jpcrp_cor:BusinessRisksTextBlock"
context_ref = "FilingDateInstant"
# 非財務情報である事業等のリスクを取得
for i, file_path in enumerate(xbrl_file_paths):
try:
# XBRLファイルをパース
edinet_xbrl_object = parser.parse_file(file_path)
# 事業等のリスクを取得
business_risk = edinet_xbrl_object.get_data_by_context_ref(key, context_ref).get_value()
# BeautifulSoupを使ってHTMLタグを除去
soup = BeautifulSoup(business_risk, "html.parser")
business_risk_cleaned = soup.get_text()
# 空白や改行を取り除く
business_risk_cleaned = re.sub(r'\\s', '', business_risk_cleaned).strip()
print(f"企業{i+1}事業等のリスク:{business_risk_cleaned}")
except Exception as e:
print(f"企業{i+1}データの取得に失敗しました。:{e}")
コード解説
# 対象のXBRLファイルパスを指定
xbrl_file_paths = glob.glob(r"xbrl_file\\*2024*\\*\\XBRL\\PublicDoc\\*.xbrl")
抽出する対象の企業のXBRLファイルについては「同じディレクトリ内にすでにあるもので解凍し使える状態である」という前提のもと話します。
このコードでは正規表現というものを使用しており、私の場合ではこのように記述してディレクトリ内にあるXBRLファイルすべてに適用しています。
正規表現ではご自身のファイルパスに適宜修正してください。
どういうことかイマイチわからない方は一つ前の記事で正規表現を使う前と使った時、両方記しているのでそちらを見ていただけると理解しやすいかと思います。
# 対象企業の事業等のリスクを取得
key = "jpcrp_cor:BusinessRisksTextBlock"
context_ref = "FilingDateInstant"
先ほど調べたタクソノミをそれぞれここで指定して下さい。
keyが要素ID(項目)、context_refがコンテキストID(期間)を表しています。 慣れてくれるとなんとなくこのタグの意味が分かってきたりします。
「jpcrp_cor:BusinessRisksTextBlock」が「事業等のリスク」、 「FilingDateInstant」が「当期」 の意味を持っています。
# 非財務情報である事業等のリスクを取得
for i, file_path in enumerate(xbrl_file_paths):
try:
# XBRLファイルをパース
edinet_xbrl_object = parser.parse_file(file_path)
# 事業等のリスクを取得
business_risk = edinet_xbrl_object.get_data_by_context_ref(key, context_ref).get_value()
# BeautifulSoupを使ってHTMLタグを除去
soup = BeautifulSoup(business_risk, "html.parser")
business_risk_cleaned = soup.get_text()
# 空白や改行を取り除く
business_risk_cleaned = re.sub(r'\\s', '', business_risk_cleaned).strip()
print(f"企業{i+1}事業等のリスク:{business_risk_cleaned}")
except Exception as e:
print(f"企業{i+1}データの取得に失敗しました。:{e}")
for文で記述することで対象のファイルがいくつであっても対応できるようにします。
また、tryとexceptを使ってどこかでエラーが起きても途中で止まらずに最後までコードが回り、エラーが起きたところだけ後で見返せるようにプログラムします。
中身でやっていることとしては、
- インポートしたedinet-xbrlライブラリを使用し、パスで指定したXBRLファイルをパース(解析)
- その中から指定したkeyとcontext_refに当てはまる情報のみを取得
- Beautiful Soupを使用して私たちが文章として読みやすく整える
- 空白や改行などを整え読みやすくする
- 出力(次の書類に移りまた1から行う)
Beautiful Soupやreモジュールのみを使用しても似たようなことはできるのですが、Beautiful Soupだけだと空白や改行がたくさん残ってしまったり、reモジュールだけではBeautiful Soupほど高精度でタグやネストを処理できないため今回は両方を使用しました。
欠点としてそれぞれ一つのみを使用したときよりも重くなるため、一気に多くのファイルを読み込まないことをオススメします。
まとめ
今回は、有価証券報告書の中でも事業等のリスクの内容のみを抽出しました。
前回までの記事よりも少し淡泊ですがそれゆえに必要なことだけを伝えられたかと思います。
テキストデータではこのようにきれいに取れる項目もあれば企業独自のタクソノミが付いていて上手く取得できない場合も多くあります。
次回は、会計士は見ることがある監査報告書から「監査上の主要な検討事項(KAM)」を抽出します。
参考
Zenn ”【自然言語処理】【Python】有価証券報告書の非財務情報(テキストデータ)を取得する” 執筆者:osn_Lofi 最終更新日:2024/08/13
https://zenn.dev/robes/articles/4ab5a7f992000d
Qiita “EDINET開示のXBRLデータから、平均給与等の従業員情報を自動で抽出してみよう(5/10)” 執筆者:XBRLJapan 最終更新日:2024/04/09
https://qiita.com/XBRLJapan/items/b1e66f79d597df7b6037