はじめに
場合によってはWebから情報を自動的に得ることも必要となる。
例えば、株価の情報など特定の値を持つデータ
ここではpythonを用いてWebから情報を集める方法の基本的なことをまとめた
環境
windows 10
python version: 3.7.8
Microsoft Edge
Yahoo Finance
Code
import requests
from bs4 import BeautifulSoup
対象は何をしても大丈夫そうなYahoo Finance
あの大きいリアルタイム株価の情報だけをゲットしたい。
情報を得ることが成功したら396.2の値を得るに違いない。
URL接続 -requests-
まずURLを通してページ上の情報を得る。
data = requests.get('https://finance.yahoo.co.jp/quote/4689.T')
print(data)
# <Response [200]>
問題がなければ成功コードが帰ってくる
data_error = requests.get('https://finance.yahoo.co.jp/quote/99999999')
print(data_error)
# <Response [404]>
存在しないURLを入力するとエラーコードが帰って来る
print(data.text)
# 人間が読めないような大量のデータが出てくる
...部分抜き取り
areChart":{"selectedItems":[],"form":[{"code":"","isExisted":true},{"code":"","isExisted":true},{"code":"","isExisted":true},{"code":"","isExisted":true}],"compareCodes":"","isError":false,"notice":""},"mainStocksHistory":{"history":{"yearHighPrice":"","yearHighPriceDate":"","yearHighPriceFlag":false,"yearLowPrice":"","yearLowPriceDate":"","yearLowPriceFlag":false,"histories":[],"splitHistories":[]},"paging":{"hasNext":false,"totalPage":0,"totalSize":0,"page":0,"size":0,"startIndex":0,"endIndex":0,"displayedPageNumbers":[]},"marginLink":"","selected":{"fromDate":"20211027","toDate":"20221027","timeFrameId":"d"},"filtered":{"fromDate":"20211027","toDate":"20221027","timeFrameId":"d"},"isLoading":false,"isError":false},"mainStocksMarginHistory":{"historyLink":"","histories":[],"paging":{"hasNext":false,"totalPage":0,"totalSize":0,"page":0,"size":0,"startIndex":0,"endIndex":0,"displayedPageNumbers":[]},"isLoading":false,"isError":false},"mainStocksNews":{"hasPaidArticle":false,"articles":[],"paging":{"hasNext":false,"totalPage":0,"totalSize":0,"page":0,"size":0,"startIndex":0,"endIndex":0,"displayedPageNumbers":[]},"isLoading":false,"isError":false,"stockForecast":{"text":"","link":""}},"mainStocksProfile":{"items":[]},"incentive":{"incentiveInfo":null,"positiveCompanyList":[]},"pageInfo":{"code":"4689.T","contentsId":"4689","spaceId":"2079486148","isUnsupportedBrowser":false,"jwtToken":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE2Njc0NzQ2NTAsImV4cCI6MTY3MDA2NjY1MH0.vPyV70KD48Yky0j3CgTJQrThlnc13cnxOV8hPD77upY","stocksJwtToken":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE2Njc0NzQ2NTAsImV4cCI6MTY3MDA2NjY1MH0.HCuF9m8IXfCinonPvqUHCKU-zyxAYRA2hVIpI7QoWyY","chartJwtToken":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE2Njc0NzQ2NTAsImV4cCI6MTY3MDA2NjY1MH0.vz0a4E9v9T47WaUPxuEd1n2cqQpyjAxflPUh6cEXAKk","currentPageLink":"https://finance.yahoo.co.jp/quote/4689.T","currentKey":"stocksContents","currentDateTime":1667474650618,"currentYear":"2022","loginUrl":"https://login.yahoo.co.jp/config/login?.src=quote&.done=https%3A%2F%2Ffinance.yahoo.co.jp%2Fquot
...
HTML情報の獲得 -BeautifulSoup-
soup = BeautifulSoup(data.content, 'html.parser')
print(soup)
# まだ読みにくが、htmlの形式としてデータを得る
...部分抜き取り
表示しています。</li><li class="W7zdvb-0">用語の意味については「<a data-ylk="pos:31" href="https://finance.yahoo.co.jp/feature/special/dictionary/">用語の説明</a>」をご覧ください。</li><li class="W7zdvb-0">時系列データは<a data-ylk="pos:32" href="https://www.jpx.co.jp/corporate/about-jpx/profile/01.html" rel="noopener noreferrer" target="_blank">東京証券取引所</a>、<a data-ylk="pos:33" href="https://www.jpx.co.jp/corporate/about-jpx/profile/02.html" rel="noopener noreferrer" target="_blank">大阪取引所</a>、<a data-ylk="pos:34" href="http://www.nse.or.jp/" rel="noopener noreferrer" target="_blank">名古屋証券取引所</a>、<a data-ylk="pos:35" href="https://www.nri.com/jp" rel="noopener noreferrer" target="_blank">野村総合研究所</a>、<a data-ylk="pos:36" href="https://www.morningstar.co.jp/" rel="noopener noreferrer" target="_blank">モーニングス
ター</a>、<a data-ylk="pos:37" href="https://www.refinitiv.com/ja" rel="noopener noreferrer" target="_blank">リフィニティブ・ジャパン</a>から
の提供を受けています。</li></ul><p class="_3vKzMSn5">情報提供会社のリンクは、すべて外部サイトへ移動します。</p><button aria-label="閉じる" class="_1pHBxEmL" type="button"><span aria-hidden="true" class="_1OlVoYo8 _2LfiAUqo"></span></button><div class="_1q5J03zs"></div></div></div></div></div></div></div></div></section></div><ul class="_2OTjANE6 _2PhgeJmM" id="support"><li class="InifRxXF"><a href="https://privacy.yahoo.co.jp/">プライバシー</a></li><li class="InifRxXF"><a href="https://about.yahoo.co.jp/common/terms/">利用規約</a></li><li class="InifRxXF"><a href="https://marketing.yahoo.co.jp/">広告掲載について</a></li><li
...
ここで、HTMLから必要な情報を取り出すために、情報が所属しているid, classを特定する必要がある
空白を右クリック → 開発者ツールで調査する
開発ツールの左上の要素を選択をクリック、もしくはCtrl + Shift + C でも選択することができる。
必要な情報を真上にカーソルを置くことでHTMLの情報を表示される
株価のHTML情報を見たところ、span
のclass = '_3rXWJKZF'
であった。
よって次の方法でspan
かつclass = '_3rXWJKZFe'
を満たす、すべての情報得る
print(soup.find_all('span', class_="_3rXWJKZF"))
[<span class="_3rXWJKZF">396.2</span>, <span class="_3rXWJKZF">-1.4</span>, <span class="_3rXWJKZF">-0.35</span>, <span class="_3rXWJKZF _11kV6f2G">397.6</span>, <span class="_3rXWJKZF _11kV6f2G">396.6</span>, <span class="_3rXWJKZF _11kV6f2G">397.1</span>, <span class="_3rXWJKZF _11kV6f2G">388.5</span>, <span class="_3rXWJKZF _11kV6f2G">25,406,200</span>, <span class="_3rXWJKZF _11kV6f2G">9,983,203</span>, <span class="_3rXWJKZF _11kV6f2G">317.6~477.6</span>, <span class="_3rXWJKZF">---</span>, <span class="_3rXWJKZF">---</span>, <span class="_3rXWJKZF _11kV6f2G">3,024,300</span>, <span class="_3rXWJKZF _11kV6f2G">7,633,266,686</span>, <span class="_3rXWJKZF _11kV6f2G">1.40</span>, <span class="_3rXWJKZF _11kV6f2G">5.56</span>, <span class="_3rXWJKZF _11kV6f2G">---</span>, <span class="_3rXWJKZF _11kV6f2G">1.10</span>, <span class="_3rXWJKZF _11kV6f2G">---</span>, <span class="_3rXWJKZF _11kV6f2G">369.02</span>, <span class="_3rXWJKZF _11kV6f2G">39,620</span>, <span class="_3rXWJKZF _11kV6f2G">100</span>, <span class="_3rXWJKZF _11kV6f2G">686</span>, <span class="_3rXWJKZF _11kV6f2G">371</span>, <span class="_3rXWJKZF">31,746,800</span>, <span class="_3rXWJKZF">+1,711,200</span>, <span class="_3rXWJKZF">23.15</span>, <span class="_3rXWJKZF">1,371,400</span>, <span class="_3rXWJKZF">+117,500</span>]
https://finance.yahoo.co.jp/quote/4689.T/chart?trm=6m
条件を満たす情報のすべてがlist形式で出てくる
print(soup.find_all('span', class_="_3rXWJKZF")[0].text)
# 396.2
データをよくみると0番目に396.2
と、現在の株価と一致する値が出てきた。
残念ながらspan
かつclass = '_3rXWJKZF'
を満たすものは、現在の株価のみではなく、複数あった。
よってより範囲を絞って検索をする。
ss = soup.select('span ._3rXWJKZF')
soup.select
はsoup.find_all
と同じであるが、追加的に範囲を絞ることができる。
ここで欲しいデータの部分をselectorコピーしてsoup.select
で使用する
ss = soup.select('#root > main > div > div > div.XuqDlHPN > div:nth-child(2) > section._1zZriTjI._2l2sDX5w > div._1nb3c4wQ > header > div.nOmR5zWz > span > span > span')
print(ss)
# [<span class="_3rXWJKZF">396.2</span>]
print(ss[0].text)
# 396.2
範囲を絞ることでlist型のデータに1つのみのデータを得られた
これで現在の株価のみをゲットすることができる
【補足】イメージ情報の獲得
image= soup.select('#DetailChart__panel--3 > div > a')
print(image[0]['href'])
# https://finance.yahoo.co.jp/quote/4689.T/chart?trm=6m
同じようにしてイメージ (src) やリンク (href) などの情報も得ることができる
まとめ
ここではpythonとBeautifulSoupを用いてWeb上の情報を得る方法を紹介した。
このように情報を得て、txtやcsvとして保存することで多量のデータを一気に扱うことができる。
関連