見出し画像

【データの集め方講座】Pythonで株式情報を収集しMySQLに保存

はじめに


ごあいさつ

ご高覧いただきありがとうございます.
ソフトウェアエンジニアのKitaharaです.
本日はPythonを使った株式情報の収集方法を解説します!

筆者も趣味でこの方法を使ったコードをレンタルサーバーで自動実行しており, データを集めていますので非常に実用性の高い記事になっているのではないかなと思っています.  

なお, 本記事で利用するサイト「無尽蔵」ですが, 掲載の継続性が確約されているものではありません. あらかじめご了承ください.

株式情報のあれこれ


株式を取得すると何がいいのか

今回のテーマの株式ですが, 収集してみたいという方も多いのではないでしょうか?

ですが, 株式がどんなものか知らない方もいらっしゃると思うので, まずは株式が何かを紹介してから株式情報を収集することの有用性についてお話いたします.

株式の定義ですが, SMBC日興証券のサイトに用語集があり, 掲載されていましたので引用させていらだきます.

株式とは、株式会社が資金を出資してもらった人に対して発行する証券のことです。
株式の発行は、その企業が事業を行うために必要な資金を集める手段のひとつで、例えば会社が工場を建てて製品をつくる、お店を出して販売するといった場合に必要な資金を集める際に行われます。株式を発行して得た資金は、銀行借入や社債を発行して得た資金とは異なり、返済の義務はありません。出資した人(株主)はお金が返ってこない代わりに、保有株式の割合に応じた経営参加ができ、利益が出たときには保有株式数に応じて配当がもらえます。また、企業が成長し株式の価値が上がったときには、その株式を売却して利益を得ることができます。

SMBC日興証券 太字は筆者が追加

この用語集から分かる通り, 成長すると思った会社の株式を買ってその後会社が成長すると株式の値段が上がって売却益を得ることができます. 多くの人が株式情報を収集したいとなる理由はおそらく株式データを使って分析をし, 高騰しそうな株を見つけたいからではないでしょうか?

==================================================

株式情報をスクレイピングで取得するのは難しい

しかしながら, 現在日本において株式情報を取得することは難しいです.
その理由は多くの証券会社・株式情報サイトでスクレイピングが禁止されているからです.

例えばYahooファイナンスでは以下のように記載がされています.

Yahoo!ファイナンスでは、Yahoo!ファイナンスに掲載している株価やその他のデータを、プログラム等を用いて機械的に取得する行為(スクレイピング等)について、システムに過度の負荷がかかり、安定したサービス提供に支障をきたす恐れがあることから禁止しています。

また、Yahoo!ファイナンスに掲載する情報の著作権その他一切の権利は、ヤフー株式会社、情報提供者またはその他の権利者に帰属します。
当該掲載情報の転用、複製および外部配信ならびに販売を含む商用利用等の一切を固く禁じています。

株価データのダウンロードを利用したい場合は、「VIP倶楽部」の「時系列データダウンロード」をご利用ください。

YahooFinance 太字は筆者によるもの

理由はここに書かれている通り, システムに負荷がかかるからです.
株式情報を欲しい人(特にリアルタイム)だと1秒間に何回もリクエストを送ることが想定されますので, 負荷がかかってしまうのです.
そのため, 他のサイトでもスクレイピングが禁止されていることが多いです.

補足ですが, そもそも大量のリクエストによってによってサーバーに負荷をかけること自体迷惑行為(Dos攻撃とみなされることもあります)ですのでやらないように気を付けるべきです. もしリクエストを何回も投げることになる場合は専用のモジュール等で時間をかけるように調整し, サイト制作者様に迷惑をかけないようにしましょう.

なお, 今回利用する無尽蔵に関しては規約上問題がなく, かつリクエストの回数も一日一回で済むのでサイト制作者様に迷惑をかけることはないです.

==================================================

APIを利用しても同じ問題が発生する

上記で説明したスクレイピング以外にも手は実はあります.
他の記事でも紹介しているAPI(Application Programming Interface)を利用することです.

ですが, こちらも※APIのリクエストの制限があったりするのでスクレイピングと同じ問題に直面することになります.

==================================================

どのようにして取得するのか

今回は以下の流れでデータを取得し, 保存します.

(1) サイト無尽蔵から当日のデータをzipファイルで取得
(2) zipファイルを解凍し, CSVファイルを別ディレクトリに保存
(3) zipファイルを削除
(4) データをMySQLに格納
(5) csvファイルを削除

無尽蔵の特徴としてデータをCSVファイルで配布しているということがあります. CSVファイルの取得には一回のリクエストで済むわけですから実行時間が短いです.

使用するものの説明


  • 無尽蔵

    • 色々なデータを掲載しているデータサイト

      • CSVファイル形式で当日の株価データを取得することができます

    • 管理人によるとデータの更新が確約されているわけではないです

  • Python

    • プログラミング言語のひとつです.

    • 型宣言等が無く, 初心者にも扱いやすい言語だと言われています

    • 近年Deep Learningのライブラリが豊富であることから注目を集めている人気の言語です

    • 公式ドキュメント

  • MySQL

    • オラクル社によって開発されているSQLデータベース管理システム

    • SQLのデータベース管理システムの中でも根強い人気を誇っています

    • 公式ドキュメント

言語のバージョンと完成図


各言語のバージョン

使う言語はPython3とMySQLです.
なお, 絶対にこのバージョンじゃないと動かないというわけではないです. ご了承ください.

また, 筆者はcmdで作りましたが, Ubuntuでも同じように作れます
(venvのあとのアクティベーションがsource env/bin/activateになるだけです)

# MySQLのバージョンを確認する
mysql> select version();
+-----------+
| version() |
+-----------+
| 8.0.23    |
+-----------+
1 row in set (0.00 sec)
# Pythonのバージョンを確認する
(env) C:\Training\Kabu>python --version
Python 3.10.0

今回作るものの完成図

.
├── csv
├── env
│   ├── Include
│   ├── Lib
│   ├── Scripts
│   └── pyvenv.cfg
├── main.py
└── tmp

環境構築


Pythonの仮想環境を作る

まずはPythonの仮想環境を作成します.
仮想環境を作成することでローカルにインストールされたPythonのライブラリの影響を避けることができるので開発しやすくなります.

まず適当な開発用のディレクトリに移動してください.

# 開発用のディレクトリに移動
cd YOUR_PROJECT_DIR
# 仮想環境を作成する
python -m venv env

仮想環境ができたらアクティベートしておきましょう.
仮想環境が立ち上がると環境名がcmdの画面の左側に()付き表示されます.

# 仮想環境をアクティベート
.\env\Scripts\activate.bat
# Linuxの場合はsource enb/bin/activate

MySQLのデータベース・テーブルを作成しておく

利用するデータベースとテーブルを作成しておきましょう

# データベースを作成する
>mysql CREATE DATABASE YOUR_DATABASE_NAME

# テーブルを作成する
mysql> create table YOUR_DATABASE_NAME.stocks (
    id int AUTO_INCREMENT not null PRIMARY KEY,
    date date not null,
    stock_name varchar(50) not null,
    stock_code int not null,
    open float not null, 
    high float not null,  
    low float not null,
    close float not null,   
    volume float not null, 
    market varchar(10) not null
);

一次的にファイルを保存するディレクトリを作成する

株データをzipファイルで取得し, csvファイルを取り出すという作業をするので一時的にファイルを入れておくディレクトリを作成しておきましょう.

また, この後使用するのでmain.pyも作成しておいてください.

.
├── csv # このファイルを作る
├── env
│   ├── Include
│   ├── Lib
│   ├── Scripts
│   └── pyvenv.cfg
├── main.py
└── tmp # このファイルを作る

以上で環境構築は終了です.
お疲れ様でした.

株式データを取得


開発用のディレクトリ直下にmain.pyを作成してください

# main.py
# 使用するモジュールのimport
# PyMySQLはあらかじめpip installしてください

import urllib.error
import urllib.request
import zipfile
import os
import datetime
import csv
import pymysql.cursors

インポートが終わったら無尽蔵から株式データをダウンロードするファイルを作成していきましょう.

ダウンロードするにはまず, URLの指定をする必要があります.
無尽蔵のURLは

  • year: 年

  • month: 月(常に2桁)

  • day: 日付(常に2桁)

  • year_last_tow_digits: yearの下二桁

とするときに

"http://mujinzou.com/d_data/"+year+"d/"+year_last_two_digits+"_"+month+"d/T"+year_last_two_digits+month+day+".zip"

となっていますので先程挙げた四つのパラメータをdatetime.datetime.now()から加工して作成します.

あとはコードを追っていけば理解できるものだとおもわれますが, 最後にreturnを設定していることに注意してください. これはデータを登録するための関数で該当するCSVファイルを使用するためにreturnしています.

以下がコードです.

# main.py

def download_kabu_data():
    # ダウンロードで使う日付データを取得し使うものをstr型でまとめる
    # year: 年, mondth: 月(常に2桁), day: 日付(常に2桁), year_last_tow_digits: yearの下二桁
    datetime_data = datetime.datetime.now()
    year = datetime_data.year
    year_last_two_digits = str(year)[2:]

    month = datetime_data.strftime('%m')
    day = datetime_data.strftime('%d')

    file_url = "http://mujinzou.com/d_data/"+str(year)+"d/"+\
        year_last_two_digits+"_"+month+"d/T"+year_last_two_digits+month+day+".zip"

    save_path = "./tmp/download.zip"

    # file_urlからsave_pathにzipファイルをダウンロード
    try:
        with urllib.request.urlopen(file_url) as download_file:
            data = download_file.read()
            with open(save_path, mode='wb') as save_file:
                save_file.write(data)
    except urllib.error.URLError as e:
        print(e)

    # zipファイルの中身を./csv/に展開
    with zipfile.ZipFile("./tmp/download.zip") as obj_zip:
        # zipから指定ファイル(第1引数)を取得して、指定ディレクトリ(第2引数)に保存する
        obj_zip.extract("T"+year_last_two_digits+month+day+".csv", "./csv/")

    # ダウンロードしたファイルを削除
    os.remove('tmp/download.zip')

    return "csv/"+"T"+year_last_two_digits+month+day+".csv"

次にデータを登録していきます.
csvファイルの読み込みですとcsv.readerを使うほかにpandas.read_csv()を使うという手がありますが, csvの方が簡潔に書けるのでこちらを採用しました.

使い方は簡単でfor文(他の言語でいうforeach文)に入れると一行ごとにリストとして取得できますので, それらをデータを保存する形にして, MySQLに接続するだけです.

connectionの設定データは「環境構築」の章で作ったものを各自で入れてください.

def registerate_kabu_data(file_path):
    with open(file_path) as f:
        reader = csv.reader(f)
        # ループ回数:約4000回
        for row in reader:
            date = row[0].replace('/','-')
            stock_code = int(row[1])
            stock_name = row[3][4:].replace('\u3000','')
            open_data = float(row[4])
            high = float(row[5])
            low = float(row[6])
            close = float(row[7])
            volume = float(row[8])
            market = row[9]

            # データベースに接続
            connection = pymysql.connect(host='localhost',
                                        user='YOUR_USER_NAME',
                                        password='YOUR_MYSQL_PASSWORD',
                                        db='YOUR_DATABASE',
                                        charset='utf8mb4',
                                        cursorclass=pymysql.cursors.DictCursor)

            try:
                with connection.cursor() as cursor:
                    sql = "INSERT INTO your_table (date, stock_name, stock_code, open, high, low, close, volume, market) VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s);"
                    cursor.execute(sql, (date, stock_name, stock_code, open_data, high, low, close, volume, market))
                    connection.commit()
            finally:
                connection.close()
    
    # csvファイルを削除
    os.remove(file_path)

最後にファイルを呼び出したときに実行をするコードを書きます

if __name__ == '__main__':
    file_path = download_kabu_data()
    registerate_kabu_data(file_path)

MySQLで上手くいっているか確認しましょう

mysql> use YOUR_DATABASE
mysql> select * from your_table

おわりに


今回はPythonとMySQLを使って株式情報を取得し保存する方法を解説しました!参考になったという方はぜひハートボタンを押していってください!

やる気が出ます!

冒頭にもありましたが, 私はこの方法でデータを集めたあと, PHPとJavaScriptで可視化しています. 興味のある人が多ければそちらも記事にしようかとおもっておりますので, 是非ご感想お待ちしております.

記事内で不明な点等ございましたら気軽にご連絡ください.

Twitter: @kitahara_dev
email: kitahara.main1@gmail.com

補足


※がついている部分に関する解説です

  • APIのリクエスト制限

    • 株式のAPIに限らず, 多くの無料のAPIにはリクエスト回数の制限があります. 300回/1h というようなイメージです.

    • リクエスト制限を超えるとリクエストを受け取ることができません.

    • なので, 株式情報のような何千回とリクエストを送る必要のある場合は事前にこのようなリクエスト制限があるかどうかを確認する必要があります.

この記事が気に入ったらサポートをしてみませんか?