web-dev-qa-db-ja.com

Beautifulsoup:.find()と.select()に違いはありますか-python 3.xx

簡単な質問があります:

BeautifulSoupを使用してWebサイトの特定の部分をスクレイピングするには、data.find()data.findAll()またはdata.select()

質問は次のとおりです。 .find()メソッドと.select()メソッドの間に大きな違いはありますか? (例:パフォーマンスまたは柔軟性、または...)

またはそれらは同じですか?

敬具

23
Dieter

コメントを要約するには:

  • selectは複数のインスタンスを検索してリストを返し、findは最初のインスタンスを検索し、彼らは同じことをしません。 select_onefindと同等です。
  • タグを連鎖するとき、またはtag.classnameを使用するときは、ほとんどの場合cssセレクターを使用します。クラスを使用せずに単一の要素を検索する場合find。基本的には、ユースケースと個人的な好みに帰着します。
  • 柔軟性が得られる限り、あなたは答えを知っていると思いますが、soup.select("div[id=foo] > div > div > div[class=fee] > span > span > a")は複数のチェーンfind/find_all呼び出しを使用するとかなり見苦しくなります。
  • Bs4のcssセレクターの唯一の問題は、サポートが非常に限定されていることです。nth-of-typeは、実装された擬似クラスであり、a [ href] [src]もcssセレクターの他の多くの部分と同様にサポートされていません。しかし、a [href= ..] *、a [href ^ =]a [href $ =]など。find("a", href=re.compile(....))よりもはるかに良いと思いますが、これも個人的なものです好み。

パフォーマンスのために、いくつかのテストを実行できます。 here here から取得した800以上のhtmlファイルで実行する answer here からコードを変更しましたが、網羅的ではありませんが、一部のオプションの読みやすさとパフォーマンス:

変更された機能は次のとおりです。

from bs4 import BeautifulSoup
from glob import iglob


def parse_find(soup):
    author = soup.find("h4", class_="h12 talk-link__speaker").text
    title = soup.find("h4", class_="h9 m5").text
    date = soup.find("span", class_="meta__val").text.strip()
    soup.find("footer",class_="footer").find_previous("data", {
        "class": "talk-transcript__para__time"}).text.split(":")
    soup.find_all("span",class_="talk-transcript__fragment")



def parse_select(soup):
    author = soup.select_one("h4.h12.talk-link__speaker").text
    title = soup.select_one("h4.h9.m5").text
    date = soup.select_one("span.meta__val").text.strip()
    soup.select_one("footer.footer").find_previous("data", {
        "class": "talk-transcript__para__time"}).text
    soup.select("span.talk-transcript__fragment")


def  test(patt, func):
    for html in iglob(patt):
        with open(html) as f:
            func(BeautifulSoup(f, "lxml")

タイミングについては:

In [7]: from testing import test, parse_find, parse_select

In [8]: timeit test("./talks/*.html",parse_find)
1 loops, best of 3: 51.9 s per loop

In [9]: timeit test("./talks/*.html",parse_select)
1 loops, best of 3: 32.7 s per loop

網羅的ではないと言ったように、cssセレクターは間違いなくより効率的であると言えます。

34