1. 使用 CSS 语法
BeautifulSoup 除了可以使用 find 与 find_all 函数查找 HTML 文档树的结点元素外,还可以采用 CSS 类似的语法来查询,
规则是:tag.select(css)
tag 是一个bs4.element.Tag对象,即 HTML 中的一个 element 结点元素;
select 是它的查找方法;
css 是类似 CSS 语法的一个字符串
其一般结构如下:
[tagName][attName[=value]]
其中[...]部分是可选的
tagName 是元素名称,如果没有指定就是所有元素
attName=value 是属性名称,value是它的对应的值,可以不指定属性,在指定了属性后也可以不指定值
tag.select(css) 返回一个 bs4.element.Tag 的列表,他怕只有一个元素也是一个列表
例:
soup.select("a") 查找文档中所有<a>元素结点(必须是双引);
soup.select("p a") 查找文档中所有<p>结点下的所有<a>元素结点;
soup.select("p[class='story'] a") 查找文档中所有属性class="story"的<p>结点下的所有<a>元素结点;
soup.select("p[class] a") 查找文档中所有具有class属性的<p>节点下的所有<a>元素节点;
soup.select("a[id='link1']") 查找属性id="link1"的<a>节点;
soup.select("body head title") 查找<body>下面<head>下面的<title>节点;
soup.select("body [class] ") 查找<body>下面所有具有class属性的节点;
soup.select("body [class] a") 查找<body>下面所有具有class属性的节点下面的<a>节点。
frombs4importBeautifulSoup
doc='''
<html><head><title>The Dormouse's story</title></head>
<body>
<p class="title"><b>The Dormouse's story</b></p>
<p class="story">
Once upon a time there were three little sisters; and their names were
<a href="https://example.com/elsie" class="sister" id="link1">Elsie</a>,
<a href="https://example.com/lacie" class="sister" id="link2">Lacie</a> and
<a href="https://example.com/tillie" class="sister" id="link3">Tillie</a>;
and they lived at the bottom of a well.
</p>
<p class="story">...</p>
</body>
</html>
'''
# 查找HTML文档中所有<p>下面的<a>的链接
soup=BeautifulSoup(doc, "lxml")
tags=soup.select("p[class='story'] a") # CSS 语法字符串能够较好把标签的层次结构进行简单多样的表达
# 另外我们通过
# tags=soup.select("p a")
# tags=soup.select("a")
# tags=soup.select("p[class] a") # 等也可以得到一样的结果。
fortagintags:print(tag["href"])# https://example.com/elsie# https://example.com/lacie# https://example.com/tillie
2. 属性的语法规则
在CSS结构中的 [attName=value] 表示属性attrName与value相等,也可以指定不等、包含等运算关系,
具体运算如下表:
选择器 | 描述 |
[attName] | 用于选取带有指定属性的元素。 |
[attName=value] | 用于选取带有指定属性和值的元素。 |
[attName^=value] | 匹配属性值以指定值开头的每个元素。 |
[attName$=value] | 匹配属性值以指定值结尾的每个元素。 |
[attrName*=value] | 匹配属性值中包含指定值的每个元素。 |
因此:
soup.select("a[href='http://example.com/elsie']") 查找href="http://example.com/elsie"的<a>节点;
soup.select("a[href$='sie']") 查找href以"sie"结尾的<a>节点;
soup.select("a[href^='http://example.com']") 查找href以"http://example.com"开始的<a>节点;
soup.select("a[href*='example']") 查找href的值中包含"example"字符串的<a>节点。
3. Select 查找子孙结点
在select(css)中的css有多个节点时,节点元素之间用空格分开,就是查找子孙节点,例如soup.select("div p")是查找所有<div>节点下面的所有子孙<p>节点。
frombs4importBeautifulSoup
doc="""<div><p>A</p><span><p>B</p></span></div><div><p>C</p></div>"""
# 查找子孙结点
soup=BeautifulSoup(doc, "lxml")
tags=soup.select("div p")
fortagintags:print(tag)# <p>A</p># <p>B</p># <p>C</p>
4. Select 查找直接子结点
在select(css)中的css有多个节点时,节点元素之间用" > "分开(注意 > 的前后至少包含一个空格),就是查找直接子节点,例如soup.select("div > p")是查找所有<div>节点下面的所有直接子节点<p>,不包含孙节点。
frombs4importBeautifulSoup
doc="""<div><p>A</p><span><p>B</p></span></div><div><p>C</p></div>"""
soup=BeautifulSoup(doc, "lxml")
tags=soup.select("div > p")
fortagintags:print(tag)# <p>A</p># <p>C</p>
5. Select 查找兄弟结点
在select中用" ~ "连接两个节点表示查找前一个节点后面的所有同级别的兄弟节点(注意 ~ 号前后至少有一个空格),例如soup.select("div ~ p")查找<div>后面的所有同级别的<p>兄弟节点。
在select中用" + "连接两个节点表示查找前一个节点后面的第一个同级别的兄弟节点(注意 + 号前后至少有一个空格)
frombs4importBeautifulSoup
doc="""<body>demo<div>A</div><b>X</b><p>B</p><span><p>C</p></span><p>D</p></div></body>"""
# 查找兄弟结点
soup=BeautifulSoup(doc, "lxml")
# print(soup.prettify()) # 修复后HTML文档树——去掉12行</div>
tags=soup.select("div ~ p")
fortagintags:print(tag)# <p>B</p># <p>D</p>
print()
tags=soup.select("div + p")
fortagintags:print(tag) # 没找到匹配结果