以下は、自分が XBRL を読み込むために作成した Python ライブラリです。
(2022年3月31日 追記)このライブラリよりも、まずは↑上記の Arelle の使用をおすすめします。
金融庁の EDINET で公開されている XBRL を読み込むために作りました。
上場企業の有価証券報告書、四半期報告書に対応しています。また、2013年以前の【旧】EDINET XBRL 形式にも対応しています。
このライブラリは、各勘定科目のタグ名・金額・日付・連結区分といった情報を、XBRL ファイルから一括で取得します。
要は、XBRLデータの中身をスクレイピングするライブラリです。
たとえば、以下のようなデータが取得できます。
コンテキストなどの定義をたどって、表形式に組み立てるのが主な機能です。
このデータから時系列分析をした時の記事はこちら
version から第N期(第N四半期のこと)までがファイル名からの情報で、名前空間接頭辞から値までが、個々の勘定科目とコンテキストから読み取った情報です。
このライブラリに XBRL のファイルパスを渡すと、上の画像のようなデータフレームが返ってきますので、ある企業の XBRL を全て連結して、売上・利益の時系列グラフを描く、といったことに使えます。
(米国のEDGAR XBRL用のライブラリも作りました)
もっと詳細なXBRLパーサーの作り方の記事も書きました。
以下、XBRL解析ライブラリの説明です。
Pythonライブラリのダウンロード
有価証券報告書の XBRL を読み込む Python ライブラリ です。
(xbrl reader for edinet)
xbrl_reader_for_edinet_20180702-00.zip (zip形式 11.1KB)
※ このライブラリは、当サイトの管理人が作成したものです。
EDINET や金融庁は無関係です。
ライセンス (NYSL Version 0.9982)
このライセンスは、上記ライブラリの中の各Pythonファイルに対して適用します。
これらのPythonファイルの中でインポートしているその他のライブラリに関しては、それぞれのライセンスに従ってご利用ください。
NYSL Version 0.9982
A. 本ソフトウェアは Everyone’sWare です。このソフトを手にした一人一人が、
ご自分の作ったものを扱うのと同じように、自由に利用することが出来ます。A-1. フリーウェアです。作者からは使用料等を要求しません。
A-2. 有料無料や媒体の如何を問わず、自由に転載・再配布できます。
A-3. いかなる種類の 改変・他プログラムでの利用 を行っても構いません。
A-4. 変更したものや部分的に使用したものは、あなたのものになります。
公開する場合は、あなたの名前の下で行って下さい。B. このソフトを利用することによって生じた損害等について、作者は
責任を負わないものとします。各自の責任においてご利用下さい。C. 著作者人格権は シラベルノート はるかわ に帰属します。著作権は放棄します。
D. 以上の3項は、ソース・実行バイナリの双方に適用されます。
動作環境と必要なライブラリ
カッコ内は動作確認で使用したバージョンです。
極端に古くなければ、ほかのバージョンでも動くと思います。
- Python (3.5.2) 64bit版 または Python (3.4.3) 32bit版
- lxml (3.6.4)
- python-dateutil (2.6.1)
- pandas (0.22.0)
インストール手順
ダウンロードした zip の中身を、あなたが開発している Python ファイルと同じフォルダに展開します。
または、別のフォルダに展開して、そのフォルダへのパスを sys.path のリストに追加します。
"""あなたが開発しているPythonファイル.py"""
import sys
sys.path.append(r'ライブラリを展開したフォルダへのパス')
これで、あなたの Python ファイルからインポートできるようになりました。
アンインストール手順
インストール手順で展開した Python ファイルを削除してください。
これで、アンインストールは完了です。
あと、ライブラリを使用した場合は、「__pycache__」というフォルダに「.pyc」というキャッシュファイルが作られていると思います。展開した Python ファイルの名前が入ったキャッシュファイルは不要ですので、これも削除してください。
「.pyc」の説明は、以下の Python マニュアルをご覧ください。
(Python) モジュール (module) "コンパイル"
された Python ファイル
XBRLファイルを読み込む
複数の Python ファイルに分かれていますが、実際にインポートして使うのは「エックス・ビー・アール・エル・プロック(xbrl_proc.py)」にある、以下の関数です。それぞれ、解凍済みの「.xbrl」を読み込む用と、圧縮された「.zip」から読み込む用です。
read_xbrl(xbrl=xbrlファイルパス)
戻り値:pandas.DataFrame
read_xbrl_from_zip(xbrl=zipファイルパス)
戻り値:pandas.DataFrame のリスト
※ zipの中には、「jpfrとifrs」、「jpcrpとifrs」といった組み合わせで複数のXBRLファイルが入っている場合があります。そのため、zip版では戻り値を常にリストに入れて返すようにしています。ですので、戻り値をfor文にかけるなどして、個々のデータフレームを取り出してください。
なお、監査報告書の XBRL(jpaud)はスキップしています。財務諸表が載っている XBRL だけを読み込んでいます。
使用例
ファイルに応じて、以下のように使い分けます。どちらか必要なほうを使ってください。
xbrl から読み込む
XBRL 用の関数にファイルパスを渡すと、データフレームが返ります。
# xbrl から読み込む
from xbrl_proc import read_xbrl
xbrl_file = r"*****\jpcrp030000-asr-001_E00000-000_2017-03-31_01_2017-06-29.xbrl"
df = read_xbrl(xbrl_file)
zip から読み込む
zip 用の関数にファイルパスを渡すと、データフレームのリストが返ります。
# zip から読み込む (データフレームのリストが返る)
from xbrl_proc import read_xbrl_from_zip
zip_file = r"*****\SXXXXXXX.zip"
df_list = read_xbrl_from_zip(zip_file)
for df in df_list:
(データ処理など)
Pythonコードの解説
このライブラリの Python コードの解説は「XBRLまとめ」の記事に載っています。ライブラリの構造を知りたい時にご覧ください。
読み込みエラーなどについて
このライブラリには、assert文やraise文といった、デバッグ用のコードが残っています。もし、これらに反応して読み込めないファイルがあったときは、反応しているコードをコメントアウトするなどしてみてください。それでとりあえず読み込める場合もあるかもしれません。
全上場企業のXBRLを大量に読み込んでいくと、何かしらの読み込みエラーに遭遇すると思います。原因ですが、ダウンロードに失敗してXBRL(zip)が壊れていた、ファイル名が仕様書に無いパターンであった、XBRLファイルの構文に誤りがあった、などです。
これらに遭遇するたび修正して、出来るだけ止まらず読み込めるようにしてきました。今のところ、私の環境では実用的に動いていますが、ほかの環境でも動くかはわかりません。ライブラリは、ほぼ制限のないライセンスにしましたので、必要に応じて手を加えてみてください。
【旧】EDINET XBRL形式の ifrs に関してですが、個々の勘定科目の連結区分が空欄になる場合があります。「.xbrl」のファイルだけでは判定できない仕様のようだったので、そのようにしています。
読み込みを高速化したいとき
2014年以降の新しいEDINET XBRLでは、有報の本文まで載っています。このデータの読み込みをスキップすることで、読み込みが非常に速くなります。特に文章の多い本決算の有報では、所要時間を3分の1くらいにまで短縮できました。
高速化の方法ですが、「xbrl_jpcor.py」の「Parserクラス」にある「get_xbrl_datas()メソッド」に、本文などをスキップするコードがあります。そこのコメントアウトを外すことで、データの大きい本文などをスキップするようになります。
def get_xbrl_datas(self, namespace):
"""データ取得"""
datas = OrderedDict()
for element in self.root.findall('.//{%s}*' % namespace):
# # 本文のテキストブロックは不要なのでスキップ
# if self.ns_crp:
# if self.ns_crp in element.tag:
# if 'CoverPage' in element.tag:
# # print('skipped %s %s' % (
# # element.tag.split('}')[1], element.text[:20]))
# continue
# elif 'TextBlock' in element.tag:
# # print('skipped %s %s' % (
# # element.tag.split('}')[1], element.text[:20]))
# continue
# # 提出者別タクソノミのテキストブロックは不要なのでスキップ
# if self.ns_self:
# if self.ns_self in element.tag:
# if 'CoverPage' in element.tag:
# # print('skipped %s %s' % (
# # element.tag.split('}')[1], element.text[:20]))
# continue
# elif 'TextBlock' in element.tag:
# # print('skipped %s %s' % (
# # element.tag.split('}')[1], element.text[:20]))
# continue
# tag名、contextRef、idのタプルをキーにして辞書を作成
key = (element.tag, element.get('contextRef'), element.get('id'))
data = OrderedDict()
# 属性の内容を追加
data.update(element.attrib)
# テキストも追加
data.update({'text': element.text})
if key in datas:
if data == datas[key]:
# キーも値も同じなのでスキップ
continue
else:
print('キー重複 %s' % str(key))
# リストに追加
datas.update({key: data})
return datas
プログラミングの参考になれば幸いです