gpt4 book ai didi

python - BeautifulSoup 网络抓取 find_all() : finding exact match

转载 作者:技术小花猫 更新时间:2023-10-29 12:22:29 25 4
gpt4 key购买 nike

我正在使用 Python 和 BeautifulSoup 进行网页抓取。

假设我有以下 html 代码要抓取:

<body>
<div class="product">Product 1</div>
<div class="product">Product 2</div>
<div class="product special">Product 3</div>
<div class="product special">Product 4</div>
</body>

使用 BeautifulSoup,我只想找到具有属性 class="product"的产品(仅产品 1 和 2),不是“特殊”产品

如果我执行以下操作:

result = soup.find_all('div', {'class': 'product'})

结果包括所有产品(1、2、3 和 4)。

我应该怎么做才能找到类别与“产品”完全匹配的产品?


我运行的代码:

from bs4 import BeautifulSoup
import re

text = """
<body>
<div class="product">Product 1</div>
<div class="product">Product 2</div>
<div class="product special">Product 3</div>
<div class="product special">Product 4</div>
</body>"""

soup = BeautifulSoup(text)
result = soup.findAll(attrs={'class': re.compile(r"^product$")})
print result

输出:

[<div class="product">Product 1</div>, <div class="product">Product 2</div>, <div class="product special">Product 3</div>, <div class="product special">Product 4</div>]

最佳答案

在 BeautifulSoup 4 中,class 属性(以及其他几个属性,例如 accesskey 和表格单元格元素上的 headers 属性)是作为一个集合处理;您匹配属性中列出的各个元素。这遵循 HTML 标准。

因此,您不能将搜索仅限于一个类。

你必须使用 custom function在这里与类匹配:

result = soup.find_all(lambda tag: tag.name == 'div' and 
tag.get('class') == ['product'])

我使用 lambda 创建了一个匿名函数;每个标签都匹配名称(必须是 'div'),并且类属性必须完全等于列表 ['product'];例如只有一个值。

演示:

>>> from bs4 import BeautifulSoup
>>> text = """
... <body>
... <div class="product">Product 1</div>
... <div class="product">Product 2</div>
... <div class="product special">Product 3</div>
... <div class="product special">Product 4</div>
... </body>"""
>>> soup = BeautifulSoup(text)
>>> soup.find_all(lambda tag: tag.name == 'div' and tag.get('class') == ['product'])
[<div class="product">Product 1</div>, <div class="product">Product 2</div>]

为了完整起见,以下是所有此类设置属性,来自 BeautifulSoup 源代码:

# The HTML standard defines these attributes as containing a
# space-separated list of values, not a single value. That is,
# class="foo bar" means that the 'class' attribute has two values,
# 'foo' and 'bar', not the single value 'foo bar'. When we
# encounter one of these attributes, we will parse its value into
# a list of values if possible. Upon output, the list will be
# converted back into a string.
cdata_list_attributes = {
"*" : ['class', 'accesskey', 'dropzone'],
"a" : ['rel', 'rev'],
"link" : ['rel', 'rev'],
"td" : ["headers"],
"th" : ["headers"],
"td" : ["headers"],
"form" : ["accept-charset"],
"object" : ["archive"],

# These are HTML5 specific, as are *.accesskey and *.dropzone above.
"area" : ["rel"],
"icon" : ["sizes"],
"iframe" : ["sandbox"],
"output" : ["for"],
}

关于python - BeautifulSoup 网络抓取 find_all() : finding exact match,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22726860/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com