Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

適時開示情報の取得

More than 1 year has passed since last update.

JPXの適時開示情報のページを参照閲覧する

tekiji_kaiji.py
from urllib.request import urlopen
from bs4 import BeautifulSoup
import pandas as pd

def fn_test(url):

      #変数設定
      a,b,c,d,e,f  = [],[],[],[],[],[] #リストを6つ用意
      df = pd.DataFrame() #取得結果格納用のデータフレーム

      #ページの閲覧
      html = urlopen(url)
      bsObj = BeautifulSoup(html, "html.parser")    
      tbl3 = bsObj.findAll("table")[3]
      trs = tbl3.findAll("tr")

      for tr in trs:
            lst=[]
            tds = tr.findAll('td') 
            for td in tds:
                  #各tdの値を各リストに各々格納
                  if td.get("class")[1] =="kjTime":a += [td.text ] #開示時刻
                  if td.get("class")[1] =="kjCode":b += [td.text ] #コード
                  if td.get("class")[1] =="kjName":c += [td.text ] #社名
                  if td.get("class")[1] =="kjTitle":d += [td.text ] #表題
                  if td.get("class")[1] =="kjTitle": #pdfのリンクURL
                      e += [td.a.get("href") ] if td.a is not None else [td.a ] 
                  if td.get("class")[1] =="kjXbrl" : #XBRLのDLリンク
                      f += [td.a.get("href") ] if td.a  is not None else [td.a ] 

      #取得結果格納リスト群からデータフレーム生成
      df = pd.DataFrame(
              data={'A': a, 'B': b, 'C': c, 'D': d, 'E': e, 'F': f},
              columns=['A', 'B', 'C', 'D', 'E', 'F'])        
      return df 

# 日付
date = '20190426' #900件超
#date = '20190502' #0件
#date = '20190506' #1件

# URL文字列の生成
url0 = 'https://www.release.tdnet.info/inbs/'
url1 = url0  +  'I_list_{}_{}.html'.format('001',date)

# 該当URLを閲覧
html = urlopen(url1)
bsObj = BeautifulSoup(html, "html.parser")
tbl1 = bsObj.findAll("table")[1]

dv1 = tbl1.findAll("div",{"class":"kaijiSum"})
dv2 = tbl1.findAll("div",{"class":"pager-O"})
dv3 = tbl1.findAll("div",{"class":"pager-M"})

if dv1 ==[]:
   print('開示0件')
else:
    print(str(dv1).split('全')[1].split('</')[0])
    lst =[ int(i.string) for i in dv3]
    if lst ==[]:
        df  = fn_test(url1)    
        print(df)
    else:
        # ページ数の取得
        mxpg= max(lst) 
        print( mxpg ) 

        # 再度URL文字列の生成
        for i in range(mxpg):
              s = str(i + 1)
              url1= url0  + 'I_list_{}_{}.html'.format(s.zfill(3) ,date)      
              print(s , url1)

              # ページを逐次閲覧して開示情報を取得
              df = fn_test(url1)
              print(df)

まざりもの氏のブログを参考に、JPXの適時開示情報ページを閲覧して、開示情報を取得するスクリプトを書いてみた。
・JPXの適時開示情報のWebページはiframeタグ(インラインフレーム)で構成されているので、埋め込まれている方のURL(ページ番号+日付yyyymmdd)を直接参照してbeautifulsoupでWebスクレイピングするようなイメージで逐次適時開示情報を取得。

・最初に001ページの先頭にある上部のテーブルからページ数を取得して、そのページ数の分だけループ処理で逐次ページを閲覧して開示情報を取得格納するイメージ。また日によっては開示が0件であったり、あるいは開示件数が少なくて次ページがない001ページのみの場合があるので、上記スクリプトでは分岐させている。

このページによると、各列の値を格納するリスト群を用意して、例えば6つの列のあるHTMLテーブルの情報をpandasのデータフレームオブジェクトを生成しようとする場合、各列に対応するlistを6つ(A列用のリスト、B列用のリスト、C列用のリスト、D列用のリスト、E列用のリスト、F列用のリスト)用意して上記のようにオブジェクト生成した方が処理が早いとのことなので参考にしました。(自分今までは1行ずつレコードのデータをリストで生成して、1件ずつappendか何かでデータフレームオブジェクトに行追加していくイメージで、pandasのデータフレームオブジェクトを生成していたような気が汗...)

・適時開示のページは閲覧可能な日付が1ヶ月分であり、過去のデータは閲覧できない。なので毎日逐次閲覧して取得格納するイメージの運用になるのかなと思われ。(過去分の適時開示情報を参照したい場合は、日経電子版or株探or四季報オンラインなどを参照する必要があるかと。)
・生成したpandasデータフレームはto_sql()などでご本尊のRDBなどに接続して、最寄りのデータベースの最寄りのテーブルに格納しておく的な後続処理が必要になってくるかと。(今回は割愛)

・決算短信にはXBRLファイルのDLリンクが付いているので、忘れずに取得しておくべし。想定される後続処理としては、これら決算短信のXBRLファイルをダウンロードして、XBRLファイルをパースして数値等を取得してデータベースに格納するといった処理が考えられる。

・ただし決算短信以外の情報にはXBRLファイルが付いていない。例えば業績予想の修正の会社リリースや長期経営計画の会社リリースにはXBRLファイルが付いていない。投資家的には、XBRLの付いていないこれら業績予想の修正や長期経営計画の会社リリースの方が欲しいのかもしれないですね。(その場合はXBRLが付いていないので、pdfをダウンロードして、pdftotextなどでテキスト情報に変換処理が必要になってくるかと)

・欧米ではアルゴリズム取引が盛んらしく、提出書類をテキストマイニングで瞬時に読み込んで、売りか買いかを瞬時にジャッジメントして取引を大量に実行するようなので。上記スクリプトもそういうアルゴ取引の方向に活用改良すればいいんじゃなくね?と思うものの。さはさりながらも日本の現在の適時開示の状況を鑑みると、大多数の発表が後場が閉まった午後3時以降の発表が多いことを考えると、秒殺処理をする必要性は低いのかも(なので翌日のマーケットが開く朝9時までに処理が完了できればOKよ的なイメージ?いや知らんけど)

おまけ:有報キャッチャーのAPIを利用する

ufo_catcher_api.py
import requests
from bs4 import BeautifulSoup

sic=9658
url='http://resource.ufocatch.com/atom/tdnetx/query/'+str(sic)
r = requests.get(url)
soup = BeautifulSoup( r.text,'html.parser')
enty = soup.find_all("entry")

print(enty)

・自分は今まで「有報キャッチャー」は、有価証券報告書や四半期報告書といったEDINETの提出書類が利用できるAPIだと思っていましたが、どうやらTDNETの開示書類も閲覧可能との事。atomの種類は「tdnet」もしくは「tdnetx」(XBRLが付いた書類限定)と指定してあげれば、TDNETつまり適時開示の書類も参照可能。
・何件か観察してみたが。12時に発表があった決算短信が1分後に有報キャッチャーAPIでも検索できたので、こちらを利用してもいいかもしれませんね!(ただし決算発表が集中する日に同等の速度が出ているかは不明、ていうか未確認)

追記(2019/05/11)

昨日(5/10)は開示が1600件超あって、適時開示情報のページが17ページに及ぶくらい決算発表が集中した日でした。上記のスクリプトだと10ページ以上のページが取得できないため、変数dv3にページ数の上限が取得できずに途中でエラーで落ちます。要改良。

Fortinbras
Go, bid the soldiers shoot.
https://connpass.com/user/fortinbras/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away