こんな人にオススメ
pythonでWebスクレイピングできるけど、まずは何をすればいい?
モジュールは何を入れればいい?
ということで、今回は自分の勉強の記録としてWebスクレイピングの導入を記事にしてみた。Webスクレイピングはイメージはできていたが、実際に書いたことはなかった。
執筆者と同じくWebスクレイピング始めてみようと思う方は本記事も参考にしていただければ幸いだ。
python環境は以下。
- Python 3.9.4
- requests 2.25.1
- beautifulsoup4 4.9.3
必要なimport
必要なimport
は以下の二つ。他にも方法はあるが、簡単かつメジャーなのは以下の二つ。
import requests from bs4 import BeautifulSoup
anacondaで入れる際にはそれぞれ以下のコードでインストール可能。一応、ご自身で検索していただければ幸いだ。
requests
:conda install -c anaconda requests
conda install
:-c anaconda beautifulsoup4
流れ
requests
でHTMLとしてデータを取得BeautifulSoup
で必要なデータを抽出
requests
requests
モジュールは、Webサイトの情報を取得するためのモジュール。これがないとスクレイピングできない。anacondaのインストールコマンドは以下。
conda install -c anaconda requests
BeautifulSoup
BeautifulSoup
モジュールは、HTMLからデータを取り出すためのモジュール。
conda install -c anaconda beautifulsoup4
WebサイトのデータをHTMLとして出力
サイトのステータスコードの取得
ステータスコードとは、Webサーバからのレスポンスを表す3桁の数字。有名なのが「404 Not Found」。ざっくりいうと、
- 100番台: 情報レスポンス
- 処理に時間がかかっているが継続中
- 200番台: 成功レスポンス
- 処理が成功して正常にレスポンスできている
- 300番台: リダイレクション
- リダイレクト(サイトが新しいURLになった時に自動で転送)などで追加の処理が必要
- 400番台: クライアントエラー
- 正常にレスポンスできない
- 500番台: サーバーエラー
- サーバーに問題がありエラー
requests
モジュールのget
メソッドの引数に見たいURLを指定し、サーバーからのレスポンスを取得。ステータスコードが200
なので正常に処理されている。
# getメソッドは引数にURLを指定しwebページにアクセスしてサーバーからのレスポンスを取得 site = requests.get('<https://www.google.com>') # サイトのステータスコード # 正常にサイトにアクセスできていることを示す print(site) # <Response [200]>
サイトデータをHTMLとして出力
site.text
でサイトのデータをHTMLとして出力。
# サイトのデータをHTMLとして出力 print(site.text)
初めの方の<meta contetn="世
で始まる部分の&#...
はHTMLエンティティと呼ばれるものらしく、デコードすると通常の文字として表現可能。HTMLエンティティとは&
で始まり;
で終わる文字列の一塊のこと。例えば上記だと
世界中のあらゆる情報を検索するためのツールを提供しています。さまざまな検索機能を活用して、お探しの情報を見つけてください。
はデコードすると
世界中のあらゆる情報を検索するためのツールを提供しています。さまざまな検索機能を活用して、お探しの情報を見つけてください。
となる。初めの世
は「世」に対応する。デコードは以下のサイトで行なった。
HTMLからタグを抽出
データの抽出にはBeautifulSoup
を使用するのだった。
HTML全体を抽出
まずはHTML全体を抽出。parser
はパース(解析)するための機能。いくつかの種類があるが使用するには別途モジュールのimport
が必要。とりあえずpython標準のhtml.parser
を使用。
data = BeautifulSoup(site.text, 'html.parser') print(type(data)) # <class 'bs4.BeautifulSoup'> print(data)
ここでは上記のデコードなされており日本語が散見される。
タグの抽出
HTML全体を抽出することができたので、続いてはそれぞれの要素を抽出。HTMLには「タグ」と呼ばれる箱?に文字が入っているので、それらタグを選択して目当ての要素を抽出する。
まずはタイトル(<title>
タグ)から。.text
でタグの中身だけ抽出可能。
# 引き出したデータに「.title」とつけるとHTMLのタイトルを取得 title_tag = data.title print(title_tag) # <title>Google</title> print(type(title_tag)) # <class 'bs4.element.Tag'> # 「.text」をつければタグの中身だけを取れる print(title_tag.text) # Google print(type(title_tag.text)) # <class 'str'>
<a>
タグはAnchorの略で、指定部分をハイパーリンクとして扱うことができるタグ。
# aタグも出力 a_tag = data.a print(a_tag) # <a class="gb1" href="<https://www.google.co.jp/imghp?hl=ja&tab=wi>">画像</a> print(type(a_tag)) # <class 'bs4.element.Tag'> print(a_tag.text) # 画像 print(type(a_tag.text)) # <class 'str'>
.find()
でも同じ結果。
# .find()でも同じ結果 title_tag = data.find('title') print(title_tag) # <title>Google</title> print(type(title_tag)) # <class 'bs4.element.Tag'> a_tag = data.find('a') print(a_tag) # <a class="gb1" href="<https://www.google.co.jp/imghp?hl=ja&tab=wi>">画像</a> print(type(a_tag)) # <class 'bs4.element.Tag'>
タグの要素全てを抽出
前節でタグを抽出したが、このタグは実は初めの一つ。全てのタグを抽出したいのなら.find_all()
を使用する。
# .find_allで全部抽出 title_tag_all = data.find_all('title') print(title_tag_all) # [<title>Google</title>] print(len(title_tag_all)) # 1 print(type(title_tag_all)) # <class 'bs4.element.ResultSet'>
各要素(今回は1つしかないが)は前節のdata.title
の時と同じ。
# 各要素はdata.titleと同じ print(title_tag_all[0]) # <title>Google</title> print(type(title_tag_all[0])) # <class 'bs4.element.Tag'> print(title_tag_all[0].text) # Google
a
タグも同じように出力してみる。
# すべての「a」タグを出力する a_tag_all = data.find_all('a') print(a_tag_all)
print(len(a_tag_all)) # 18 print(type(a_tag_all)) # <class 'bs4.element.ResultSet'>
list
っぽい形式なのでfor
ループで要素を取り出し可能。
for element in a_tag_all: print(element)
他にも囲んだ範囲にCSSを適用するための<span>
タグは以下。
span_tag_all = data.find_all('span') print(span_tag_all)
print(len(span_tag_all)) # 8 for element in span_tag_all: print(element)
id属性とclass属性を抽出
最後はid属性とclass属性を抽出する。Webページは色々は要素の集まりでできており、それぞれの要素に名前をつけてあげないと区別することができない。人やものの名称をつけて区別するのと同じ。
そこで使用される考え方がid属性とclass属性。似たような使用用途であるが、明確に使い分けが必要。
id属性とclass属性
まずはid属性とclass属性とは何かというところから。いかに共通点とそれぞれの特徴を示す。
- 共通
- タグにつける(命名する)
- 命名した部分だけにCSSを適用できる
- id属性
- 1つのページで1回しか使用できない
- サイトの大きなレイアウトを決めるなどに使用
- ヘッダやフッタに使用
- class属性
- 1つのページで何度でも使用できる
- ページ内の具体的な表現などに使用
- 頻繁に呼び出すCSSに使用
id属性を抽出
id属性の抽出には.find(id=(id属性))
で可能。
# id属性は1つのページ内に1つしかない mngb = data.find(id='mngb') print(mngb)
class属性を抽出
class属性の場合はpythonのclass
と区別するため、引数はclass_
とする必要がある。また、class属性は1つのページ内で複数個存在させることが可能なのでfind
では初めの1つしか抽出できない。
# class属性は1つのページ内に複数ある場合がある=findだと初めの1つだけ抽出 gb1 = data.find(class_='gb1') print(gb1) # <b class="gb1">検索</b>
したがって、find_all
で全て抽出する。
gb1 = data.find_all(class_='gb1') print(gb1)
find_all
で全部抽出したのでfor
でそれぞれの要素を確認。
for element in gb1: print(element) # <b class="gb1">検索</b> # <a class="gb1" href="<https://www.google.co.jp/imghp?hl=ja&tab=wi>">画像</a> # <a class="gb1" href="<https://maps.google.co.jp/maps?hl=ja&tab=wl>">マップ</a> # <a class="gb1" href="<https://play.google.com/?hl=ja&tab=w8>">Play</a> # <a class="gb1" href="<https://www.youtube.com/?gl=JP&tab=w1>">YouTube</a> # <a class="gb1" href="<https://news.google.com/?tab=wn>">ニュース</a> # <a class="gb1" href="<https://mail.google.com/mail/?tab=wm>">Gmail</a> # <a class="gb1" href="<https://drive.google.com/?tab=wo>">ドライブ</a> # <a class="gb1" href="<https://www.google.co.jp/intl/ja/about/products?tab=wh>" style="text-decoration:none"><u>もっと見る</u> »</a>
id属性の中のa
タグをさらに抽出
上記で抽出したid属性mngb
からa
タグを抽出。
# 取り出したid属性からaタグを抽出 a_tag_all_mngb = mngb.find_all('a') print(a_tag_all_mngb)
それぞれの要素をfor
で抽出。
for elemnt in a_tag_all_mngb: print(elemnt) # <a class="gb1" href="<https://www.google.co.jp/imghp?hl=ja&tab=wi>">画像</a> # <a class="gb1" href="<https://maps.google.co.jp/maps?hl=ja&tab=wl>">マップ</a> # <a class="gb1" href="<https://play.google.com/?hl=ja&tab=w8>">Play</a> # <a class="gb1" href="<https://www.youtube.com/?gl=JP&tab=w1>">YouTube</a> # <a class="gb1" href="<https://news.google.com/?tab=wn>">ニュース</a> # <a class="gb1" href="<https://mail.google.com/mail/?tab=wm>">Gmail</a> # <a class="gb1" href="<https://drive.google.com/?tab=wo>">ドライブ</a> # <a class="gb1" href="<https://www.google.co.jp/intl/ja/about/products?tab=wh>" style="text-decoration:none"><u>もっと見る</u> »</a> # <a class="gb4" href="<http://www.google.co.jp/history/optout?hl=ja>">ウェブ履歴</a> # <a class="gb4" href="/preferences?hl=ja">設定</a> # <a class="gb4" href="<https://accounts.google.com/ServiceLogin?hl=ja&passive=true&continue=https://www.google.com/&ec=GAZAAQ>" id="gb_70" target="_top">ログイン</a>
さらに、それぞれの要素からa
タグのテキストを抽出。
for elemnt in a_tag_all_mngb: print(elemnt.text) # 画像 # マップ # Play # YouTube # ニュース # Gmail # ドライブ # もっと見る » # ウェブ履歴 # 設定 # ログイン
class属性の中のa
タグをさらに抽出
class属性でも同様にa
タグを抽出しようとしたが、なぜかできなかった。
print(type(gb1[0]), type(mngb)) # <class 'bs4.element.Tag'> <class 'bs4.element.Tag'> b_tag_all_gb1 = gb1[0].find_all('b') print(b_tag_all_gb1) # [] a_tag_all_gb1 = gb1[1].find_all('a') print(a_tag_all_gb1) # []
div
タグの中じゃないからか?わからん。
HTML・CSSの知識がいるねこりゃ
今回はpythonのrequests
モジュールとBeautifulSoup
モジュールを使用して、Webスクレイピングを始めてみたという内容だった。具体的には
requests
でサイトデータを取得BeautifulSoup
で取得データを抽出できる状態にするfinf
,find_all
でタグや属性でフィルター
Webスクレイピングができるようになれば、Web上のデータ解析を自動で行えるようになるらしいので楽をするためにも勉強していきたい。
さらに、タグとかid属性とかHTMLの知識が必要なので、これを機に少しずつ覚えていきたい。
関連記事
-
-
【python&list】pythonのlistの超基礎
続きを見る
-
-
【python&~】数値にチルダ(~)をつけると値が+1されて負の数になる(ビット反転)
続きを見る
-
-
【px&バブルチャート】plotly.expressで各国の収入と平均寿命の時代変化をアニメーションで
続きを見る
-
-
【plotly&Scattergeo】世界地図に各国の首都の位置をプロット
続きを見る