📌

BeautifulSoupで特定の要素を選択するチートシート

2022/12/10に公開

主に以下のサイトを参考にさせていただきました。

https://techacademy.jp/magazine/34387

https://qiita.com/Chanmoro/items/db51658b073acddea4ac

https://gammasoft.jp/blog/difference-find-and-select-in-beautiful-soup-of-python/

https://ai-inter1.com/beautifulsoup_1/#st-toc-h-29

インポート

from bs4 import BeautifulSoup

soupにHTMLの中身を入れる

# Requestsを利用して取り込む
res = requests.get('http://nenmatsunenshiha.com/')
soup = BeautifulSoup(res.text, 'html.parser')

# Seleniumを利用して取り込む
driver = webdriver.Chrome(driver_path, options=options)
driver.get('http://nenmatsunenshiha.com/')
html = driver.page_source
soup = BeautifulSoup(html, "html.parser")

基本的な文字列の取り出し方

コード 動作
soup.select("title")[0].string titleタグの1番目の要素の中の文字列
soup.get_text() 文字列すべて

要素の選択の仕方(CSSセレクタを利用)

findやfind_allを利用するのも手なのですが、select系だとCSSセレクタというものを利用できるらしく、ほかにも応用が利きそうなのでこちらを利用しています。

すべてリストで返ってくるはずなので、利用するときは[0]のように何番目の要素なのか指定する必要があります。(select_oneを利用すれば話は別です)

コード 指定内容
soup.select("li") タグがli
soup.select("li, p") タグがliまたはp
soup.select('a[data]) タグがaで、dataという属性を持っている
soup.select('a[href="http://www.google.com"]') タグがaで、href属性が"http://www.google.com"
soup.select(".ramen") クラスがramen
soup.select("[class='ramen item']") 完全一致('ramen item')。rowspanとかも使えるのでやりやすい。
soup.select(".ramen.item") 部分一致、AND検索(classに'ramen', 'item'のそれぞれを含む)
soup.select("li.favorite") タグがliで、クラスにfavoriteを含む
soup.select("#miso") idがmiso
soup.select("#miso, #tonkotsu") idがmisoまたはidがtonkotsu
soup.select('html body p') タグの親子関係を指定
soup.body.select('p') 上と同様の結果
soup.select('html > body') 直接の親子関係
soup.select("ul#book > li") 「idがbookのul」の子要素のli
soup.select("p.title + p") 直後の兄弟要素
soup.select("p.title ~ p") 後ろすべての兄弟要素

おまけ:指定した要素が手に入るまでリトライしてくれる関数

Seleniumベースで作りました。

import time
import traceback

from bs4 import BeautifulSoup


def patient_selector(driver, url, css_selector, retry_count=12, sec_to_sleep=10) -> list:
"""css_selectorには`soup.select()`の中身を入れる。"""
    for _ in range(retry_count):
        try:
            driver.get(url)
            html = driver.page_source.encode('utf-8')
            soup = BeautifulSoup(html, "html.parser")

            # 指定した中身が入っていればreturn。Noneならもう一度。
            result =  soup.select(css_selector)
            if result:
                return result
            print('Not desired html. Retrying.')
            time.sleep(sec_to_sleep)
        except Exception as e:
            # 何かしらのエラーでももう一度
            traceback.print_exc()
            time.sleep(sec_to_sleep)
    # リトライしてもダメだったなら空のリストを返す
    return []

Discussion