AB型技術系 主に備忘録

ほぼプログラム関連の備忘録

スクレイピングした株価情報をjson形式で出力しFTPでサーバーにアップロードする

前回保有している株の株価情報をスクレイピングしてjson形式のファイルに出力することができました。

freelancer.hatenablog.jp

このファイルを元に最終的にはスターサーバー上のMySQLに登録したいのでまずはFTPを使ってアップロードできるようにします。

サンプルプログラム

import requests
import json
import time
import ftplib
from bs4 import BeautifulSoup
    
def getText(el):
    """指定した要素内の文字列を返す

    Args:
        el (bs4.element.ResultSet): 要素

    Returns:
        str: 要素内の文字列
    """
    if el is not None:
        return el.getText()
    return ""

# 処理件数
cnt = 0

# システム日付
sysDate = ""

# 銘柄情報リスト
stockInfoList = []

# 保有している銘柄コードを取得する自前のAPI 
# スターサーバー上のMySQLからデータを取得し下記の形式で返します
# [{"stock_cd": "1942"}, {"stock_cd": "2730"}
res = requests.get("http://xxx.yyy.zzz/codeList")

# JSONに変換
data = json.loads(res.text)

# 銘柄コード毎に株価情報を取得
for cd in data:

    # 上限設定
    if cnt == 50:
        break

    # 株価情報取得
    res = requests.get("https://kabutan.jp/stock/?code=" + cd["stock_cd"])
    
    # レスポンスの解析
    doc = BeautifulSoup(res.text, "html.parser")
    
    # 株価情報の取得
    elPrice = doc.select("#kobetsu_left tr")
    
    # タイトルの取得 [<th scope="row">終値</th>]
    elTitle = doc.select("#kobetsu_left th")
    
    # 銘柄名の取得
    name = doc.select_one(".si_i1_1 h2")

    # 銘柄名が取得できない場合はスキップ
    if name is None:
        continue

    # 銘柄情報
    stockInfo = {}

    # 銘柄名を設定 銘柄コード+銘柄名で文字列を取得するので銘柄コードをブランクにする
    stockInfo["stock_cd"] = cd["stock_cd"]
    stockInfo["stock_na"] = name.getText().replace(cd["stock_cd"], "")

    # システム日付が未指定の場合は日付を取得
    if sysDate == "":

        # システム日付の取得 [<time datetime="2021-10-08">10月08日</time>]
        elDate = doc.select("#kobetsu_left h2>time")
        if elDate is None:
            break;
        
        # システム日付を(yyyymmdd形式)にする
        sysDate = elDate[0].attrs["datetime"].replace("-", "")
        
    # タイトルの解析
    if  elTitle is not None:

        # 始値、高値、安値、終値、出来高が存在しない場合はスキップする
        if len(elTitle) < 5:
            continue

        if elTitle[0].getText() != "始値":
            continue

        if elTitle[1].getText() != "高値":
            continue

        if elTitle[2].getText() != "安値":
            continue

        if elTitle[3].getText() != "終値":
            continue

        if elTitle[4].getText() != "出来高":
            continue

    # 銘柄情報の設定
    if elPrice is not None and len(elPrice) >= 5:
        stockInfo["open_price"] = getText(elPrice[0].select_one("td")).replace(",", "")
        stockInfo["high_price"] = getText(elPrice[1].select_one("td")).replace(",", "")
        stockInfo["low_price"] = getText(elPrice[2].select_one("td")).replace(",", "")
        stockInfo["closing_price"] = getText(elPrice[3].select_one("td")).replace(",", "")
        stockInfo["vol"] = getText(elPrice[4].select_one("td")).replace("\u00a0\u682a", "").replace(",", "")
        stockInfoList.append(stockInfo)
    
    # カウントアップ
    cnt+=1

    # 1秒停止
    time.sleep(1)

if sysDate != "":
    dt = {}
    dt["dt"] = sysDate
    dt["stock_info"] = stockInfoList
    filePath = "C:/data/"
    fileNa = sysDate + "_stock_price.json"
    with open(filePath + fileNa, mode='a') as fo:
        fo.write(json.dumps(dt))

    with ftplib.FTP() as ftp:
        try:
            # FTPサーバーに接続
            ftp.connect(host="aaa.bbb.ccc", port=21, timeout=30)
            # パッシブモードに設定
            ftp.set_pasv(1)
            # FTPサーバー ログイン
            ftp.login("username", "password")
            with open(filePath + fileNa, 'rb') as fp:
                ftp.storbinary("STOR /server/json/" + fileNa, fp)
        except ftplib.all_errors as e:
            print(e)

標準モジュールのftplibを使ってFTPを使ってサーバーにアップロードする処理を追加しました。

実行結果

f:id:freelancer13:20211014013016p:plain
アップロードしたディレクトリのファイル一覧

jsonファイルをアップロードすることができました。

次にやりたいこと

アップロードしたjsonファイルを読み込んで結果を表示するページを作成する