LoginSignup
0
2

More than 1 year has passed since last update.

[python] Webスクレイピング -BeautifulSoup-

Last updated at Posted at 2022-11-03

はじめに

場合によってはWebから情報を自動的に得ることも必要となる。
例えば、株価の情報など特定の値を持つデータ
ここではpythonを用いてWebから情報を集める方法の基本的なことをまとめた

環境

windows 10
python version: 3.7.8
Microsoft Edge
Yahoo Finance

Code

import requests
from bs4 import BeautifulSoup

image.png
対象は何をしても大丈夫そうな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 
...

image.png

ここで、HTMLから必要な情報を取り出すために、情報が所属しているid, classを特定する必要がある
空白を右クリック → 開発者ツールで調査する

image.png

開発ツールの左上の要素を選択をクリック、もしくはCtrl + Shift + C でも選択することができる。

image.png
必要な情報を真上にカーソルを置くことでHTMLの情報を表示される
株価のHTML情報を見たところ、spanclass = '_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.selectsoup.find_allと同じであるが、追加的に範囲を絞ることができる。

image.png
ここで欲しいデータの部分を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.png

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として保存することで多量のデータを一気に扱うことができる。

関連

0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2