如何按类查找元素

我在使用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'

如何消除这个错误呢?

976535 次浏览

试着先检查div是否有class属性,就像这样:

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

你可以使用BS3优化你的搜索,只找到那些给定类的div:

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

直接的方法是:

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

确保你使用的是findAll的外壳,而不是findall

这招对我很管用:

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

从文档中可以看到:

# EYZ1 # EYZ0:

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

在这种情况下是:

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

它还适用于:

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

这可以让我访问class属性(在beautifulsoup 4上,与文档所说的相反)。KeyError返回的是一个列表,而不是字典。

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

具体到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">
< p >更新:2016 在beautifulsoup的最新版本中,方法“findAll”已被重命名为 “find_all”。# EYZ0 < / p >

List of method names changed

因此答案将是

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

如何按类查找元素

我在用“类”解析html元素时遇到了麻烦。属性使用Beautifulsoup。

你可以很容易地找到一个类,但如果你想找到两个类的交集,这就有点困难了,

文档(强调):

如果你想搜索匹配两个或更多 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重命名为更python化的find_all

这应该可以工作:

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

CSS选择器

单班第一场比赛

soup.select_one('.stylelistrow')

匹配列表

soup.select('.stylelistrow')

复合类(即与另一个类)

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

复合类名中的空格,例如class = stylelistrow otherclassname,将被"."取代。您可以继续添加类。

类列表(OR -匹配当前的任何一个)

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

类属性,其值包含一个字符串,例如带有"stylelistrow"

以“style"”开头:

[class^=style]

以“row”结尾;

[class$=row]

包含“list":

[class*=list]

^, $和*是操作符。点击这里阅读更多内容:https://developer.mozilla.org/en-US/docs/Web/CSS/Attribute_selectors

如果你想排除这个类,那么,以anchor tag为例,选择没有这个类的anchor tags:

a:not(.stylelistrow)

你可以在:not()伪类中传递简单、复合和复杂的css选择器列表。看到# EYZ0


Bs4 4.7.1 +

特定类,其innerText包含一个字符串

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

注意:

soupsieve 2.1.0 + Dec'2020年起

NEW:为了避免与未来的CSS规范冲突 更改,非标准伪类现在将以:-soup-开始 前缀。因此,:contains()现在将被称为 :-soup-contains(),尽管一度已弃用的形式 :contains()仍将被允许,并警告用户应该 迁移到:-soup-contains().

NEW:增加了新的非标准伪类:-soup-contains-own() 操作类似于:-soup-contains(),只是它只查看 与当前作用域元素和直接关联的文本节点 而不是它的后代

具有特定子元素的特定类,例如a标签

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

截至BeautifulSoup 4+,

如果你只有一个类名,你可以像这样把类名作为参数传递:

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

或者如果你有多个类名,只需将类名列表作为参数传递:

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

下面的方法对我很有效

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

或者我们可以使用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

其他答案对我不起作用。

在其他答案中,findAll被用于soup对象本身,但我需要一种方法来对从执行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. 我没有显式地定义搜索是在'类'属性findAll("li", {"class": "song_item"})上,因为它是我搜索的唯一属性,它将默认搜索类属性,如果你不专门告诉哪个属性你想找到。

  2. 当您执行findAllfind时,生成的对象属于bs4.element.ResultSet类,它是list的子类。您可以在任意数量的嵌套元素(只要它们是ResultSet类型)中使用ResultSet的所有方法来执行查找或查找全部。

  3. 我的BS4版本- 4.9.1,Python版本- 3.8.1

以下操作应该可以工作

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

用你的类名替换'totalcount',用你正在寻找的标签替换'span'。此外,如果类包含多个带空格的名称,只需选择一个并使用即可。

附注:这个函数用给定的条件找到第一个元素。如果你想找到所有的元素,那么将'find'替换为'find_all'。

关于@Wernight在上面的回答上关于部分匹配的评论…

你可以部分匹配:

  • # EYZ0和
  • # EYZ0

与# EYZ0:

from gazpacho import Soup


my_divs = soup.find("div", {"class": "stylelistrow"}, partial=True)

两者都将被捕获并作为Soup对象列表返回。

如果你想找到没有说明HTML标签号元素,请使用class_=

对于单个元素:

soup.find(class_='my-class-name')

对于多个元素:

soup.find_all(class_='my-class-name')

soup.find("form",{"class":"c-login__form"})

多个

res=soup.find_all("input")
for each in res:
print(each)