メむンコンテンツぞスキップ
芋出し画像

【デヌタの集め方講座】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 ずいうようなむメヌゞです.

      • リク゚スト制限を超えるずリク゚ストを受け取るこずができたせん.

      • なので, 株匏情報のような䜕千回ずリク゚ストを送る必芁のある堎合は事前にこのようなリク゚スト制限があるかどうかを確認する必芁がありたす.

     
     

    Kitahara

     
     
    Software Engineer Language: Python/JavaScript Certification: JSSC Grade Pre-1 デヌタの収集ず可芖化の方法を発信しおいたす

    あなたぞのおすすめ