如何按类查找元素

时间:2011-02-18 11:58:10

标签: python html web-scraping beautifulsoup

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

如何摆脱此错误?

19 个答案:

答案 0 :(得分:504)

您可以优化搜索,只使用BS3找到具有给定类的div:

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

答案 1 :(得分:207)

来自文档:

As of Beautiful Soup 4.1.2, you can search by CSS class using the keyword argument class_

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

在这种情况下会是:

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

它也适用于:

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

答案 2 :(得分:41)

更新:2016年 在最新版本的beautifulsoup中,方法'findAll'已重命名为 '找到所有'。 Link to official documentation

List of method names changed

因此答案将是

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

答案 3 :(得分:15)

直接的方式是:

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

确保您使用 findAll 的大小写,而不是 findall

答案 4 :(得分:14)

特别针对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">

答案 5 :(得分:8)

  

如何按类

查找元素      

使用Beautifulsoup解析带有“class”属性的html元素时遇到了问题。

你可以通过一个班级轻松找到,但是如果你想通过两个班级的交集找到它,那就更困难了,

documentation(强调添加):

  

如果您要搜索匹配两个或更多 CSS类的标记,则应使用CSS选择器:

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

要清楚,这只选择了三角形和三角形的标签。

要查找一组类中的 any 的交集(不是交集,而是联合),您可以为class_关键字参数提供一个列表(从4.1开始) 0.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

答案 6 :(得分:4)

尝试首先检查div是否具有class属性,如下所示:

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

答案 7 :(得分:3)

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

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

答案 8 :(得分:3)

使用 class_= 如果您想查找元素而不说明 HTML 标记

对于单个元素:

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

对于多个元素:

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

答案 9 :(得分:1)

这对我有用:

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

答案 10 :(得分:1)

CSS选择器

单班第一场比赛

soup.select_one('.stylelistrow')

比赛列表

soup.select('.stylelistrow')

复合类(即AND另一类)

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

复合类名称中的空格,例如class = stylelistrow otherclassname被替换为“。”。您可以继续添加类。

课程列表(或-匹配存在的任何

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

答案 11 :(得分:1)

关于@Wernight对top answer的有关部分匹配的评论...

您可以部分匹配:

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

gazpacho

from gazpacho import Soup

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

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

答案 12 :(得分: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

答案 13 :(得分:1)

其他答案对我不起作用。

在其他答案中,findAll被用于汤对象本身,但是我需要一种方法,可以对从{{1 }}。

如果您要在嵌套的HTML元素中进行搜索以按类名获取对象,请尝试以下操作-

findAll

注意事项:

  1. 我没有明确地将搜索定义在'class'属性# 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 上,因为这是我正在搜索的唯一属性,如果您不这样做,默认情况下它将搜索class属性•专门告诉您要查找的属性。

  2. 当您执行findAll("li", {"class": "song_item"})findAll时,所得对象属于find类,是bs4.element.ResultSet的子类。您可以在任意数量的嵌套元素中使用list的所有方法(只要它们的类型为ResultSet)即可进行查找或全部查找。

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

答案 14 :(得分:0)

单人

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

多个

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

答案 15 :(得分:0)

以下应该可以工作

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

将“ totalcount”替换为您的班级名称,并将“ span”替换为您要查找的标签。另外,如果您的班级包含多个带空格的名称,只需选择一个并使用。

P.S。这将找到具有给定标准的第一个元素。如果要查找所有元素,则将“ find”替换为“ find_all”。

答案 16 :(得分:0)

以下内容对我有用

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

答案 17 :(得分:0)

自BeautifulSoup 4+起,

如果只有一个类名,则只需将类名作为参数传递即可:

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

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

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

答案 18 :(得分:0)

这应该有效:

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