スポンサーリンク

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

スポンサーリンク

webスクレイピングとやらをやってみたくて、Udemyの講座を受講した。
(ちなみに2022.8.24.現在、89%オフになってます!!!)

Pythonによるビジネスに役立つWebスクレイピング(BeautifulSoup、Selenium、Requests)

基礎から丁寧に解説してくれており、実際に手を動かしながらやってみる形式で、演習問題もあり、非常に良質の講座でした。

しかし、いかんせん脳みそが小さいものだから、習った内容が盛りだくさん(普通の人にとっては盛りだくさんではないのかもしれない)で、ごっちゃごちゃに混乱状態になってしまった。

で、整理するための備忘録その3です。
ちなみにpython,webスクレイピングとも超初心者です。
ブラウザはGooGleChrome、コードエディターはjupyterNotebook(Anacondaに入ってたやつ)を使用しています。

まず、BeautifulSoupで要素を特定して、要素内のテキストやURLを取得するとき、
select,find,find_allを使うらしい。

前回selectをやったので、find、find_allについてやってみようと思います。

1.BeautifulSoupの要素のつかみ方:find

findは一つの要素を返します。find_allは合致する要素をすべてリスト型で返します。

前回同様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)find,find_allの基本

findは一つの要素を取り出します。タグ名でやってみます。

soup.find("div")

出力結果:一番最初のdiv(containerクラス)が取り出されました

<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>

find_allは合致したすべての要素を取り出します

soup.find_all("div")

出力結果:divは入れ子になっています。まず一番大きいdiv(containerクラス)が出力されます。次に、div(containerクラス)の中身のdiv(クラスitemA、itemB)が取り出しされています。

[<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>,
 <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>]

わかりにくいのでもうひとつ。今度は「li」タグを指定します。

soup.find_all("li")

出力結果:4つの「li」タグ要素が取り出しされました。

[<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>]

ちなみにselectのようにgoogle→検証→Copy selector でCSSセレクターをコピーしたものを指定しても、なにも起こりませんでした。

elem=soup.find("#article1 > a")
print(elem)
None

2.タグ名で指定

(1)複数のタグの指定

××の下の△△の指定。
divの下のliの指定。selectのようにいっぺんに指定できないようです。
つないで書いたらできた。
divタグ内で「li」タグを探しています。

elem=soup.find("div").find_all("li")
print(elem)
#出力結果
[<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>]

(2)または、の書き方

または、の書き方。[]で囲って並列
h1タグ、またはh2タグを出力

soup.find_all(["h1","h2"])
#出力結果
[<h1>おすすめ記事</h1>, <h2 class="excel">エクセル</h2>, 
<h2 class="vba">VBA</h2>]

3.クラスで指定

(1)クラス名で指定

class_=”クラス名” と指定します。
selectとは違って、classにアンダーバーを付けることが必要です。
selectでクラスを記載する場合slelct(”[class=’excel’]”)とダブルクォーテーション(またはシングルクォーテーション)内に記載したので文字列扱いですが、findではダブルクォーテーション(またはシングルクォーテーション)内ではないので、pythonの予約語とかぶってしまうからだそうです。

elem = soup.find_all(class_="excel")
print(elem)

出力結果:クラス名excelを持つ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>]

(2)〇〇タグのクラス名△△を指定する

liタグ、かつクラス名excelを指定

elem = soup.find_all("li",class_="excel")
print(elem)

出力結果:liタグでかつクラス名excelの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)複数のクラス名を指定

「excle recomend」クラスを指定

elem = soup.find_all(class_="excel recomend")
print(elem)

出力結果

[<li class="excel recomend" id="article1"><a href="https://mwkexcelfriend.com/excel-vlookup-kousoku/">エクセルVLOOKUP高速</a></li>]

(4)複数のクラス名。「または」の指定

liタグかつ「excle」または「vba」クラスを指定。
classを複数指定する場合は[]で囲ってカンマで区切るとできるらしい。

elem = soup.find_all("li",class_=["excel","vba"])
print(elem)

出力結果

[<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>]

4.idの指定方法

(1)idで指定

elem = soup.find_all(id="article1")
print(elem)

出力結果

[<li class="excel recomend" id="article1"><a href="https://mwkexcelfriend.com/excel-vlookup-kousoku/">エクセルVLOOKUP高速</a></li>]

(2)複数のidで指定。「または」の指定方法

id「article1」または「article3」に合致するもの。
[]でくくってカンマで区切ります。

elem = soup.find_all(id=["article1","article3"])
print(elem)

出力結果

[<li class="excel recomend" id="article1"><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>]

5.その他複合条件

(1)クラスメイトidで指定

クラス名、id名で指定。クラスがexcelかつidがarticle2の指定。

elem = soup.find_all(class_="excel",id="article2")
print(elem)

出力結果

[<li class="excel" id="article2"><a href="https://mwkexcelfriend.com/excel-countif-speedup/">エクセルCOUNTIF高速</a></li>]

(2)辞書で属性を指定する方法

属性を辞書で指定することもできるようです。
attrs={”属性”:”属性名”,”属性”:”属性名”}

elem = soup.find_all("li",attrs={"class":"excel","id":"article2"})
print(elem)

出力結果

[<li class="excel" id="article2"><a href="https://mwkexcelfriend.com/excel-countif-speedup/">エクセルCOUNTIF高速</a></li>]

(3)href属性で指定

href属性が〇〇に一致

elem = soup.find_all(href="https://mwkexcelfriend.com/excel-countif-speedup/")
print(elem)

出力結果

[<a href="https://mwkexcelfriend.com/excel-countif-speedup/">エクセルCOUNTIF高速</a>]

href属性が〇〇を含む、と指定するときは正規表現を利用するみたいです。

6.正規表現の利用

(1)href属性〇〇を含む

正規表現を使います。reをインポートします。
href=re.compile(〇〇)、と〇〇を含むを指定します。

import re
elem = soup.find_all(href=re.compile('countif'))
print(elem)

出力結果

[<a href="https://mwkexcelfriend.com/excel-countif-speedup/">エクセルCOUNTIF高速</a>]

(2)タグ、クラス、idでの正規表現の利用

●タグが「t」で始まる

elem = soup.find_all(re.compile('^t'))
print(elem)
#出力結果
[<title>testhtml</title>]

●クラスが「e」で始まる

elem = soup.find_all(class_=re.compile('^e'))
print(elem)
#出力結果
[<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>]

●idに「article」を含む

elem = soup.find_all(id=re.compile('article'))
print(elem)
#出力結果
[<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>]

7.テキストの検索方法、正規表現の利用

text=〇〇またはstring=〇〇で検索できる。

〇〇を含むの場合は
text=re.compile(〇〇)
またはstring=re.compile(〇〇)

(1)テキストが〇〇と一致

一致の場合:「li」タグ内で文字列が「エクセルVLOOKUP高速」の要素

elem = soup.find_all("li",text="エクセルVLOOKUP高速")
print(elem)

elem = soup.find_all("li",string="エクセルVLOOKUP高速")
print(elem)

出力結果は同じ

[<li class="excel recomend" id="article1"><a href="https://mwkexcelfriend.com/excel-vlookup-kousoku/">エクセルVLOOKUP高速</a></li>]

(2)テキストに〇〇を含む(正規表現の利用)

含む:「li」タグ内で文字列に「エクセル」を含む要素

elem = soup.find_all("li",text=re.compile('エクセル'))
print(elem)

出力結果

[<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>]

テキストに〇〇を含む、はselectではできないのではないだろうか。
できないとしたら、この点はfindが勝るのかも。

またまた、だらだらと書き連ねました。見苦しくてすみません。

勉強させていただいたリンク
https://www.crummy.com/software/BeautifulSoup/bs4/doc/#the-keyword-arguments
https://gammasoft.jp/blog/difference-find-and-select-in-beautiful-soup-of-python/

python webスクレイピング 超初心者の備忘録シリーズ

コメント

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