ヤフーファイナンス」タグアーカイブ

Pythonを使ってヤフーファイナンス日経平均株価の時系列を取得、スクレイピング

Python を使ってヤフーファイナンス 日経平均株価の時系列を取得、スクレイピング
#https://stocks.finance.yahoo.co.jp/stocks/history/?code=998407.O
#日経平均株価の時系列のテーブル表から該当の文字列を取得する、日付 始値 高値 安値 終値

import time
from selenium import webdriver
import csv
import datetime
import os

class jikeiretsu:
    def __init__(self,day,kopen,khigh,klow,kclose):
        self.day=day
        self.kopen=kopen
        self.khigh=khigh
        self.klow=klow
        self.kclose=kclose
        
class yahooFinanceTimeline:
    def __init__(self):
        self.hello="yahoo Finace"
        
    def getTimeline(self):
        #print("カプセルにして取得")
         #動作確認のためのメソッド
        # 仮想ブラウザ起動、URL先のサイトにアクセス
        driver = webdriver.Chrome('/usr/local/bin/chromedriver')#ここでエラーになったらパスが違うかchromedriverをインストールする
        #他のエラーで、「unexpectedly exited. Status code was:-9」だったら、Macの場合はシステム環境設定 → セキュリティとプライバシー で許可すればよい
        url='https://stocks.finance.yahoo.co.jp/stocks/history/?code=998407.O'
        driver.get(url)
        time.sleep(1)
        #title = driver.title
        #print(title)
        main = driver.find_element_by_id("main")
        el = main.find_element_by_css_selector(".padT12.marB10.clearFix")
        tableElem = el.find_element_by_tag_name("table")
        trs = tableElem.find_elements_by_tag_name("tr")
        ths = trs[0].find_elements_by_tag_name("th")
        kabuka=""
        #thタグは1行目のTRにだけ存在する。
        for f in range(0,len(ths)):#日付	始値	高値	安値	終値
            ths[f].text
            kabuka+=ths[f].text+" "
        print(kabuka)
        jikeiretsuArray=[]
        for i in range(0,len(trs)):
            tds = trs[i].find_elements_by_tag_name("td")
            if len(tds)>=5:
                getJikeiretsu=jikeiretsu(tds[0].text,tds[1].text,tds[2].text,tds[3].text,tds[4].text)
                jikeiretsuArray.append(getJikeiretsu)
            else: 
                print("tdsの数が足りない行があるので無視")
        time.sleep(1)    
        driver.close()#起動したウィンドウを閉じる
        print("通常出力日付	始値	高値	安値	終値")
        for f in range(0,len(jikeiretsuArray)):
            print(jikeiretsuArray[f].day,jikeiretsuArray[f].kopen,jikeiretsuArray[f].khigh,jikeiretsuArray[f].klow,jikeiretsuArray[f].kclose)
        print('+----------------------+')
        print("個人的出力順、CSVカンマ区切りで 桁区切りのカンマは削除、昇順day,High,Low,Open,Close,AdjClose")#("個人的な利用の出力順、昇順day,High,Low,Open,Close,AdjClose")    
        count=len(jikeiretsuArray)
        tmpstr=""    
        for n in reversed(range(count)):#).replace(',','') カンマを削除
            tmpstr=jikeiretsuArray[n].day+","+jikeiretsuArray[n].khigh.replace(',','')+","+jikeiretsuArray[n].klow.replace(',','')+","+\
                  jikeiretsuArray[n].kopen.replace(',','')+","+jikeiretsuArray[n].kclose.replace(',','')+","+\
                  jikeiretsuArray[n].kclose.replace(',','')
            print(tmpstr)

    #テスト用のメソッドなので実際は不要なメソッド        
    def getTimelineTest(self):
        print("test")
        #動作確認のためのメソッド
        # 仮想ブラウザ起動、URL先のサイトにアクセス
        driver = webdriver.Chrome('/usr/local/bin/chromedriver')#ここでエラーになったらパスが違うかchromedriverをインストールする
        #他のエラーで、「unexpectedly exited. Status code was:-9」だったら、Macの場合はシステム環境設定 → セキュリティとプライバシー で許可すればよい
        url='https://stocks.finance.yahoo.co.jp/stocks/history/?code=998407.O'
        #driver.get(url+str(code)+'.T')
        driver.get(url)
        time.sleep(1)
        #title = driver.title
        #print(title)
        main = driver.find_element_by_id("main")
        #el = main.find_element_by_id("stockinf")
        #nextClass = el.find_element_by_css_selector(".stocksDtl.clearFix")
        el = main.find_element_by_css_selector(".padT12.marB10.clearFix")
        tableElem = el.find_element_by_tag_name("table")
        trs = tableElem.find_elements_by_tag_name("tr")
        ths = trs[0].find_elements_by_tag_name("th")
        kabuka=""
        #thタグは1行目のTRにだけ存在する。
        for f in range(0,len(ths)):#日付	始値	高値	安値	終値
            ths[f].text
            kabuka+=ths[f].text+" "
        print(kabuka)
        kabuka=""
        for i in range(0,len(trs)):
            tds = trs[i].find_elements_by_tag_name("td")
            for m in range(0,len(tds)):
                kabuka+=tds[m].text+" "#ここはカプセルにしてクラスオブジェクトを配列に入れたほうがいいかも
                #print(kabuka)
            print(kabuka)
            kabuka=""
        time.sleep(1)    
        driver.close()#起動したウィンドウを閉じる
###START
print("START#####################################")
print("Japan yahoo financeの日経平均株価の時系列")
getstock=yahooFinanceTimeline()
getstock.getTimeline()

print("End#####################################")

 

出力例

START#####################################
Japan yahoo financeの日経平均株価の時系列
カプセルにして取得
日付 始値 高値 安値 終値 
tdsの数が足りない行があるので無視
通常出力日付	始値	高値	安値	終値
2021年2月16日 30,229.46 30,714.52 30,191.65 30,467.75
2021年2月15日 29,662.41 30,092.34 29,662.41 30,084.15
2021年2月12日 29,635.88 29,650.51 29,417.32 29,520.07
2021年2月10日 29,412.55 29,562.93 29,368.18 29,562.93
2021年2月9日 29,435.61 29,585.75 29,350.48 29,505.93
2021年2月8日 28,831.58 29,400.56 28,817.6 29,388.5
2021年2月5日 28,631.46 28,785.71 28,548.27 28,779.19
2021年2月4日 28,557.46 28,600.22 28,325.89 28,341.95
2021年2月3日 28,482.71 28,669.95 28,402.3 28,646.5
2021年2月2日 28,207.48 28,379.31 28,089.12 28,362.17
2021年2月1日 27,649.07 28,107.1 27,649.07 28,091.05
2021年1月29日 28,320.72 28,320.72 27,629.8 27,663.39
2021年1月28日 28,169.27 28,360.48 27,975.85 28,197.42
2021年1月27日 28,665.34 28,754.99 28,542 28,635.21
2021年1月26日 28,696.3 28,740.71 28,527.81 28,546.18
2021年1月25日 28,698.89 28,822.29 28,566.85 28,822.29
2021年1月22日 28,580.2 28,698.18 28,527.16 28,631.45
2021年1月21日 28,710.41 28,846.15 28,677.61 28,756.86
2021年1月20日 28,798.74 28,801.19 28,402.11 28,523.26
2021年1月19日 28,405.49 28,720.91 28,373.34 28,633.46
+----------------------+
個人的出力順、カンマを削除、昇順day,High,Low,Open,Close,AdjClose
2021年1月19日,28720.91,28373.34,28405.49,28633.46,28633.46
2021年1月20日,28801.19,28402.11,28798.74,28523.26,28523.26
2021年1月21日,28846.15,28677.61,28710.41,28756.86,28756.86
2021年1月22日,28698.18,28527.16,28580.2,28631.45,28631.45
2021年1月25日,28822.29,28566.85,28698.89,28822.29,28822.29
2021年1月26日,28740.71,28527.81,28696.3,28546.18,28546.18
2021年1月27日,28754.99,28542,28665.34,28635.21,28635.21
2021年1月28日,28360.48,27975.85,28169.27,28197.42,28197.42
2021年1月29日,28320.72,27629.8,28320.72,27663.39,27663.39
2021年2月1日,28107.1,27649.07,27649.07,28091.05,28091.05
2021年2月2日,28379.31,28089.12,28207.48,28362.17,28362.17
2021年2月3日,28669.95,28402.3,28482.71,28646.5,28646.5
2021年2月4日,28600.22,28325.89,28557.46,28341.95,28341.95
2021年2月5日,28785.71,28548.27,28631.46,28779.19,28779.19
2021年2月8日,29400.56,28817.6,28831.58,29388.5,29388.5
2021年2月9日,29585.75,29350.48,29435.61,29505.93,29505.93
2021年2月10日,29562.93,29368.18,29412.55,29562.93,29562.93
2021年2月12日,29650.51,29417.32,29635.88,29520.07,29520.07
2021年2月15日,30092.34,29662.41,29662.41,30084.15,30084.15
2021年2月16日,30714.52,30191.65,30229.46,30467.75,30467.75
End#####################################

 

Pythonを使ってヤフーファイナンス情報を取得、スクレイピング

#複数企業コード対応版 企業コードから企業名と株価を取得する
#Anaconda JupyterLabによる動作 Shift+Enterで実行になる

動作環境:MacOS 、Python、Anaconda JupyterLab

面倒だった点は、複数タグが存在するタグ名tr,td,ddの扱い。複数の場合forで回して配列みたいにしてデータを取得する必要があるし、スペースが含まれるクラス名は別のプロパティ?で読み込む必要がある。

find_element_by_class_nameでスペースを含むクラス名はエラーとなるので、find_element_by_css_selectorとしてドット.で接続する。

誤り:el.find_element_by_class_name(‘stocksDtl clearFix’)

正:el.find_element_by_css_selector(“.stocksDtl.clearFix”)

以下はサンプルコード。使い方は、codelistに企業コードを入力すると、ヤフーファイナンスからスクレイピングして「コード、企業名、終値株価、前日比、日付」を半角スペース区切りで出力するだけ。ヤフーファイナンスに接続するときは、取得間隔を1,2秒程度空けている。連続で取得するとサーバ負荷が増えるから強制切断とかアクセスをブロックされてしまうかもしれない。

>>コード修正、Spanタグが存在しない時間帯があるみたいなので、存在するかどうかのチェックを追記した。2021年2月8日、12時06分

import time
from selenium import webdriver
import csv
import datetime
import os

codelist=[]
codelist=[6315,2207,6928,5724,2702]#企業コード、複数

def getName(code):
    # 仮想ブラウザ起動、URL先のサイトにアクセス
    driver = webdriver.Chrome('/usr/local/bin/chromedriver')#ここでエラーになったらパスが違うかchromedriverをインストールする
    #他のエラーで、「unexpectedly exited. Status code was:-9」だったら、Macの場合はシステム環境設定 → セキュリティとプライバシー で許可すればよい
    url='https://stocks.finance.yahoo.co.jp/stocks/detail/?code='
    driver.get(url+str(code)+'.T')
    #time.sleep(1)
    #title = driver.title
    #print(title)
    main = driver.find_element_by_id("main")
    el = main.find_element_by_id("stockinf")

    #エラー、nextClass = el.find_element_by_class_name('stocksDtl clearFix') Classにスペースが含まれるとエラーになるので別のメソッドにする
    nextClass = el.find_element_by_css_selector(".stocksDtl.clearFix")
    subNextClass = nextClass.find_element_by_class_name("forAddPortfolio")
    tableElem = subNextClass.find_element_by_class_name("stocksTable")
    dlElem = subNextClass.find_element_by_css_selector(".stocksInfo.clearFix")
    
    dds = dlElem.find_elements_by_tag_name("dd")
    trs = tableElem.find_element_by_tag_name("tr")
    symbol = trs.find_element_by_class_name("symbol")
    name = symbol.find_element_by_tag_name("h1")
    stockinfo = []
    stockinfo.append(str(code))
    stockinfo.append(name.text)
    tds = trs.find_elements_by_tag_name("td")
    
    for j in range(0,len(tds)):
        if tds[j].text != "":
            stockinfo.append(tds[j].text)

    ##ddタグの中に spanタグがあって、他に文字がある。spanタグのテキストだけが取得したかった。
    ##>>追記 2021年2月8日エラー処理を追加
    if len(dds[1].find_elements_by_tag_name("span"))>0:#存在チェック elementでなくてelementsにする
        stockinfo.append(dds[1].find_element_by_tag_name("span").text)#日付
    output=stockinfo
    driver.close()#起動したウィンドウを閉じる
    return output

###START
print("START#####################################")
tmpStr=""
f=0
for i in codelist:
    outputStr=getName(i)
    #コード、企業名、終値株価,前日比、日付
    for m in outputStr:
        if f==2:
            tmpStr+=m+'円'+' '
        else:
            tmpStr+=m+' '
        f+=1
        #print(outputStr[0],outputStr[1],outputStr[2]+"円",outputStr[3],outputStr[4])
    print(tmpStr)
    tmpStr=""
    f=0
    time.sleep(2)
print("End#####################################")

 

更に修正した。メソッドをクラスにした。また始値、高値、安値を入れた。2021/02/12

#Python を使って#ヤフーファイナンス 情報を取得、#スクレイピング 
#複数企業コード対応版 企業コードから企業名と株価を取得する
#Anaconda JupyterLabによる動作 Shift+Enterで実行になる
#修正、クラスに変更
#修正2021/02/12、始値、高値、安値を入れた

#手作業はcodelistにコードを入れる
import time
from selenium import webdriver
import csv
import datetime
import os

codelist=[]
codelist=[6134,7952,6462
         ]#企業コード、複数
#これからは、どんなに小さなプログラムでもクラスを使用する。そのほうが汎用性がある。
#同じメソッド名でもクラス名が異なればコピペして使用できる
class yahooFinanceClass():
        def __init__(self):
            self.hello="yahoo Finace"
        
        def getName(self,code):
            # 仮想ブラウザ起動、URL先のサイトにアクセス
            driver = webdriver.Chrome('/usr/local/bin/chromedriver')#ここでエラーになったらパスが違うかchromedriverをインストールする
            #他のエラーで、「unexpectedly exited. Status code was:-9」だったら、Macの場合はシステム環境設定 → セキュリティとプライバシー で許可すればよい
            url='https://stocks.finance.yahoo.co.jp/stocks/detail/?code='
            driver.get(url+str(code)+'.T')
            time.sleep(1)
            #title = driver.title
            #print(title)
            main = driver.find_element_by_id("main")
            el = main.find_element_by_id("stockinf")

            #エラー、nextClass = el.find_element_by_class_name('stocksDtl clearFix') Classにスペースが含まれるとエラーになるので別のメソッドにする
            nextClass = el.find_element_by_css_selector(".stocksDtl.clearFix")
            subNextClass = nextClass.find_element_by_class_name("forAddPortfolio")
            tableElem = subNextClass.find_element_by_class_name("stocksTable")
            dlElem = subNextClass.find_element_by_css_selector(".stocksInfo.clearFix")

            dds = dlElem.find_elements_by_tag_name("dd")
            trs = tableElem.find_element_by_tag_name("tr")
            symbol = trs.find_element_by_class_name("symbol")
            name = symbol.find_element_by_tag_name("h1")
            stockinfo = []
            stockinfo.append(str(code))
            stockinfo.append(name.text)
            tds = trs.find_elements_by_tag_name("td")

            for j in range(0,len(tds)):
                if tds[j].text != "":
                    stockinfo.append(tds[j].text)

            ##始値、高値、安値を取得
            detail = main.find_element_by_id("detail")
            innerDate = detail.find_element_by_class_name("innerDate")
            innerDate_divs = innerDate.find_elements_by_css_selector(".lineFi.clearfix")#S複数
            for n in range(0,len(innerDate_divs)):
                if len(innerDate_divs[n].find_elements_by_class_name("tseDtl"))>0:#存在確認は複数形
                    tseDtl = innerDate_divs[n].find_element_by_class_name("tseDtl")#こっちは単数
                    kubun=tseDtl.find_element_by_class_name("title").text
                    #共通の処理をまとめた
                    if kubun=="安値" or kubun=="高値" or kubun=="始値":
                        ymuiEditLink=tseDtl.find_element_by_css_selector(".ymuiEditLink.mar0")
                        kabuka=ymuiEditLink.find_element_by_tag_name("strong").text
                    #配列に追加    
                    if kubun=="安値":
                        stockinfo.append("安値:"+kabuka)
                    elif kubun=="高値":
                        stockinfo.append("高値:"+kabuka)
                    elif kubun=="始値":  
                        stockinfo.append("始値:"+kabuka)
                              
            ##ddタグの中に spanタグがあって、他に文字がある。spanタグのテキストだけが取得したかった。
            ##>>追記 2021年2月8日エラー処理を追加
            if len(dds[1].find_elements_by_tag_name("span"))>0:#存在チェック elementでなくてelements(複数S)にする
                stockinfo.append(dds[1].find_element_by_tag_name("span").text)#日付 こっちは単数のelement  
            output=stockinfo
            driver.close()#起動したウィンドウを閉じる
            return output
        
###START
print("START#####################################")
tmpStr=""
f=0
obj=yahooFinanceClass()
for i in codelist:
    outputStr=obj.getName(i)
    #コード、企業名、終値株価,前日比、日付
    for m in outputStr:
        if f==2:
            tmpStr+=m+'円'+' '
        else:
            tmpStr+=m+' '
        f+=1
        #print(outputStr[0],outputStr[1],outputStr[2]+"円",outputStr[3],outputStr[4])
    print(tmpStr)
    tmpStr=""
    f=0
    time.sleep(2)
print("End#####################################")    
'''出力例
START#####################################
6134 (株)FUJI 2,795円 前日比+51(+1.86%) 始値:2,794 高値:2,832 安値:2,777 14:08 
7952 (株)河合楽器製作所 3,510円 前日比+380(+12.14%) 始値:3,200 高値:3,540 安値:3,155 14:06 
6462 (株)リケン 2,400円 前日比+114(+4.99%) 始値:2,449 高値:2,449 安値:2,329 14:07 
End#####################################  
'''