Beautiful Soup 搜索文档树
1. 过滤器
过滤器贯穿了整个搜索的 API。过滤器可以用于 Tag
的 name
中, Tag
的属性中, NavigableString
字符串中或者他们的混合中。
a. 字符串过滤器
最简单的过滤器就是字符串。在搜索方法中传入一个字符串参数, BeautifulSoup
会查找与字符串完整匹配的内容。
如果掺入字节码参数,则 BeautifulSoup
会将它作为 UTF-8
编码。
b. 正则表达式过滤器
如果传入正则表达式作为参数,则 BeautifulSoup
会通过正则表达式的 match()
来匹配内容。
c. 列表过滤器
如果传入列表参数,则 BeautifulSoup
将列表中任一元素匹配的内容返回。
d. True
过滤器
如果传入 True
作为参数,则可以匹配任何值。
e. 自定义过滤器
你可以自定义一个方法,该方法只接受一个元素参数。如果这个方法返回 True
,则表示当前元素匹配并且被找到。 如果该方法返回 False
,则表示不匹配。
2. find_all()
方法
Tag.find_all(name,attrs,recursive,text,**kwargs)
:搜索当前 Tag
的子节点,并返回符合过滤器条件的子节点。
name
参数:查找所有名字为name
的字Tag
。对于NavigableString
子节点会自动被忽略。 搜索name
参数的过滤器可以为字符串过滤器、正则表达式过滤器、列表过滤器、True
过滤器。keyword
参数:如果一个关键字参数的关键字不是name
、recursive
、text
之一, 则搜索时会将该关键字参数当作指定名字的Tag
属性来搜索。如:soup.find_all(id='a1')
将搜索Tag
的id
属性。- 这种类型的过滤器可以为字符串过滤器、正则表达式过滤器、列表过滤器、
True
过滤器。 - 如果使用了多个关键字参数,则可以同时过滤
Tag
的多个属性 - 有些
Tag
属性在搜索时不能使用,如HTML5
中的data-*
属性,此时可以用attrs
参数定义一个字典参数包含特殊属性的Tag
。如:soup.find_all=(attrs={'data-foo':'value'})
- 如果要搜索
Tag
的CSS
属性,按理来说使用class=xxx
关键字参数。 但是Python
中class
是个保留字,因此BeautifulSoup
使用class_
关键字参数搜索有指定CSS
类名的Tag
。- 由于
Tag
的CSS
属性是个多值属性,因此可以只指定某个CSS
属性即可匹配 - 由于
Tag
的CSS
属性是个多值属性,你也可以匹配所有的CSS
属性, 此时要求CSS
类名的名字、顺序完全一致。
- 由于
其实这些都可以通过
attrs
关键字参数指定,该关键字参数的参数值是一个字典。 字典的键值对就指定了Tag
的属性和值。- 这种类型的过滤器可以为字符串过滤器、正则表达式过滤器、列表过滤器、
text
关键字参数:搜索Tag
的字符串内容。搜索text
参数的过滤器可以为字符串过滤器、正则表达式过滤器、列表过滤器、True
过滤器。它返回的是NavigableString
对象- 可以使用其他参数混合
text
关键字参数来过滤Tag
。此时BeautifulSoup
搜索Tag.string
与text
参数值相符的Tag
。
- 可以使用其他参数混合
limit
关键字参数:find_all()
默认返回全部的搜索结果。如果文档树很大那么搜索会很慢。如果我们不需要全部结果可以使用limit
关键字参数限制返回结果的上限。当搜索到的结果数量到达limit
指定的值时,就停止搜索并返回结果。recursive
关键字参数:find_all()
默认会搜索当前Tag
的所有子孙节点。如果只想搜索Tag
的直接子节点,可以用参数recursive=False
。
name
、text
关键字参数也接受自定义的过滤器(一个可调用对象或者函数)
由于 find_all()
是最常用的搜索方法,所以这里定义了它的简写方法: BeautifulSoup
对象和 Tag
对象作为可调用对象,其调用结果就是 find_all()
方法。如:
soup('a')
等价于soup.find_all('a')
tag('a')
等价于tag.find_all('a')
3. find()
方法:
find(name,attrs,recursive,text,**kwargs)
:只返回符合条件的第一个节点。它等价于 limit=1
的 find_all()
调用。唯一的区别是 find_all()
返回结果是一个列表,而 find()
直接返回结果。
- 如果没有找到目标,则
find_all()
返回空列表 - 如果没有找到木,则
find()
返回None
对于 soup.head.title
这种就是多次调用 find()
方法的简写。
4. 其他搜索 find*()
方法
find_parents( name , attrs , recursive , text , **kwargs )
与find_parent( name , attrs , recursive , text , **kwargs )
: 参数与find_all()
相同,别在于搜索文档的不同部分。find_parents()
搜索当前节点的父辈节点然后过滤出所有符合条件的父辈节点。find_parent
搜索当前节点的父辈节点然后过滤出第一个符合条件的父辈节点。搜索父辈节点的方法实际上就是对.parents
属性的迭代搜索。find_next_siblings( name , attrs , recursive , text , **kwargs )
与find_next_sibling( name , attrs , recursive , text , **kwargs )
: 参数与find_all()
相同,区别在于搜索文档的不同部分。find_next_siblings()
搜索当前节点的后面的兄弟节点然后过滤出符合条件的所有后兄弟节点。find_next_sibling
只返回符合条件的后面兄弟节点中第一个符合条件的节点。搜索后兄弟节点的方法实际上就是对.next_siblings
属性的迭代搜索。find_previous_siblings( name , attrs , recursive , text , **kwargs )
与find_previous_sibling( name , attrs , recursive , text , **kwargs )
: 参数与find_all()
相同,区别在于搜索文档的不同部分。find_previous_siblings()
搜索当前节点的前面的兄弟节点然后过滤出符合条件的前兄弟节点。find_previous_sibling
只返回符合条件的前兄弟节点中第一个符合条件的节点。搜索前兄弟节点的方法实际上就是对.previous_siblings
属性的迭代搜索。find_all_next( name , attrs , recursive , text , **kwargs )
与find_next( name , attrs , recursive , text , **kwargs )
: 参数与find_all()
相同,区别在于搜索文档的不同部分。find_all_next()
搜索当前节点的后面解析的节点然后过滤出符合条件的后解析节点。find_next
只返回符合条件的所有后解析结点中第一个符合条件的结点。搜索后解析节点的方法实际上就是对.next_elements
属性的迭代搜索find_all_previous( name , attrs , recursive , text , **kwargs )
与find_previous( name , attrs , recursive , text , **kwargs )
: 参数与find_all()
相同,区别在于搜索文档的不同部分。find_all_previous()
搜索当前节点的前面解析的节点然后过滤出符合条件的前解析节点。find_previous
只返回符合条件的所有前解析结点中第一个满足条件的结点。搜索前解析节点的方法实际上就是对.previoust_elements
属性的迭代搜索
find_all( name , attrs , recursive , text , **kwargs )
与find( name , attrs , recursive , text , **kwargs )
只在当前节点的子孙结点中搜索(注意并不搜索本节点本身)。
5. CSS 选择器
在 Tag
和 BeautifulSoup
对象的 .select()
方法中传入字符串参数即可使用 CSS 选择器的语法找到 Tag
。 下面的示例是常见的 CSS 选择器:
soup.select('p') # 通过标签查找,选择所有的 p
soup.select('.cls') #通过 CSS 类名查找,选择 class=cls
soup.select('#id1') #通过`id=id1`查找
soup.select('div,p') #查找所有的 div 和 p
soup.select('div p') #查找 div 内部的所有的 p
soup.select('div>p') #查找直系父元素为 div 的所有的 p
soup.select('div+p') #查找紧接在 div 之后的所有 p
soup.select('[target]') #查找所有带 target 属性的元素
soup.select('[target=_blank]') #查找所有 target='_blank'的元素
选择器 | 例子 | 例子描述 |
---|---|---|
. class | .intro | 选择 class="intro" 的所有元素。 |
# id | #firstname | 选择 id="firstname" 的所有元素。 |
* | * | 选择所有元素。 |
element | p | 选择所有 <p> 元素。 |
element, element | div,p | 选择所有 <div> 元素和所有 <p> 元素。 |
element element | div p | 选择 <div> 元素内部的所有 <p> 元素。 |
element> element | div>p | 选择父元素为 <div> 元素的所有 <p> 元素。 |
element+ element | div+p | 选择紧接在 <div> 元素之后的所有 <p> 元素。 |
[ attribute] | [target] | 选择带有 target 属性所有元素。 |
[ attribute= value]> | [target=_blank] | 选择 target="_blank" 的所有元素。 |
[ attribute~= value] | [title~=flower] | 选择 title 属性包含单词 "flower" 的所有元素。 |
[ attribute|= value] | [lang|=en] | 选择 lang 属性值以 "en" 开头的所有元素。 |
:link | a:link | 选择所有未被访问的链接。 |
:visited | a:visited | 选择所有已被访问的链接。 |
:active | a:active | 选择活动链接。 |
:hover | a:hover | 选择鼠标指针位于其上的链接。 |
:focus | input:focus | 选择获得焦点的 input 元素。 |
:first-letter | p:first-letter | 选择每个 <p> 元素的首字母。 |
:first-line | p:first-line | 选择每个 <p> 元素的首行。 |
:first-child | p:first-child | 选择属于父元素的第一个子元素的每个 <p> 元素。 |
:before | p:before | 在每个 <p> 元素的内容之前插入内容。 |
:after | p:after | 在每个 <p> 元素的内容之后插入内容。 |
:lang( language) | p:lang(it) | 选择带有以 "it" 开头的 lang 属性值的每个 <p> 元素。 |
element1~ element2 | p~ul | 选择前面有 <p> 元素的每个 <ul> 元素。 |
[ attribute^= value] | a[src^="https"] | 选择其 src 属性值以 "https" 开头的每个 <a> 元素。 |
[ attribute$= value] | a[src$=".pdf"] | 选择其 src 属性以 ".pdf" 结尾的所有 <a> 元素。 |
[ attribute*= value] | a[src*="abc"] | 选择其 src 属性中包含 "abc" 子串的每个 <a> 元素。 |
:first-of-type | p:first-of-type | 选择属于其父元素的首个 <p> 元素的每个 <p> 元素。 |
:last-of-type | p:last-of-type | 选择属于其父元素的最后 <p> 元素的每个 <p> 元素。 |
:only-of-type | p:only-of-type | 选择属于其父元素唯一的 <p> 元素的每个 <p> 元素。 |
:only-child | p:only-child | 选择属于其父元素的唯一子元素的每个 <p> 元素。 |
:nth-child( n) | p:nth-child(2) | 选择属于其父元素的第二个子元素的每个 <p> 元素。 |
:nth-last-child( n) | p:nth-last-child(2) | 同上,从最后一个子元素开始计数。 |
:nth-of-type( n) | p:nth-of-type(2) | 选择属于其父元素第二个 <p> 元素的每个 <p> 元素。 |
:nth-last-of-type( n) | p:nth-last-of-type(2) | 同上,但是从最后一个子元素开始计数。 |
:last-child | p:last-child | 选择属于其父元素最后一个子元素每个 <p> 元素。 |
:root | :root | 选择文档的根元素。 |
:empty | p:empty | 选择没有子元素的每个 <p> 元素(包括文本节点)。 |
:target | #news:target | 选择当前活动的 #news 元素。 |
:enabled | input:enabled | 选择每个启用的 <input> 元素。 |
:disabled | input:disabled | 选择每个禁用的 <input> 元素 |
:checked | input:checked | 选择每个被选中的 <input> 元素。 |
:not( selector) | :not(p) | 选择非 <p> 元素的每个元素。 |
::selection | ::selection | 选择被用户选取的元素部分。 |
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论