webスクレイピングとやらをやってみたくて、Udemyの講座を受講した。
Pythonによるビジネスに役立つWebスクレイピング(BeautifulSoup、Selenium、Requests)
基礎から丁寧に解説してくれており、実際に手を動かしながらやってみる形式で、演習問題もあり、非常に良質の講座でした。
しかし、いかんせん脳みそが小さいものだから、習った内容が盛りだくさん(普通の人にとっては盛りだくさんではないのかもしれない)で、ごっちゃごちゃに混乱状態になってしまった。
で、整理するための備忘録その2です。
ちなみにpython,webスクレイピングとも超初心者です。
ブラウザはGooGleChrome、コードエディターはjupyterNotebook(Anacondaに入ってたやつ)を使用しています。
1.BeautifulSoupの要素のつかみ方:Select
まず、BeautifulSoupで要素を特定して、要素内のテキストやURLを取得するとき、
select,find,find_allを使うらしい。
実際にやってみて整理してみようと思います。
このようなHTMLを直接読み込んででやってみます。htmlの書いたことなくて見よう見まね。。。
#html
html = """
<html>
<head>
<meta charset="UTF-8"/>
<title>testhtml</title>
</head>
<body>
<h1>おすすめ記事</h1>
<br>
<div class="container">
<div class="itemA">
<h2 class="excel">エクセル</h2>
<ul>
<li class="excel recomend" id="article1"><a href="https://mwkexcelfriend.com/excel-vlookup-kousoku/">エクセルVLOOKUP高速</a></li>
<li class="excel" id="article2"><a href="https://mwkexcelfriend.com/excel-countif-speedup/">エクセルCOUNTIF高速</a></li>
</ul>
</div>
<br>
<div class="itemB">
<h2 class="vba">VBA</h2>
<ul>
<li class="vba recomend" id="article3"><a href="https://mwkexcelfriend.com/excel-vba-transpose-genkai/">TRANCEPOSEちょん切れ</a></li>
<li class="vba" id="article4"><a href="https://mwkexcelfriend.com/excel-vba-hairetu-kousoku/">配列</a></li>
</ul>
</div>
</div>
</body>
</html>
"""
#BeautifulSoupをインポートし、変数htmlを解析してsoupに代入
from bs4 import BeautifulSoup
soup = BeautifulSoup(html,"html.parser")
(1)soupにはなにが入ったのか。タグを指定して要素を取り出すとはどうゆうことか
soup.body とすると、<body>タグ~そのお尻</body>までが出力されました。
合致したhtml要素のカタマリ(タグの中身)を返すのですね。
soup.body
出力結果
<body>
<h1>おすすめ記事</h1>
<br/>
<div class="container">
<div class="itemA">
<h2 class="excel">エクセル</h2>
<ul>
<li class="excel recomend" id="article1"><a href="https://mwkexcelfriend.com/excel-vlookup-kousoku/">エクセルVLOOKUP高速</a></li>
<li class="excel" id="article2"><a href="https://mwkexcelfriend.com/excel-countif-speedup/">エクセルCOUNTIF高速</a></li>
</ul>
</div>
<br/>
<div class="itemB">
<h2 class="excel">VBA</h2>
<ul>
<li class="vba recomend" id="article3"><a href="https://mwkexcelfriend.com/excel-vba-transpose-genkai/">TRANCEPOSEちょん切れ</a></li>
<li class="vba" id="article4"><a href="https://mwkexcelfriend.com/excel-vba-hairetu-kousoku/">配列</a></li>
</ul>
</div>
</div>
</body>
soup.body.h1 とすると、bodyの下の<h1>タグの最初からお尻</h1>まで出力されました。
このようにselectメソッドなどを使わなくても、要素の特定ができれば要素の出力などもできるようですね。
soup.body.h1
出力結果
<h1>おすすめ記事</h1>
(2)selectメソッド
selectメソッドを使ってみます。
slelctメソッドはCSSセレクタを指定して要素を取り出すそうです。よくわかりませんね。
タグ名で指定してみます。
soup.select(“body”) とすると、上記と同様に<body>タグ~そのお尻</body>までが出力されました。ただし、selectはリストで返ってくるので[]内に入っています。select_oneメソッドだとリスト型ではなく最初の一つだけ返ってきます。
soup.select("body")
#出力結果
[<body>
<h1>おすすめ記事</h1>
<br/>
<div class="container">
<div class="itemA">
<h2 class="excel">エクセル</h2>
<ul>
<li class="excel recomend" id="article1"><a href="https://mwkexcelfriend.com/excel-vlookup-kousoku/">エクセルVLOOKUP高速</a></li>
<li class="excel" id="article2"><a href="https://mwkexcelfriend.com/excel-countif-speedup/">エクセルCOUNTIF高速</a></li>
</ul>
</div>
<br/>
<div class="itemB">
<h2 class="vba">VBA</h2>
<ul>
<li class="vba recomend" id="article3"><a href="https://mwkexcelfriend.com/excel-vba-transpose-genkai/">TRANCEPOSEちょん切れ</a></li>
<li class="vba" id="article4"><a href="https://mwkexcelfriend.com/excel-vba-hairetu-kousoku/">配列</a></li>
</ul>
</div>
</div>
</body>]
#select_one
soup.select_one("body")
#出力結果
<body>
<h1>おすすめ記事</h1>
<br/>
<div class="container">
<div class="itemA">
<h2 class="excel">エクセル</h2>
<ul>
<li class="excel recomend" id="article1"><a href="https://mwkexcelfriend.com/excel-vlookup-kousoku/">エクセルVLOOKUP高速</a></li>
<li class="excel" id="article2"><a href="https://mwkexcelfriend.com/excel-countif-speedup/">エクセルCOUNTIF高速</a></li>
</ul>
</div>
<br/>
<div class="itemB">
<h2 class="vba">VBA</h2>
<ul>
<li class="vba recomend" id="article3"><a href="https://mwkexcelfriend.com/excel-vba-transpose-genkai/">TRANCEPOSEちょん切れ</a></li>
<li class="vba" id="article4"><a href="https://mwkexcelfriend.com/excel-vba-hairetu-kousoku/">配列</a></li>
</ul>
</div>
</div>
</body>
(3)タグで指定する
select(“タグ名”) ダブルクォーテーションかシングルクォーテーションでタグ名を囲んで指定します。
elem = soup.select("li")
elem
elemの出力結果:リストにhtml内のli要素4つが入りました。
[<li class="excel recomend" id="article1"><a href="https://mwkexcelfriend.com/excel-vlookup-kousoku/">エクセルVLOOKUP高速</a></li>, <li class="excel" id="article2"><a href="https://mwkexcelfriend.com/excel-countif-speedup/">エクセルCOUNTIF高速</a></li>, <li class="vba recomend" id="article3"><a href="https://mwkexcelfriend.com/excel-vba-transpose-genkai/">TRANCEPOSEちょん切れ</a></li>, <li class="vba" id="article4"><a href="https://mwkexcelfriend.com/excel-vba-hairetu-kousoku/">配列</a></li>
〇複数タグで指定する
カンマでタグ名を区切って指定します
elem = soup.select("h2,li")
print(elem)
出力結果。<h2>タグと<li>タグの内容が出力されました。
[<h2 class="excel">エクセル</h2>,
<li class="excel recomend" id="article1"><a href="https://mwkexcelfriend.com/excel-vlookup-kousoku/">エクセルVLOOKUP高速</a></li>,
<li class="excel" id="article2"><a href="https://mwkexcelfriend.com/excel-countif-speedup/">エクセルCOUNTIF高速</a></li>,
<h2 class="vba">VBA</h2>,
<li class="vba recomend" id="article3"><a href="https://mwkexcelfriend.com/excel-vba-transpose-genkai/">TRANCEPOSEちょん切れ</a></li>,
<li class="vba" id="article4"><a href="https://mwkexcelfriend.com/excel-vba-hairetu-kousoku/">配列</a></li>]
(4)複数タグを使った指定
〇××タグの下の△△タグの指定
××の直下の△△の指定は >
divの直下のulの直下のliの指定
elem = soup.select("div > ul > li")
print(elem)
××の下の△△の指定は 空白でつなぎます。
divの下のliの指定。こちらは直下でなくてOK。
elem = soup.select("div li")
print(elem)
どちらも出力結果は同じです。
(5)検索範囲を狭める
検索範囲を狭める。
上記はhtml全体からヒットするものを検索していました。selectなどで検索範囲を絞り込みすると、目的の要素を取り出しやすくなりそうです。
#elemにクラスitemAのdivタグの中身だけを代入(※1)
elem = soup.select_one("div.itemA")
#その中からliタグを取り出し(※2)
elem_li = elem.select("li")
#取り出したli要素の0番目(※3)
print(elem_li[0])
<li class="excel recomend" id="article1"><a href="https://mwkexcelfriend.com/excel-vlookup-kousoku/">エクセルVLOOKUP高速</a></li>
#取り出したli要素の1番目のテキスト
print(elem_li[1].text)
エクセルCOUNTIF高速
#取り出したli要素の1番目のaタグ内のhref属性(※4、5)
print(elem_li[1].a["href"])
https://mwkexcelfriend.com/excel-countif-speedup/
※1:divタグのクラスitemA用をelemに代入しました。リスト形式にしたくなかったのでselect_oneを使用しています。
そうすると、elemに<div class=”itemA”>~</div>までが入ります。
<div class=”itemA”> <h2 class=”excel”>エクセル</h2> <ul> <li class=”excel recomend” id=”article1″><a href=”https://mwkexcelfriend.com/excel-vlookup-kousoku/”>エクセルVLOOKUP高速</a></li> <li class=”excel” id=”article2″><a href=”https://mwkexcelfriend.com/excel-countif-speedup/”>エクセルCOUNTIF高速</a></li> </ul> </div>
※2:次はelemから<li>タグを取得してリストに代入します。
リストに2つの要素が入ります。
[<li class=”excel recomend” id=”article1″><a href=”https://mwkexcelfriend.com/excel-vlookup-kousoku/”>エクセルVLOOKUP高速</a></li>,
<li class=”excel” id=”article2″><a href=”https://mwkexcelfriend.com/excel-countif-speedup/”>エクセルCOUNTIF高速</a></li>]
※3:一つ目を出力します。リストなので[]内にインデックスを指定します。
print(elem_li[0])
>出力結果
<li class=”excel recomend” id=”article1″><a href=”https://mwkexcelfriend.com/excel-vlookup-kousoku/”>エクセルVLOOKUP高速</a></li>
※4:2つ名を出力します。
li内のテキストを出力します
print(elem_li[1].text)
>出力結果
エクセルCOUNTIF高速
※5:li内のaタグ内のhref属性を出力します。il内の<a>なので、.aとつなぎます。そのhref属性なので[“href”]と指定します。
print(elem_li[1].a[“href”])
>出力結果
https://mwkexcelfriend.com/excel-countif-speedup/
(6)クラス名で指定する
クラス名は .クラス名 と指定します。
divタグの下のitemAクラスを指定。itemAクラスはhtml内に一つしかないので、この場合はどちらの書き方でも同じ結果となります。
elem = soup.select_one("div.itemA")
elem = soup.select_one(".itemA")
出力結果。クラス名itemAを持つdivタグが出力されました。
<div class="itemA">
<h2 class="excel">エクセル</h2>
<ul>
<li class="excel recomend" id="article2"><a href="https://mwkexcelfriend.com/excel-vlookup-kousoku/">エクセルVLOOKUP高速</a></li>
<li class="excel" id="article2"><a href="https://mwkexcelfriend.com/excel-countif-speedup/">エクセルCOUNTIF高速</a></li>
</ul>
</div>
(7)「××タグの△△クラス」で指定する
<li>タグ内のクラス名recomendを持つ要素
elem = soup.select("li.recomend")
出力結果
[<li class="excel recomend" id="article2"><a href="https://mwkexcelfriend.com/excel-vlookup-kousoku/">エクセルVLOOKUP高速</a></li>, <li class="vba recomend" id="article3"><a href="https://mwkexcelfriend.com/excel-vba-transpose-genkai/">TRANCEPOSEちょん切れ</a></li>
(8)クラス名を複数指定する方法
●<li>タグ内のクラス名excelとrecomendを両方持つ要素
elem = soup.select("li.excel.recomend")
出力結果
[<li class="excel recomend" id="article2"><a href="https://mwkexcelfriend.com/excel-vlookup-kousoku/">エクセルVLOOKUP高速</a></li>]
●クラス名「excel recomend」を持つ要素(完全一致)
elem = soup.select("[class='excel recomend']")
出力結果
[<li class="excel recomend" id="article2"><a href="https://mwkexcelfriend.com/excel-vlookup-kousoku/">エクセルVLOOKUP高速</a></li>]
●クラスexcelに完全一致する要素
elem = soup.select("[class='excel']")
出力結果
[<h2 class="excel">エクセル</h2>,
<li class="excel" id="article2"><a href="https://mwkexcelfriend.com/excel-countif-speedup/">エクセルCOUNTIF高速</a></li>]
●クラス名「itemA」または「itemB」を持つ要素
elem = soup.select(".itemA,.itemB")
出力結果
[<div class="itemA"> <h2 class="excel">エクセル</h2> <ul> <li class="excel recomend" id="article1"><a href="https://mwkexcelfriend.com/excel-vlookup-kousoku/">エクセルVLOOKUP高速</a></li> <li class="excel" id="article2"><a href="https://mwkexcelfriend.com/excel-countif-speedup/">エクセルCOUNTIF高速</a></li> </ul> </div>, <div class="itemB"> <h2 class="vba">VBA</h2> <ul> <li class="vba recomend" id="article3"><a href="https://mwkexcelfriend.com/excel-vba-transpose-genkai/">TRANCEPOSEちょん切れ</a></li> <li class="vba" id="article4"><a href="https://mwkexcelfriend.com/excel-vba-hairetu-kousoku/">配列</a></li> </ul> </div>]
(9)id名で指定
id名は#で指定します。
<li>タグ内のid名article3
elem = soup.select("li#article3")
elem = soup.select("#article3")
この場合、出力結果はおなじ
[<li class="vba recomend" id="article3"><a href="https://mwkexcelfriend.com/excel-vba-transpose-genkai/">TRANCEPOSEちょん切れ</a></li>]
(10)idタグを複数使う指定
●id名article2およびarticle4
elem = soup.select("#article3,#article4")
出力結果
[<li class="vba recomend" id="article3"><a href="https://mwkexcelfriend.com/excel-vba-transpose-genkai/">TRANCEPOSEちょん切れ</a></li>, <li class="vba" id="article4"><a href="https://mwkexcelfriend.com/excel-vba-hairetu-kousoku/">配列</a></li>]
●クラス名、id名の下のなんちゃらと指定できる
elem = soup.select(".itemA > ul > li")
elem = soup.select(".itemA li")
出力結果。どちらも同じ結果
[<li class="excel recomend" id="article2"><a href="https://mwkexcelfriend.com/excel-vlookup-kousoku/">エクセルVLOOKUP高速</a></li>, <li class="excel" id="article2"><a href="https://mwkexcelfriend.com/excel-countif-speedup/">エクセルCOUNTIF高速</a></li>]
(11)属性に××を含む
href属性に〇〇を含む
前方一致[href^=’××’] => href=’××://abcd’
後方一致[href$=’××’] => href=’http://abcd××’
あいまい検索[href*=’××’] => href=’http://abcd××efgh’
●href属性に「vlookup」を含む
elem = soup.select("a[href*='vlookup']")
出力結果。urlにvlookupを含む<a>タグが出力されました。
[<a href="https://mwkexcelfriend.com/excel-vlookup-kousoku/">エクセルVLOOKUP高速</a>]
(12)Copy Selector
Googleの開発者用ツールを使うと、セレクターを教えてくれるようです。
こちらのページを利用してみます。
上記のhtmlを固定ページにしたものです。
https://mwkexcelfriend.com/testtest/
このような内容がコピーされました。id article1の下のa要素ということですね。
#article1 > a
import requests
from bs4 import BeautifulSoup
url = "https://mwkexcelfriend.com/testtest/"
res = requests.get(url)
soup = BeautifulSoup(res.text, "html.parser")
#ここでコピーしたCSSセレクターをselectの引数内に貼り付けする
elem = soup.select("#article1 > a")
#出力
print(elem)
print(elem[0].text)
print(elem[0].attrs["href"])
出力結果
print(elem) → 取得した要素そのもの。
print(elem[0].text) → テキストを出力します。
print(elem[0].attrs[“href”]) → href属性を出力します。
リスト形式のため、[0]番目の要素と指定してテキスト、hrefを出力します。
[<a href="https://mwkexcelfriend.com/excel-vlookup-kousoku/">エクセルVLOOKUP高速</a>] エクセルVLOOKUP高速【Excel/関数】大量データのVLOOKUPをウソみたいに早くする方法大量データでVLOOKUPをかけると計算が遅い。。。というときに!VLOOKUPの近似値を使うと嘘みたいに計算が早くなります。かといって近似値を持ってこられても困るので、近似値を使って完全一致と同じ結果を得るやり方を解説します。
ごちゃごちゃに書きなぐった。自分の中で整理できたようなできてないような。
勉強させていただいたリンク
わかりやすかった↓
https://gammasoft.jp/blog/difference-find-and-select-in-beautiful-soup-of-python/
こちらも↓
https://lets-hack.tech/programming/languages/python/beautifulsoup/
https://qiita.com/d_m/items/f477c6665ec69dfaf594
https://naruport.com/blog/2019/12/26/bs4-select/
python webスクレイピング 超初心者の備忘録シリーズ
コメント