クラスごとに要素を見つける方法


386

Beautifulsoupを使用して "class"属性を持つHTML要素を解析するのに問題があります。コードは次のようになります

soup = BeautifulSoup(sdata)
mydivs = soup.findAll('div')
for div in mydivs: 
    if (div["class"] == "stylelistrow"):
        print div

スクリプトが終了した後、同じ行にエラーが表示されます。

File "./beautifulcoding.py", line 130, in getlanguage
  if (div["class"] == "stylelistrow"):
File "/usr/local/lib/python2.6/dist-packages/BeautifulSoup.py", line 599, in __getitem__
   return self._getAttrMap()[key]
KeyError: 'class'

このエラーを取り除くにはどうすればよいですか?

回答:


646

BS3を使用して、特定のクラスのdivのみを検索するように検索を絞り込むことができます。

mydivs = soup.findAll("div", {"class": "stylelistrow"})

@クラウス-代わりにfindAllを使用したい場合はどうなりますか?

1
これをありがとう。これは、@ classだけでなく、あらゆる目的に使用できます。
prageeth 2014年

41
これは完全一致の場合にのみ機能します。<.. class="stylelistrow">一致しますが、一致しません<.. class="stylelistrow button">
2014

4
@pyCthon @jmunschの回答を参照してください。BSはclass_正しく動作するものをサポートするようになりました。
2014年

25
beautifulsoup4以降、findAllはfind_allになりました
Neoecos

273

ドキュメントから:

Beautiful Soup 4.1.2以降、キーワード引数を使用してCSSクラスで検索できます class_

soup.find_all("a", class_="sister")

この場合、これは次のようになります。

soup.find_all("div", class_="stylelistrow")

それはまた働きます:

soup.find_all("div", class_="stylelistrowone stylelistrowtwo")

5
リストも使用できますsoup.find_all("a", ["stylelistrowone", "stylelistrow"])。多くのクラスがない場合は、より安全です。
ヌーノ・アンドレ

4
これは受け入れられる答えである必要があります。これは、他の選択肢よりも正確かつ簡潔です。
goncalopp 2016年

1
BeautifulSoup 3に対する@NunoAndréの回答の補足soup.findAll("a", {'class':['stylelistrowone', 'stylelistrow']})
ブラッド

55

更新:2016 beautifulsoupの最新バージョンでは、メソッド「findAll」の名前が「find_all」に変更されました。公式ドキュメントへのリンク

変更されたメソッド名のリスト

したがって、答えは

soup.find_all("html_element", class_="your_class_name")

18

BeautifulSoup 3に固有:

soup.findAll('div',
             {'class': lambda x: x 
                       and 'stylelistrow' in x.split()
             }
            )

これらのすべてを見つけます:

<div class="stylelistrow">
<div class="stylelistrow button">
<div class="button stylelistrow">

なぜre.search( '。* stylelistrow。*'、x)しないのですか?
rjurney 2015年

それで、stylelistrow2が一致するからです。より良いコメントは「なぜreの代わりにstring.find()を使用しないのですか?」です。
FlipMcF 2015年

2
lambda x: 'stylelistrow' in x.split()シンプルで美しい
fferri

そして、私は正規表現が嫌いです。ありがとうございました!(回答の更新)| 'x and'を維持してNoneをテスト
FlipMcF

16

簡単な方法は次のとおりです。

soup = BeautifulSoup(sdata)
for each_div in soup.findAll('div',{'class':'stylelist'}):
    print each_div

findallではなく、findAllのケーシングを使用してください。


4
これは完全一致の場合にのみ機能します。<.. class="stylelistrow">一致しますが、一致しません<.. class="stylelistrow button">
2014

11

クラスごとに要素を見つける方法

Beautifulsoupを使用して "class"属性を持つhtml要素を解析するのに問題があります。

1つのクラスで簡単に見つけることができますが、2つのクラスの共通部分で検索する場合は、少し難しくなります。

ドキュメントから(強調を追加):

2つ以上の CSSクラスに一致するタグを検索する場合は、CSSセレクターを使用する必要があります。

css_soup.select("p.strikeout.body")
# [<p class="body strikeout"></p>]

明確にするために、これは取り消し線とボディクラスの両方であるpタグのみを選択します。

一連のクラス(交差ではなく、共用体)のいずれかの交差を見つけるには、class_キーワード引数にリストを指定できます(4.1.2以降)。

soup = BeautifulSoup(sdata)
class_list = ["stylelistrow"] # can add any other classes to this list.
# will find any divs with any names in class_list:
mydivs = soup.find_all('div', class_=class_list) 

また、findAllはcamelCaseからよりPythonicに名前が変更されたことにも注意してくださいfind_all


11

CSSセレクター

単一クラスの最初の一致

soup.select_one('.stylelistrow')

一致のリスト

soup.select('.stylelistrow')

複合クラス(つまり、別のクラス)

soup.select_one('.stylelistrow.otherclassname')
soup.select('.stylelistrow.otherclassname')

複合クラス名のスペースは、たとえばclass = stylelistrow otherclassname「。」に置き換えられます。引き続きクラスを追加できます。

クラスのリスト(または-存在するものに一致)

soup.select_one('.stylelistrow, .otherclassname')
soup.select('.stylelistrow, .otherclassname')

bs4 4.7.1 +

innerText文字列を含む特定のクラス

soup.select_one('.stylelistrow:contains("some string")')
soup.select('.stylelistrow:contains("some string")')

aタグなどの特定の子要素を持つ特定のクラス

soup.select_one('.stylelistrow:has(a)')
soup.select('.stylelistrow:has(a)')

5

BeautifulSoup 4+以降、

クラス名が1つしかない場合は、次のようにクラス名をパラメータとして渡すだけです。

mydivs = soup.find_all('div', 'class_name')

または、クラス名が複数ある場合は、クラス名のリストを次のようにパラメータとして渡します。

mydivs = soup.find_all('div', ['class1', 'class2'])

3

次のように、最初にdivにクラス属性があるかどうかを確認してください。

soup = BeautifulSoup(sdata)
mydivs = soup.findAll('div')
for div in mydivs:
    if "class" in div:
        if (div["class"]=="stylelistrow"):
            print div

1
それはうまくいきません。あなたのアプローチは正しかったと思いますが、4行目は意図したとおりに機能しません。
ネオ

1
ああ、divは辞書のように機能すると思いましたが、Beautiful Soupにはあまり慣れていないので、それは推測にすぎません。
Mew

3

これは、私がクラス属性にアクセスするのに役立ちます(ドキュメントに書いてあるのとは対照的に、beautifulsoup 4では)。KeyErrorには、辞書ではなくリストが返されます。

for hit in soup.findAll(name='span'):
    print hit.contents[1]['class']


1

これは私のために働きました:

for div in mydivs:
    try:
        clazz = div["class"]
    except KeyError:
        clazz = ""
    if (clazz == "stylelistrow"):
        print div

1

または、lxmlを使用することもできます。これは、xpathをサポートし、非常に高速です。

from lxml import html, etree 

attr = html.fromstring(html_text)#passing the raw html
handles = attr.xpath('//div[@class="stylelistrow"]')#xpath exresssion to find that specific class

for each in handles:
    print(etree.tostring(each))#printing the html as string

0

これはうまくいくはずです:

soup = BeautifulSoup(sdata)
mydivs = soup.findAll('div')
for div in mydivs: 
    if (div.find(class_ == "stylelistrow"):
        print div

0

他の答えは私にとってうまくいきませんでした。

他の回答でfindAllは、はスープオブジェクト自体で使用されていますが、実行後に取得したオブジェクトから抽出された特定の要素内のオブジェクトをクラス名で検索する方法が必要でしたfindAll

ネストされたHTML要素内で検索を実行してクラス名でオブジェクトを取得しようとしている場合は、以下を試してください-

# parse html
page_soup = soup(web_page.read(), "html.parser")

# filter out items matching class name
all_songs = page_soup.findAll("li", "song_item")

# traverse through all_songs
for song in all_songs:

    # get text out of span element matching class 'song_name'
    # doing a 'find' by class name within a specific song element taken out of 'all_songs' collection
    song.find("span", "song_name").text

注意点:

  1. 「class」属性に検索を明示的に定義するのではありません。これは、検索するfindAll("li", {"class": "song_item"})唯一の属性であり、検索する属性を独占的に指定しない場合、デフォルトでクラス属性が検索されるためです。

  2. findAllまたはを実行するfindと、結果のオブジェクトはのbs4.element.ResultSetサブクラスであるクラスになりlistます。のすべてのメソッドを利用してResultSet、ネストされた任意の数の要素内で(タイプがである限りResultSet)、検索を実行したり、すべてを検索したりできます。

  3. 私のBS4バージョン-4.9.1、Pythonバージョン-3.8.1


0

以下はうまくいくはずです

soup.find('span', attrs={'class':'totalcount'})

「totalcount」をクラス名に、「span」を探しているタグに置き換えます。また、クラスにスペース付きの複数の名前が含まれている場合は、1つを選択して使用します。

PSこれは与えられた基準で最初の要素を見つけます。すべての要素を検索する場合は、「find」を「find_all」に置き換えます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.