webスクレイピングとやらをやってみたくて、Udemyの講座を受講した。
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スクレイピング 超初心者の備忘録シリーズ
コメント