Day4

# -*- coding:utf-8 -*-
#! usr/bin/env python3.7
from datetime import date
import os
import sys
import requests
import json
from zipfile import ZipFile
import pandas as pd
import glob

# XBRLをpython形式に変換するライブラリのフォルダパス
sys.path.append(r'任意のフォルダパス')
from xbrl_proc import read_xbrl_from_zip
import urllib3
from urllib3.exceptions import InsecureRequestWarning
urllib3.disable_warnings(InsecureRequestWarning)

def get_list(start, end, company_list):
    """指定した期間、報告書種類、会社で報告書を取得し、取得したファイルのパスの辞書を返す"""
    #取得期間の日付リストを作成
    day_term = [start + timedelta(days=i) for i in range((end - start).days)]

    # データ抜出時に使用する、有価証券報告書および四半期報告書のコードの設定
    ordinance_code = "010"
    form_code_quart = "043000" # 四半期報告書
    form_code_securities = "030000" # 有価証券報告書

    # EDINETのAPIで、書類一覧を取得し、各日ごとに必要な書類の項目の抜き出し
    quart_list = []  # 四半期報告書のリスト 
    securities_list = []  # 有価証券報告書のリスト

    print('EDINETへのアクセスを開始')
    for i,day in enumerate(day_term):
        url = "https://disclosure.edinet-fsa.go.jp/api/v1/documents.json"
        params = {"data": day, "type": 2}

        # 進捗表示
        if i % 50 == 0:
            print('{i}日目:{day}を開始'.format(i, day))

        # EDINETからの1日の書類一覧を取得
        res = requests.get(url, params=params, verify=False)

        # 必要な書類の項目の抜き出し
        if res.ok:
            json_data = res.json()

            for data in json_data['results']:
                # 指定した会社の、指定した書類の抜き出し
                if data['ordinanceCode'] == ordinance_code and data['formCode'] == form_code_quart and data['filerName'].replace('株式会社', '') in company_list:
                    quart_list.append(data)
                elif data['ordinanceCode'] == ordinance_code and data['formCode'] == form_code_securities and data['filerName'].replace('株式会社', '') in company_list:
                    securities_list.append(data)

        else:
             print('アクセス失敗かも{day}'.format(day))

    list_dic = {'四半期報告書':quart_list, '有価証券報告書':securities_list}

    return list_dic
day_term = [start + timedelta(days=i) for i in range((end - start).days)]

・リスト内包表記

list = [function(i) for i in range(params)]

・繰り返し処理

for i,day in enumerate(day_term)

enumerate関数がここで使えるのは今日の学び。

・辞書

params = {"data": day, "type": 2}

・フォーマット

print('{i}日目:{day}を開始'.format(i, day))

json
json()は何を表すのか。

 json_data = res.json()


・replaceと、繰り返し処理のデータ表示のしかたの例

for sth in data['result']
  sth['content_in_result'] == sth[''].replace(' ',' ')


・リストを辞書に含めることができる

quart_list = []
securities_list = []
list_dic = {'四半期報告書':quart_list, '有価証券報告書':securities_list}
def get_zip(list_dic, quart_dir_path, securities_dir_path):
    """取得したいデータをzipファイルで取得してファイルパスのリストを返す"""
    dir_path_dic = {'四半期報告書':quart_dir_path, '有価証券報告書':securities_dir_path}
    file_path_dic = {'四半期報告書':[], '有価証券報告書':[]}  # ダウンロードした有価証券報告書のパスを格納する辞書

    for key in list_dic.keys():

        # 既にzipをDLしている場合のため、既存んおdocIDリストを取得
        files = os.listdir(dir_path_dic[key])
        existing_docID_list = [file.split('.')[0].split('_')[1] for file in files if os.path.isfile(os.path.join(dir_path_dic[key], file))]

        print('{key}ファイルのDLを開始'.format(key))
        for i, doc in enumerate(list_dic[key]):
            # zipファイルパスのリストの作成
            file_name = doc['filerName'].replace('株式会社', '') + '_' + doc['docID']
            file_path = os.path.join(dir_path_dic[key], file_name + ".zip")
            file_path_dic[key].append(file_path)

            # 所有していないファイルの場合はDLを行う
            if doc['docID'] not in existing_docID_list:
                # ファイルを取得
                url_zip = "https://disclosure.edinet-fsa.go.jp/api/v1/documents/" + doc['docID']
                params_zip = {"type":1}

                # 進捗表示
                if i % 100 == 0:
                    print('{i}ファイル目を開始'.format(i))

                # データのDL
                res_zip = requests.get(url_zip, params=params_zip, verify=False, stream=True)

                # zipとして保存
                if res_zip.status_code == 200:
                    with open(file_path, 'wb') as f:
                        for chunk in res_zip.iter_content(chunk_size=1024):
                            if chunk:
                                f.write(chunk)
                                f.flush()

        return file_path_dic

・keys()とは、おそらく、辞書のkeyだな!

for key in file_path_dic.keys():


・これこれ、俺が気になったコードは。まず、リスト内包表記、でifの条件分岐をリストに入れることができるのか。
・split("第一引数"、"第二引数")があって、第一引数にはどこで区切るか。第二引数には初めから数えてどのくらい区切るか、を指定する。で[0]は一番初めのもの。それをさらにsplitして[1]から表示する。というような気がする。わからんが。わかったら直していこう!

existing_docID_list = [file.split('.')[0].split('_')[1] for file in files if os.path.isfile(os.path.join(dir_path_dic[key], file))]

list = [something for x in Xs if sth]

次のコードへ。

def zip_to_df(file_path_dic):
  """ダウンロードしたzipをdfに変換して各会社のdicにして返す"""

  all_df_dic = {}
  for key in file_path_dic.keys():
      print('{key}データの変換を開始'.format(key))
      df_dic = {}
      for i, company_zip in enumerate(file_path_dic[key]):
          # 進捗表示
          if i % 100 == 0:
              print('{i}ファイル目を開始'.format(i))
          company_name = os.path.splittext(os.path.basename(company_zip))[0].split('_')[0]
          doc_name = ps.path.splittext(os.path.basename(company_zip))[0].split('_')[1]

          if company_name not in df_dic: # 会社が辞書中に存在しない場合
              df_dic[company_name] = {}
              df_dic[company_name] = read_xbrl_from_zip(company_zip)[0]
          elif company_name in df_dic: # 会社が辞書中に存在する場合
              df_dic[company_name] = pd.concat( [df_dic[company_name],read_xbrl_from_zip(company_zip)[0]])

      all_df_dic[key] = df_dic

  return all_df_dic

# 会社のリストを読み込み
company_list = ['ホウスイ','カネコ種苗']

# 取得期間の設定:直近n日分
delta_day = 800
end = date.today()
start = date.today() - timedelta(days=delta_day)

# ダウンロードしたデータのフォルダパス
quart_dir_path = r'四半期報告書を保存する任意のフォルダパス'
securities_dir_path = r'有価証券報告書を保存する任意のフォルダパス'

# XBRLデータの取得
list_dic = get_list(start,end,company_list)
file_path_dic = get_zip(list_dic, quart_dir_path, securities_dir_path)

# XBRLからデータ形式を変換
df_dic = zip_to_df(file_path_list)

# 営業利益部分抽出
quart = all_df_dic['四半期報告書']['カネコ種苗']
quart_oi = quart[(quart['tag'] == 'OperatingIncome') & (quart['context'] == 'CurrentYTDDuration')]
quart_oi[['第N期', '終了日', '値']].sort_values('終了日')
quart_oi = quart_oi.rename({'終了日':'Date', '値':'OperatingIncome'}, axis=1).reset_index(drop=True)
quart_oi['type'] = '四半期報告書'

securities = all_df_dic['四半期報告書']['カネコ種苗']
securities_oi = securities[(securities['tag'] == 'OperatingIncome') & (securities['context'] == 'CurrentYTDDuration')]
securities_oi[['第N期', '終了日', '値']].sort_values('終了日')
securities_oi = securities_oi.rename({'終了日':'Date', '値':'OperatingIncome'}, axis=1).reset_index(drop=True)
securities_oi['type'] = '四半期報告書'

oi_df = pd.concat([quart_oi, securities_oi]).sort_values('Date').reset_index(drop=True)

# 各四半期ごとの営業利益や、前年同期比の売上高営業利益率の変化を計算
oi_df['tempOperatingIncome'] = oi_df['OperatingIncome'] - oi_df['OperatingIncome'].shift(1)
oi_df['CalcOperatingIncome'] = oi_df['OperatingIncome'].mask(oi_df['第N期'] == 0, oi_df['tempOperatingIncome'])
oi_df['CalcOperatingIncome'] = oi_df['CalcOperatingIncome'].mask(oi_df['第N期'] == 3, oi_df['tempOperatingIncome'])
oi_df['CalcOperatingIncome'] = oi_df['CalcOperatingIncome'].mask(oi_df['第N期'] == 2, oi_df['tempOperatingIncome'])
oi_df['CalcOperatingIncome_YoYchangerate'] = oi_df['CalcOperatingIncome'] / oi_df['CalcOperatingIncome'].shift(4)

# 棒グラフで可視化
oi_df.plot.bar(x='Date', y='CalcOperatingIncome', rot=45)

oi_df.plot.bar(x='Date', y='CalcOperatingIncome_YoYchangerate', rot=45)

明日からは短めのコードをかくこと。
その中で一番ためになったコードを説明してみることにする。

以上!



ソースコード元は
pythonで財務分析:EDINETから四半期ごとの情報を取得する | kiseno-log