【Python】Edinetから取得したXBRLファイルをCSVファイルにpythonで変換することに成功した!

1. 実行結果
2. コードの全容
3. コードの説明
4. 次にすること


1. 実行結果

まずは、実行結果のcsvファイルです。

スクリーンショット 2020-11-12 19.28.20

こんな感じで、日本語での項目名(例:売上高)、英語での項目名、context_idなるもの、qnameなるもの、数値を取り出してcsvにすることができました。

2. コードの全容

(get_xbrl_path.py)

import glob

def get_xbrl_path(data_folder_path) -> list:
 files = glob.glob(data_folder_path + '/**/XBRL/PublicDoc/*.xbrl')
 return files

(arelle_parser.py)

import re
import csv
import os

from Arelle.arelle import Cntlr


class XbrlToCsv(object):

 def __init__(self, xbrl_filename):
   self.xbrl_filename = xbrl_filename
   self.csv_filename = ''
   self.xbrl_dicts_list_data = [] # csvに書き込みたいデータを辞書型で追加していくためのリスト。

   self.make_xbrl_dicts_list_data()
   self.csv_filename = self.create_csv_filename_folder()
   self.write_csv()

 # xbrl_dicts_list_dataに情報を格納するためのメソッド
 def make_xbrl_dicts_list_data(self):
   xbrl_file = self.xbrl_filename
   ctrl = Cntlr.Cntlr(logFileName='logToPrint')
   model_xbrl = ctrl.modelManager.load(xbrl_file)

   for fact in model_xbrl.facts:
   # 必要情報の取得
     label_ja = fact.concept.label(preferredLabel=None, lang='ja', linkroleHint=None)
     label_en = fact.concept.label(preferredLabel=None, lang='en', linkroleHint=None)
     id = fact.contextID
     qname = fact.qname
     try:
       value = fact.vEqValue
     except ValueError as e:
       pass
     if not (type(value) == int or  type(value) == float):
       value = value[:20]

     self.xbrl_dicts_list_data.append({
       'label_ja': label_ja,
       'label_en': label_en,
       'context_id': id,
       'qname': qname,
       'value': value,
     })

 # csvを書き込む
 def write_csv(self):
   csv_filename = self.csv_filename
   with open(csv_filename, 'w', encoding='utf8') as csv_file:
     # header を設定
     fieldnames = ['label_ja', 'label_en', 'context_id', 'qname', 'value']
     writer = csv.DictWriter(csv_file, fieldnames=fieldnames)
     writer.writeheader()

     # データの書き込み
     for row in self.xbrl_dicts_list_data:
       writer.writerow(row)
   print('successfully created', csv_filename)


 # csvファイルの名前とフォルダを作るメソッド(証券コード/証券コード.csv)
 def create_csv_filename_folder(self):
   # フォルダ名とファイル名の作成
   for dict in self.xbrl_dicts_list_data:
     if str(dict['qname']) == "jpdei_cor:SecurityCodeDEI":
       csv_foldername = 'csv/' + dict['value']
       csv_filename = csv_foldername + '/' + str(dict['value']) + '.csv'
   # フォルダの作成
   if not os.path.exists(csv_foldername):
     os.mkdir(csv_foldername)
     print('successfully created', csv_foldername, 'folder')
   # ファイルネームをself.csv_filenameに保存
   self.csv_filename = csv_filename
   return csv_filename


 
   
# xbrlを引数に渡してインスタンスを作成すると、csvファイルも作成される
# test = XbrlToCsv('/Users/m_ishikawa/Desktop/edinet_venv/data/S100FSL4/XBRL/PublicDoc/jpcrp030000-asr-001_E03219-000_2019-02-20_01_2019-05-15.xbrl')


# 以下で全てのxbrlファイルをcsvに変換する
from get_xbrl_path import get_xbrl_path

xbrl_paths_list = get_xbrl_path('data')
i = 0
for path in xbrl_paths_list:
 i += 1
 XbrlToCsv(path)
 print('finished', i/len(xbrl_paths_list))

arelle_parser.pyを実行すると、xbrlファイルがcsvファイルに変換されます。
前提条件として、
・Arelleというライブラリのダウンロード(arelleの準備はこちらを見てみてください)
・上のpythonファイルと同じところに、dataという名前のディレクトリ(ここにedinetから取得したzipファイルを解凍したディレクトリをいれておく)、csvという名前のディレクトリを作っておく必要があります。


3. コードの説明

まずは、メソッドの説明から

# xbrl_dicts_list_dataに情報を格納するためのメソッド
 def make_xbrl_dicts_list_data(self):
   xbrl_file = self.xbrl_filename
   ctrl = Cntlr.Cntlr(logFileName='logToPrint')
   model_xbrl = ctrl.modelManager.load(xbrl_file)

   for fact in model_xbrl.facts:
   # 必要情報の取得
     label_ja = fact.concept.label(preferredLabel=None, lang='ja', linkroleHint=None)
     label_en = fact.concept.label(preferredLabel=None, lang='en', linkroleHint=None)
     id = fact.contextID
     qname = fact.qname
     try:
       value = fact.vEqValue
     except ValueError as e:
       pass
     if not (type(value) == int or  type(value) == float):
       value = value[:20]

     self.xbrl_dicts_list_data.append({
       'label_ja': label_ja,
       'label_en': label_en,
       'context_id': id,
       'qname': qname,
       'value': value,
     })

arelleを使って
self.xbrl_dicts_list_dataに、xbrlファイルの内容を辞書形式で記録しています。


def write_csv(self):
   csv_filename = self.csv_filename
   with open(csv_filename, 'w', encoding='utf8') as csv_file:
     # header を設定
     fieldnames = ['label_ja', 'label_en', 'context_id', 'qname', 'value']
     writer = csv.DictWriter(csv_file, fieldnames=fieldnames)
     writer.writeheader()

     # データの書き込み
     for row in self.xbrl_dicts_list_data:
       writer.writerow(row)
   print('successfully created', csv_filename)

上のmake_xbrl_dicts_list_dataメソッドで作った、
self.xbrl_dicts_list_dataのリストを1つずつ呼び出して、csvファイルに書き込んで行っています。


# csvファイルの名前とフォルダを作るメソッド(証券コード/証券コード.csv)
 def create_csv_filename_folder(self):
   # フォルダ名とファイル名の作成
   for dict in self.xbrl_dicts_list_data:
     if str(dict['qname']) == "jpdei_cor:SecurityCodeDEI":
       csv_foldername = 'csv/' + dict['value']
       csv_filename = csv_foldername + '/' + str(dict['qname']) + '.csv'
   # フォルダの作成
   if not os.path.exists(csv_foldername):
     os.mkdir(csv_foldername)
     print('successfully created', csv_foldername, 'folder')
   # ファイルネームをself.csv_filenameに保存
   self.csv_filename = csv_filename
   return csv_filename

上のwrite_csvメソッドでcsvファイルを書き込むためのディレクトリとcsvファイルのファイル名を作ります。ディレクトリ名とcsvファイルの名前は証券コードになっています。


def __init__(self, xbrl_filename):
   self.xbrl_filename = xbrl_filename
   self.csv_filename = ''
   self.xbrl_dicts_list_data = [] # csvに書き込みたいデータを辞書型で追加していくためのリスト。

   self.make_xbrl_dicts_list_data()
   self.csv_filename = self.create_csv_filename_folder()
   self.write_csv()

イニシャライズ:
上で紹介した3つのメソッドをインスタンス作成時に実行するようにしています。こうすることで、インスタンスを作成するだけで、xbrlファイルからcsvファイルに変換されます。


(get_xbrl_path.py)

import glob

def get_xbrl_path(data_folder_path) -> list:
 files = glob.glob(data_folder_path + '/**/XBRL/PublicDoc/*.xbrl')
 return files

edinetからダウンロードしたディレクトリからxbrlファイルを特定するコードです。このコード同じディレクトリにdataという名前のフォルダを作って、edinetからダウンロードしたS100FSL4、みたいな名前のディレクトリをおいとけばokです。


# 以下で全てのxbrlファイルをcsvに変換する
from get_xbrl_path import get_xbrl_path

xbrl_paths_list = get_xbrl_path('data')
i = 0
for path in xbrl_paths_list:
 i += 1
 XbrlToCsv(path)
 print('finished', i/len(xbrl_paths_list))

実行部分。


4. 次にすること

edinetからxbrlファイルを一括でダウンロードするとストレージが一瞬でいっぱいになるので、
edinetから一括でxbrlファイルをダウンロードすると同時に、csvに変換し、不要になったxbrlファイルを削除するコードを書いていこうと思う。

いいなと思ったら応援しよう!