Elemanları sınıfa göre bulma


386

Beautifulsoup kullanarak "class" özniteliği ile HTML öğelerini ayrıştırma konusunda sorun yaşıyorum. Kod şuna benzer

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

Komut dosyası bittikten sonra aynı satırda bir hata alıyorum.

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'

Bu hatadan nasıl kurtulurum?

Yanıtlar:


646

BS3 kullanarak yalnızca belirli bir sınıfla bu div'leri bulmak için aramanızı daraltabilirsiniz:

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

@ Klaus- Bunun yerine findAll kullanmak istersem?

1
Bunun için teşekkürler. Sadece @class için değil, her şey için.
prageeth

41
Bu yalnızca tam eşleşmeler için geçerlidir. <.. class="stylelistrow">eşleşir, ancak eşleşmez <.. class="stylelistrow button">.
Wernight

4
@pyCthon @jmunsch için cevaba bakın, BS artık class_hangisinin düzgün çalıştığını destekliyor .
Wernight

25
Beautifulsoup4'ten itibaren findAll artık find_all
Neoecos

273

Belgelerden:

Güzel Çorba 4.1.2'den itibaren, CSS sınıfına göre anahtar kelime argümanını kullanarak arama yapabilirsiniz class_ :

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

Bu durumda hangisi olurdu:

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

Ayrıca aşağıdakiler için de çalışır:

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

5
Listeleri de kullanabilirsiniz: soup.find_all("a", ["stylelistrowone", "stylelistrow"])Çok fazla dersiniz yoksa daha güvenlidir.
Nuno André

4
Bu kabul edilen cevap olmalı, alternatiflerden daha doğru ve özlü.
goncalopp

1
BeautifulSoup 3 NunoAndré cevabı @ için Supplement: soup.findAll("a", {'class':['stylelistrowone', 'stylelistrow']}).
Brad

55

Güncelleme: 2016 beautifulsoup'un son sürümünde 'findAll' yöntemi 'find_all' olarak yeniden adlandırıldı. Resmi belgelere bağlantı

Yöntem adlarının listesi değişti

Dolayısıyla cevap

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

18

BeautifulSoup 3'e özgü:

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

Tüm bunları bulacak:

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

Neden yeniden arama ('. * Stylelistrow. *', X)?
rjurney

çünkü stylelistrow2 eşleşecektir. Daha iyi yorum "neden re yerine string.find () kullanmıyorsunuz?"
FlipMcF

2
lambda x: 'stylelistrow' in x.split()basit ve güzel
fferri

Ve normal ifadelerden nefret ediyorum. Teşekkür ederim! (cevap güncelleniyor) | 'x ve' değerini None test etmek için tutar
FlipMcF

16

Basit bir yol şöyle olacaktır:

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

Emin gömleğinin almak olun findall onun değil, findall


4
Bu yalnızca tam eşleşmeler için geçerlidir. <.. class="stylelistrow">eşleşir, ancak eşleşmez <.. class="stylelistrow button">.
Wernight

11

Elemanları sınıfa göre bulma

Beautifulsoup kullanarak "sınıf" özniteliği ile html öğeleri ayrıştırmada sorun yaşıyorum.

Bir sınıfta kolayca bulabilirsiniz, ancak iki sınıfın kesiştiği yerde bulmak istiyorsanız, biraz daha zor,

Gönderen belgelerinde (vurgu eklenmiştir):

İki veya daha fazla CSS sınıfıyla eşleşen etiketleri aramak istiyorsanız , bir CSS seçici kullanmalısınız:

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

Açık olmak gerekirse, bu yalnızca hem üstü çizili hem de gövde sınıfı olan p etiketlerini seçer.

Kesiştiği için bulmak için herhangi sınıfları kümesindeki (kesişim, ancak birlik) içinde, sen bir listesini verebilirim class_(4.1.2 itibariyle) anahtar kelime argüman:

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) 

Ayrıca findAll'ın camelCase'den daha Pythonic olarak yeniden adlandırıldığını unutmayın find_all.


11

CSS seçicileri

tek sınıf ilk maç

soup.select_one('.stylelistrow')

eşleşme listesi

soup.select('.stylelistrow')

bileşik sınıf (yani AND başka bir sınıf)

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

Bileşik sınıf adlarındaki boşluklar, ör. class = stylelistrow otherclassname "." İle değiştirilir. Sınıf eklemeye devam edebilirsiniz.

sınıfların listesi (VEYA - hangisi mevcutsa eşleşir)

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

bs4 4.7.1 +

innerTextDize içeren belirli sınıf

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

Belirli bir alt öğeye sahip belirli sınıf, örneğin atag

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

5

BeautifulSoup 4+ itibariyle,

Tek bir sınıf adınız varsa, sınıf adını aşağıdaki gibi parametre olarak iletebilirsiniz:

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

Veya birden fazla sınıf adınız varsa, sınıf adları listesini aşağıdaki gibi parametre olarak iletmeniz yeterlidir:

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

3

Div'in önce bir sınıf niteliğine sahip olup olmadığını kontrol etmeye çalışın, şöyle:

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

1
Bu işe yaramıyor. Sanırım yaklaşımınız doğruydu, ancak 4. satır amaçlandığı gibi çalışmıyor.
Neo

1
Ah, div'in bir sözlük gibi çalıştığını düşündüm, Beautiful Soup'a gerçekten aşina değilim, bu yüzden sadece bir tahminti.
Mew

3

Bu benim sınıf özniteliğine erişmem için işe yarıyor (belgelerin söylediklerinin aksine beautifulsoup 4'te). KeyError bir sözlük değil döndürülen bir liste gelir.

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

3

aşağıdakiler benim için çalıştı

a_tag = soup.find_all("div",class_='full tabpublist')

1

Bu benim için çalıştı:

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

1

Alternatif olarak lxml kullanabiliriz, xpath'i destekler ve çok hızlı!

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

Bu çalışmalı:

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

0

Diğer cevaplar benim için işe yaramadı.

Diğer cevaplarda bu findAllçorba nesnesi üzerinde kullanılıyor, ama yaptıktan sonra elde ettiğim nesneden çıkarılan belirli bir eleman içindeki nesneler üzerinde sınıf ismine göre bir yol bulmak için bir yol gerekiyordu findAll.

Nesneleri sınıf adına göre almak için iç içe HTML öğelerinin içinde arama yapmaya çalışıyorsanız, aşağıda deneyin -

# 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

Dikkat edilmesi gereken noktalar:

  1. Aradığım findAll("li", {"class": "song_item"})tek özellik olduğundan ve yalnızca hangi özelliği bulmak istediğinizi söylemezseniz varsayılan olarak sınıf özniteliği için arama yapacağından, açıkça 'sınıf' özniteliğinde olmak için aramayı tanımlamıyorum .

  2. Bir findAllveya yaptığınızda find, ortaya çıkan nesne bs4.element.ResultSetbir alt sınıfı olan sınıftan olur list. Hepsini bulmak veya bulmak için ResultSet, herhangi bir sayıda iç içe elemanın içinde (tipte oldukları sürece) tüm yöntemleri kullanabilirsiniz ResultSet.

  3. BS4 sürümüm - 4.9.1, Python sürümü - 3.8.1


0

Aşağıdakiler işe yaramalıdır

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

'totalcount' yerine sınıf adınızı ve 'span' ifadesini aradığınız etiketle değiştirin. Ayrıca, sınıfınızda boşluk içeren birden çok ad varsa, birini seçin ve kullanın.

Not: Verilen ölçütlere sahip ilk öğeyi bulur. Tüm öğeleri bulmak istiyorsanız, 'find' yerine 'find_all' yazın.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.