毎週末,保有株と購入候補株の値段を調べ,Excel表を更新しています.そのExcelでは,値動きや利回りに応じて「売るべし」「買うべし」が表示されるようにしています.これで,気分に左右されることなく,比較的普遍的な評価基準で,何も考えずに判断できる仕組みになっています.
毎週末の作業は,銘柄コードをYahoo!ファイナンスページへコピペし,直近1週間の日次情報をExcelへコピペするものです.現在は37銘柄を監視しており,このコピペ作業,意外と手間.株を始めた頃はこの作業もそれなりに楽しめていたのですが,そろそろ煩わしさが勝ってきました.なんとか楽したい.
ということで以前,それらしいWebAPIを軽く突けないかと,Webページを軽くハッキングしてみました.しかし,私のHTMLおよびJavaScript力では,乗り越えるに至らず,タイムアップでギブアップしました.
5月の大型連休を前に,少し時間が確保できたので,再挑戦.今度はアプローチを変え,Webサイトに表示されている株価をHTMLから抽出することにしました.いわゆる,Webスクレイピングです.これまでやったことないけど,これならやれるでしょう.やれました.ExcelのVBAで実現しました.
まずは,指定のWebページのHTMLの取得.「Microsoft XML, v6.0」というライブラリの参照を追加し,XMLHTTP60というクラスを使ったサンプルに倣いました.こんなに簡単にできちゃうんですね.
Private Function GetHtml(ByVal url As String) As String
Dim httpReq As New XMLHTTP60
Call httpReq.Open("GET", url)
Call httpReq.send
Do While httpReq.readyState < 4
DoEvents
Loop
GetHtml = httpReq.responseText
End Function
次に,HTMLから株価の部分を抽出するコード.正規表現で頑張ればなんとかなりそう.「Microsoft VBScript Regular Expressions 5.5」というライブラリの参照を追加し,VBScript_RegExp_55.RegExpというクラスを使いました.正規表現自体,あまり使ったことないので,調べながらでした.これでいいかと思ったら,株価に桁区切りのカンマが入るケースがあったり,小数部が入るケースがあったりで,何度か修正.
Private Sub Extract(ByVal html As String)
'HTMLに埋まっている株価の表の一部の例
'{"openPrice":"3,015","highPrice":"3,039","lowPrice":"3,007","closePrice":"3,023","volume":"1,161,200","adjustedClosePrice":"3,023","baseDate":"2021年4月23日","baseDateIso":"2021-04-23T00:00:00+09:00"},
'{"openPrice":"3,047","highPrice":"3,057","lowPrice":"3,001","closePrice":"3,036","volume":"1,478,500","adjustedClosePrice":"3,036","baseDate":"2021年4月22日","baseDateIso":"2021-04-22T00:00:00+09:00"},
'{"openPrice":"3,032","highPrice":"3,034","lowPrice":"2,976","closePrice":"2,997","volume":"3,178,600","adjustedClosePrice":"2,997","baseDate":"2021年4月21日","baseDateIso":"2021-04-21T00:00:00+09:00"}
Const PTN0 As String = """openPrice"":""(\d*,?\d+\.?\d*)"""
Const PTN1 As String = """highPrice"":""(\d*,?\d+\.?\d*)"""
Const PTN2 As String = """lowPrice"":""(\d*,?\d+\.?\d*)"""
Const PTN3 As String = """closePrice"":""(\d*,?\d+\.?\d*)"""
Const PTN4 As String = """volume"":""(\d*,?\d*,?\d+\.?\d*)"""
Const PTN5 As String = """adjustedClosePrice"":""(\d*,?\d+\.?\d*)"""
Const PTN6 As String = """baseDate"":""(\d{4}年\d?\d月\d?\d日)"""
Const PTN7 As String = """baseDateIso"":""(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\+\d{2}:\d{2})"""
Dim regex As New VBScript_RegExp_55.RegExp
Dim matches As MatchCollection
Dim m As match
regex.Pattern = "{" & PTN0 & "," & PTN1 & "," & PTN2 & "," & PTN3 & "," & PTN4 & "," & PTN5 & "," & PTN6 & "," & PTN7 & "}"
regex.Global = True
Set matches = regex.Execute(html)
For Each m In matches
Debug.Print "日付:" & m.SubMatches(6) & " 終値:" & m.SubMatches(3)
Next
End Sub
これで要素技術は確保できたので,あとはExcelの表を良い感じに操作するだけです.銘柄コードからURL化するところはExcel上の数式にしちゃって,並べた銘柄分と取得した日数分だけループを回し,縦や横に配置する感じ.程よくエラー処理を入れたりして無事完成.毎週末の作業がだいぶ楽になりました.