Python中bs4爬虫处理html标签的问题:如何解析带空格的属性标签?

<td class="stream-6771">
    <a href="javascript:void(0);" id="vid_667" class="vh"><code style="display:none">已发送</code><i>7621</i></a>
    <s></s>
</td>
dataSoup = BeautifulSoup(tr.prettify(),'lxml')
tmpStr = dataSoup.find_all("code", class_= ["code","style"])

查阅文档和看了百度别人的经验,理论上这么做是能获取到“已发送”的字符串,

是否跟 python 的版本有关系? 用的是 python3,文档似乎更新时间久了,python2 的写法不能用?

谢谢解答!


Python中bs4爬虫处理html标签的问题:如何解析带空格的属性标签?

5 回复

dataSoup.find_all(“code”)

dataSoup.find_all(attrs={‘style’: ‘display:none’})


帖子回复:

这个问题很常见,处理带空格的属性标签(比如 <div class="foo bar">)时,BeautifulSoup 的默认查找方法 find()find_all() 需要特别注意。你不能直接用完整的属性值去匹配,因为 class 属性实际上是一个多值属性,空格分隔了多个值。

核心解决方案是使用CSS选择器,或者对 class 参数进行特殊处理。

下面给你两个最直接、可运行的代码示例:

方法一:使用CSS选择器(推荐) BeautifulSoup 支持 .select() 方法,它使用CSS选择器语法,处理多值 class 非常直观。

from bs4 import BeautifulSoup

html_doc = """
<div class="foo bar">这个div有两个class</div>
<div class="foo">这个只有一个</div>
"""

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

# 查找 class 同时包含 "foo" 和 "bar" 的div
# CSS选择器用 . 表示class
results = soup.select('div.foo.bar')
for tag in results:
    print(tag.text)
# 输出:这个div有两个class

# 查找 class 包含 "foo" 的div(无论是否有其他class)
results2 = soup.select('div.foo')
for tag in results2:
    print(tag.text)
# 输出:
# 这个div有两个class
# 这个只有一个

方法二:使用 find_all 并指定 class_ 参数 find_allclass_ 参数(注意下划线)可以接收一个字符串、列表或正则表达式。当传入字符串时,它会匹配包含该字符串的class。

from bs4 import BeautifulSoup

html_doc = """
<div class="foo bar">这个div有两个class</div>
<div class="foo">这个只有一个</div>
"""

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

# 查找 class 包含 "foo" 的div
tags = soup.find_all('div', class_='foo')
for tag in tags:
    print(tag.text)
# 输出:
# 这个div有两个class
# 这个只有一个

# 如果要精确匹配多个class,可以传入一个列表
tags_exact = soup.find_all('div', class_=['foo', 'bar']) # 这匹配class为 *foo* 或 *bar* 的,不是同时包含!
print("列表匹配:", [t.text for t in tags_exact])

# 要精确匹配同时拥有 "foo" 和 "bar" 的div,用CSS选择器更简单,或者用lambda
tags_exact_all = soup.find_all('div', lambda tag: tag.get('class') == ['foo', 'bar'])
print("精确匹配:", [t.text for t in tags_exact_all])
# 输出:精确匹配: ['这个div有两个class']

总结一下:

  • 想匹配包含某个class的标签:直接用 find_all(..., class_='class_name')select('tag.class_name')
  • 想匹配同时包含多个class的标签:用CSS选择器 select('tag.class1.class2') 最省事。
  • 记住 tag.get('class') 返回的是一个列表,包含了所有用空格分隔的class值。

一句话建议:用 .select() 的CSS选择器语法来处理带空格的class属性最清晰。

,感谢您的回复解答,find_all(“code”)可以直接取出
<br>&lt;code style="display:none"&gt;已发送&lt;/code&gt;<br>

这个方法小喵是是摸索出来了,

其实帖里问的是如何直接取出“已发送”这三个中文字作为 tmpStr。。。

其实还是想知道如果换了方式,我还能明白技巧在哪里。。。

<br>&lt;code class="display:none"&gt;已发送变化方式之一&lt;/code&gt;<br>&lt;class fire="display:none"&gt;已发送变化方式之二&lt;/class&gt;<br>&lt;em class="display:none"&gt;已发送变化方式之三&lt;/em&gt;<br>

尽管不一定会有这样的 HTML 代码,只是想了解一下这种空格的标签,如何直接套取 text()。。。。。

感激不尽~~~!!!

.text。。

dataSoup.find(‘code’, attrs={‘style’:‘display:none’}).text

回到顶部