Ik heb problemen met het ontleden van HTML-elementen met het kenmerk “class” met Beautifulsoup. De code ziet er zo uit
soup = BeautifulSoup(sdata)
mydivs = soup.findAll('div')
for div in mydivs:
if (div["class"] == "stylelistrow"):
print div
Ik krijg een foutmelding op dezelfde regel “nadat” het script is voltooid.
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'
Hoe kom ik van deze fout af?
Antwoord 1, autoriteit 100%
Je kunt je zoekopdracht verfijnen om alleen die div’s met een bepaalde klasse te vinden met BS3:
mydivs = soup.find_all("div", {"class": "stylelistrow"})
Antwoord 2, autoriteit 44%
Uit de documentatie:
Vanaf Beautiful Soup 4.1.2 kan zoeken op CSS-klasse met behulp van het trefwoordargumentclass_
:
soup.find_all("a", class_="sister")
Wat in dit geval zou zijn:
soup.find_all("div", class_="stylelistrow")
Het zou ook werken voor:
soup.find_all("div", class_="stylelistrowone stylelistrowtwo")
Antwoord 3, autoriteit 9%
Update: 2016
In de nieuwste versie van beautifulsoup is de methode ‘findAll’ hernoemd naar
‘vind alle’. Link naar officiële documentatie
Daarom is het antwoord
soup.find_all("html_element", class_="your_class_name")
Antwoord 4, autoriteit 3%
Specifiek voor BeautifulSoup 3:
soup.findAll('div',
{'class': lambda x: x
and 'stylelistrow' in x.split()
}
)
Zal deze allemaal vinden:
<div class="stylelistrow">
<div class="stylelistrow button">
<div class="button stylelistrow">
Antwoord 5, autoriteit 3%
CSS-kiezers
eerste wedstrijd in één klas
soup.select_one('.stylelistrow')
lijst met overeenkomsten
soup.select('.stylelistrow')
samengestelde klasse (d.w.z. EN een andere klasse)
soup.select_one('.stylelistrow.otherclassname')
soup.select('.stylelistrow.otherclassname')
Spaties in namen van samengestelde klassen, bijv. class = stylelistrow otherclassname
worden vervangen door “.”. Je kunt doorgaan met het toevoegen van lessen.
lijst met lessen (OF – match met de aanwezige)
soup.select_one('.stylelistrow, .otherclassname')
soup.select('.stylelistrow, .otherclassname')
bs4 4.7.1 +
Specifieke klasse waarvan innerText
een tekenreeks bevat
soup.select_one('.stylelistrow:contains("some string")')
soup.select('.stylelistrow:contains("some string")')
NB
soupsieve 2.1.0 + vanaf december 2020
NIEUW: om conflicten met toekomstige CSS-specificaties te voorkomen
wijzigingen, beginnen niet-standaard pseudo-klassen nu met de :-soep-
voorvoegsel. Als gevolg hiervan zal :contains() nu bekend staan als
:-soup-contains(), hoewel voor een tijd de verouderde vorm van
:contains() is nog steeds toegestaan met een waarschuwing dat gebruikers dit moeten doen
migreer naar :-soup-contains().NIEUW: Nieuwe niet-standaard pseudo-klasse toegevoegd:-soep-bevat-eigen() die
werkt vergelijkbaar met :-soup-contains() behalve dat het alleen kijkt naar
tekstknooppunten die direct zijn gekoppeld aan het element met het huidige bereik en
niet zijn nakomelingen.
Specifieke klasse die een bepaald onderliggend element heeft, b.v. a
-tag
soup.select_one('.stylelistrow:has(a)')
soup.select('.stylelistrow:has(a)')
Antwoord 6, autoriteit 2%
Een ongecompliceerde manier zou zijn:
soup = BeautifulSoup(sdata)
for each_div in soup.findAll('div',{'class':'stylelist'}):
print each_div
Zorg ervoor dat u de behuizing van findAllverwijdert, het is niet findall
Antwoord 7, autoriteit 2%
Hoe elementen per klasse te vinden
Ik heb problemen met het ontleden van html-elementen met het kenmerk “class” met Beautifulsoup.
Je kunt gemakkelijk zoeken op één klasse, maar als je wilt zoeken op het snijpunt van twee klassen, is het iets moeilijker,
Uit de documentatie(nadruk toegevoegd):
Als u wilt zoeken naar tags die overeenkomen met twee of meerCSS-klassen, moet u een CSS-selector gebruiken:
css_soup.select("p.strikeout.body") # [<p class="body strikeout"></p>]
Voor alle duidelijkheid, dit selecteert alleen de p-tags die zowel strikeout als body class zijn.
Om het snijpunt van elkein een reeks klassen (niet het snijpunt, maar de unie) te vinden, kun je een lijst geven aan het trefwoordargument class_
( vanaf 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)
Houd er rekening mee dat findAll is hernoemd van de camelCase naar het meer Pythonische find_all
.
Antwoord 8
Vanaf BeautifulSoup 4+ ,
Als je een enkele klassenaam hebt, kun je de klassenaam gewoon als parameter doorgeven, zoals:
mydivs = soup.find_all('div', 'class_name')
Of als je meer dan één klassenaam hebt, geef je de lijst met klassenamen door als parameter zoals :
mydivs = soup.find_all('div', ['class1', 'class2'])
Antwoord 9
Probeer te controleren of de div eerst een klasse kenmerk heeft, zoals dit:
soup = BeautifulSoup(sdata)
mydivs = soup.findAll('div')
for div in mydivs:
if "class" in div:
if (div["class"]=="stylelistrow"):
print div
Antwoord 10
Dit werkt voor mij om toegang te krijgen tot het kenmerk Class (op Beautifulsoup 4, in tegenstelling tot wat de documentatie zegt). De KeyErError wordt geleverd met een lijst die niet een woordenboek wordt geretourneerd.
for hit in soup.findAll(name='span'):
print hit.contents[1]['class']
Antwoord 11
Het volgende werkte voor mij
a_tag = soup.find_all("div",class_='full tabpublist')
Antwoord 12
Gebruik class_=
Als u element (en) wilt vinden zonder de HTML-tag te vermelden.
Voor een enkel element:
soup.find(class_='my-class-name')
Voor meerdere elementen:
soup.find_all(class_='my-class-name')
Antwoord 13
Andere antwoorden werkten niet voor mij.
In andere antwoorden De findAll
wordt gebruikt op het soepobject zelf, maar ik had een manier nodig om een vondst te doen bij de naam van de klas op objecten in een specifiek element dat wordt geëxtraheerd uit het doel dat ik na het doen is geëxtraheerd findAll
.
Als u probeert een zoekopdracht binnen geneste HTML-elementen te doen om objecten per klas te krijgen, probeert u hieronder –
# 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
Punten om op te merken:
-
Ik definieer niet expliciet de zoekopdracht om op ‘Class’ kenmerk
findAll("li", {"class": "song_item"})
, omdat het het enige attribuut is, omdat het het enige attribuut is Ik ben op zoek naar en het zal standaard zoeken naar classattribuut als u niet uitsluitend vertelt welk attribuut u wilt vinden. -
Wanneer u een
findAll
offind
, is het resulterende object van klassebs4.element.ResultSet
wat een subklasse is vanlist
. U kunt alle methoden vanResultSet
, binnen een willekeurig aantal geneste elementen (zolang ze zijn van het typeResultSet
) om een vondst te doen of alles te vinden. -
My BS4-versie – 4.9.1, Python-versie – 3.8.1
Antwoord 14
Betreffende @ wernight’s opmerking op de Top antwoord Over gedeeltelijke matching …
U kunt gedeeltelijk overeenkomen:
<div class="stylelistrow">
EN<div class="stylelistrow button">
met gazpacho :
from gazpacho import Soup
my_divs = soup.find("div", {"class": "stylelistrow"}, partial=True)
Beide worden vastgelegd en geretourneerd als een lijst met Soup
-objecten.
Antwoord 15
Dit werkte voor mij:
for div in mydivs:
try:
clazz = div["class"]
except KeyError:
clazz = ""
if (clazz == "stylelistrow"):
print div
Antwoord 16
Dit zou moeten werken:
soup = BeautifulSoup(sdata)
mydivs = soup.findAll('div')
for div in mydivs:
if (div.find(class_ == "stylelistrow"):
print div
Antwoord 17
Als alternatief kunnen we lxml gebruiken, het ondersteunt xpath en erg snel!
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
Antwoord 18
Het volgende zou moeten werken
soup.find('span', attrs={'class':'totalcount'})
vervang ‘totalcount’ door je klasnaam en ‘span’ door de tag die je zoekt. Als je klas meerdere namen met spatie bevat, kies er dan gewoon een en gebruik.
P.S. Dit vindt het eerste element met gegeven criteria. Als je alle elementen wilt vinden, vervang dan ‘find’ door ‘find_all’.
Antwoord 19
enkele
soup.find("form",{"class":"c-login__form"})
meerdere
res=soup.find_all("input")
for each in res:
print(each)