【データの集め方講座】Pythonで株式情報を収集しMySQLに保存
はじめに
ごあいさつ
ご高覧いただきありがとうございます.
ソフトウェアエンジニアのKitaharaです.
本日はPythonを使った株式情報の収集方法を解説します!
筆者も趣味でこの方法を使ったコードをレンタルサーバーで自動実行しており, データを集めていますので非常に実用性の高い記事になっているのではないかなと思っています.
なお, 本記事で利用するサイト「無尽蔵」ですが, 掲載の継続性が確約されているものではありません. あらかじめご了承ください.
株式情報のあれこれ
株式を取得すると何がいいのか
今回のテーマの株式ですが, 収集してみたいという方も多いのではないでしょうか?
ですが, 株式がどんなものか知らない方もいらっしゃると思うので, まずは株式が何かを紹介してから株式情報を収集することの有用性についてお話いたします.
株式の定義ですが, SMBC日興証券のサイトに用語集があり, 掲載されていましたので引用させていらだきます.
この用語集から分かる通り, 成長すると思った会社の株式を買ってその後会社が成長すると株式の値段が上がって売却益を得ることができます. 多くの人が株式情報を収集したいとなる理由はおそらく株式データを使って分析をし, 高騰しそうな株を見つけたいからではないでしょうか?
==================================================
株式情報をスクレイピングで取得するのは難しい
しかしながら, 現在日本において株式情報を取得することは難しいです.
その理由は多くの証券会社・株式情報サイトでスクレイピングが禁止されているからです.
例えばYahooファイナンスでは以下のように記載がされています.
理由はここに書かれている通り, システムに負荷がかかるからです.
株式情報を欲しい人(特にリアルタイム)だと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
言語のバージョンと完成図
各言語のバージョン
使う言語は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 というようなイメージです.
リクエスト制限を超えるとリクエストを受け取ることができません.
なので, 株式情報のような何千回とリクエストを送る必要のある場合は事前にこのようなリクエスト制限があるかどうかを確認する必要があります.
この記事が気に入ったらサポートをしてみませんか?