BeautifulSoup findAll() 给定多个类?

BeautifulSoup findAll() given multiple classes?

提问人:sebo 提问时间:9/11/2013 最后编辑:alecxesebo 更新时间:4/29/2022 访问量:124743

问:

我想从网站上抓取项目列表,并保留它们的显示顺序。这些项目在表中组织,但它们可以是两个不同类之一(按随机顺序)。

有没有办法提供多个类并让 BeautifulSoup4 找到任何给定类中的所有项目?

我需要实现此代码的功能,除了保留源代码中的项顺序:

items = soup.findAll(True,{'class':'class1'})
items += soup.findAll(True,{'class':'class2'})
python html beautifulsoup html 解析

评论

0赞 sebo 9/11/2013
感谢 alecxe 和 Roman Pekar 帮助我解决这个问题。我能够使用部分类名和 alecxe 更新的答案中建议的额外检查来实现我想要的。

答:

14赞 alecxe 9/11/2013 #1

一种方法是使用正则表达式而不是类名:

import re
import requests
from bs4 import BeautifulSoup


s = requests.Session()
link = 'https://leaderboards.guildwars2.com/en/na/achievements'
r = s.get(link)


soup = BeautifulSoup(r.text)
for item in soup.findAll(True, {"class": re.compile("^(equal|up)$")}):
    if 'achievements' in item.attrs['class'] and 'number' in item.attrs['class']:
        print item

评论

0赞 sebo 9/11/2013
感谢您的快速回复。目前,该调用没有返回任何内容。这有可能是由类名中有空格引起的吗?(例如“第 1 类”)对不起,我对正则表达式一无所知。
0赞 alecxe 9/11/2013
@sebo您能展示您正在使用的代码,以便我可以重现和解决问题?
0赞 sebo 9/11/2013
剥离后,这是我正在查看的代码:这个代码正在应用 Roman Pekar 的解决方案,但它返回一个空列表。使用正则表达式解决方案也会发生同样的事情。不过,一次检索一个类都可以正常工作。对不起,格式很糟糕。import requests from bs4 import BeautifulSoup s = requests.Session() link = 'https://leaderboards.guildwars2.com/en/na/achievements' r = s.get(link) soup = BeautifulSoup(r.text) items = soup.findAll(True, {"class":["equal achievements number", "up achievements number"]})
1赞 alecxe 9/11/2013
它@sebo起作用?soup.findAll(True, {"class": ".*achievements number.*"})
0赞 sebo 9/11/2013
这也将返回一个空列表。
119赞 Roman Pekar 9/11/2013 #2

你可以这样做

soup.findAll(True, {'class':['class1', 'class2']})

例:

>>> from bs4 import BeautifulSoup
>>> soup = BeautifulSoup('<html><body><div class="class1"></div><div class="class2"></div><div class="class3"></div></body></html>')
>>> soup.findAll(True, {"class":["class1", "class2"]})
[<div class="class1"></div>, <div class="class2"></div>]

评论

0赞 sebo 9/11/2013
在我的代码中,这与 alecxe 的解决方案返回一个空列表的方式相同。有关我的代码,请参阅他的回复下的评论。
2赞 alecxe 9/11/2013
@sebo试试这个: .soup.findAll(True, {"class":["equal", "up"]})
0赞 Roman Pekar 9/11/2013
@alecxe这可行,+1 对你来说,但仍在尝试找到如何用完整的类名来工作
1赞 alecxe 9/11/2013
@RomanPekar谢谢。我认为不会将过滤器应用于整个属性值,而是按空格拆分类。请参阅 stackoverflow.com/questions/1242755/...bs4classclass
0赞 alecxe 9/11/2013
@RomanPekar我认为有一种方法可以解决它 - 在循环中添加一个额外的检查,请参阅我更新的答案。你觉得怎么样?
28赞 Bhoopi 8/12/2017 #3

我是 Python with BeautifulSoup 的新手,但可能是我的答案,可以帮助你。我遇到了同样的情况,我必须找到一个标签的多个类,所以我只需将这些类传递到一个数组中,它就对我有用。 下面是代码片段

# Search with single Class
    find_all("tr",  {"class":"abc"})
# Search with multiple classes
    find_all("tr",  {"class": ["abc", "xyz"]})

评论

13赞 Eduardo Pignatelli 9/23/2018
是对应选择器还是选择器?{"class": ["abc", "xyz"]}orand
11赞 Slick Slime 12/12/2018
它对应于or
21赞 Sundeep Pidugu 12/10/2019
我该怎么做?and
7赞 discover 7/6/2020
您可以使用 代替 .@SundeepPiduguselectfind_allselect('div.abc.xyz')
15赞 Abdelghani Bekka 3/16/2019 #4

或者使用最新版本的 BeautifulSoup:

find_all('a', class_=['class1', 'class2'])

使用“class”会返回错误,因此他们改用“class_”。

评论

0赞 Timo 1/31/2021
这是 ,请参阅其他答案的评论。orand
17赞 danilo 1/21/2021 #5
    <html>
        <body>
            <div class="cls1">ok</div>
            <div class="cls2">hi</div>
            <div class="cls1 cls2">both</div>
        </body>
    </html>

OR 运算符

    from bs4 import BeautifulSoup
    soup = BeautifulSoup(html)
    divs = soup.find_all('div', class_=['cls1', 'cls2'])
    print(divs)

输出:

[<div class="cls1">ok</div>, <div class="cls2">hi</div>, <div class="cls1 cls2">both</div>]

AND 运算符

    from bs4 import BeautifulSoup
    soup = BeautifulSoup(html)
    divs = soup.select('div.cls1.cls2')
    print(divs)

输出:

[<div class="cls1 cls2">both</div>]
2赞 Jose Francisco Cheble 11/2/2021 #6

如果您使用 Url 作为参数,请不要忘记传递标头。我花了大约一个小时来获得这些带有 2 个类的 div 元素,直到我注意到我忘记传递这个标头,它才对我不起作用。

header = {
    "Accept-Language": "es-ES,es;q=0.9",
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36"
}
url = 'something.com'
response = requests.get(url=url,headers=header)
response.raise_for_status()
data = response.text

soup = BeautifulSoup(data, 'html.parser')  

elements = soup.select('div.fde444d7ef._c445487e2')