スポンサーリンク

【python】webスクレイピング BeautifulSoupのSELECTメソッド(超初心者がやってます)

スポンサーリンク
※当サイトは広告を含みます

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スクレイピング 超初心者の備忘録シリーズ

コメント

タイトルとURLをコピーしました