返回介绍

Beautiful Soup 搜索文档树

发布于 2024-05-19 17:35:14 字数 11238 浏览 0 评论 0 收藏 0

1. 过滤器

过滤器贯穿了整个搜索的 API。过滤器可以用于 Tagname 中, 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 参数:如果一个关键字参数的关键字不是 namerecursivetext 之一, 则搜索时会将该关键字参数当作指定名字的 Tag 属性来搜索。如: soup.find_all(id='a1') 将搜索 Tagid 属性。
    • 这种类型的过滤器可以为字符串过滤器、正则表达式过滤器、列表过滤器、 True 过滤器。
    • 如果使用了多个关键字参数,则可以同时过滤 Tag 的多个属性
    • 有些 Tag 属性在搜索时不能使用,如 HTML5 中的 data-* 属性,此时可以用 attrs 参数定义一个字典参数包含特殊属性的 Tag 。如: soup.find_all=(attrs={'data-foo':'value'})
    • 如果要搜索 TagCSS 属性,按理来说使用 class=xxx 关键字参数。 但是 Pythonclass 是个保留字,因此 BeautifulSoup 使用 class_ 关键字参数搜索有指定 CSS 类名的 Tag
      • 由于 TagCSS 属性是个多值属性,因此可以只指定某个 CSS 属性即可匹配
      • 由于 TagCSS 属性是个多值属性,你也可以匹配所有的 CSS 属性, 此时要求 CSS 类名的名字、顺序完全一致。

    其实这些都可以通过 attrs 关键字参数指定,该关键字参数的参数值是一个字典。 字典的键值对就指定了 Tag 的属性和值。

  • text 关键字参数:搜索 Tag 的字符串内容。搜索 text 参数的过滤器可以为字符串过滤器、正则表达式过滤器、列表过滤器、 True 过滤器。它返回的是 NavigableString 对象
    • 可以使用其他参数混合 text 关键字参数来过滤 Tag 。此时 BeautifulSoup 搜索 Tag.stringtext 参数值相符的 Tag
  • limit 关键字参数: find_all() 默认返回全部的搜索结果。如果文档树很大那么搜索会很慢。如果我们不需要全部结果可以使用 limit 关键字参数限制返回结果的上限。当搜索到的结果数量到达 limit 指定的值时,就停止搜索并返回结果。
  • recursive 关键字参数: find_all() 默认会搜索当前 Tag 的所有子孙节点。如果只想搜索 Tag 的直接子节点,可以用参数 recursive=False

nametext 关键字参数也接受自定义的过滤器(一个可调用对象或者函数)

由于 find_all() 是最常用的搜索方法,所以这里定义了它的简写方法: BeautifulSoup 对象和 Tag 对象作为可调用对象,其调用结果就是 find_all() 方法。如:

  • soup('a') 等价于 soup.find_all('a')
  • tag('a') 等价于 tag.find_all('a')

    find_all() 方法

3. find() 方法:

find(name,attrs,recursive,text,**kwargs) :只返回符合条件的第一个节点。它等价于 limit=1find_all() 调用。唯一的区别是 find_all() 返回结果是一个列表,而 find() 直接返回结果。

  • 如果没有找到目标,则 find_all() 返回空列表
  • 如果没有找到木,则 find() 返回 None

对于 soup.head.title 这种就是多次调用 find() 方法的简写。

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 ) 只在当前节点的子孙结点中搜索(注意并不搜索本节点本身)。

其他 find*() 方法

5. CSS 选择器

TagBeautifulSoup 对象的 .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" 的所有元素。
**选择所有元素。
elementp选择所有 <p> 元素。
element, elementdiv,p选择所有 <div> 元素和所有 <p> 元素。
element elementdiv p选择 <div> 元素内部的所有 <p> 元素。
element> elementdiv>p选择父元素为 <div> 元素的所有 <p> 元素。
element+ elementdiv+p选择紧接在 <div> 元素之后的所有 <p> 元素。
[ attribute][target]选择带有 target 属性所有元素。
[ attribute= value]>[target=_blank]选择 target="_blank" 的所有元素。
[ attribute~= value][title~=flower]选择 title 属性包含单词 "flower" 的所有元素。
[ attribute|= value][lang|=en]选择 lang 属性值以 "en" 开头的所有元素。
:linka:link选择所有未被访问的链接。
:visiteda:visited选择所有已被访问的链接。
:activea:active选择活动链接。
:hovera:hover选择鼠标指针位于其上的链接。
:focusinput:focus选择获得焦点的 input 元素。
:first-letterp:first-letter选择每个 <p> 元素的首字母。
:first-linep:first-line选择每个 <p> 元素的首行。
:first-childp:first-child选择属于父元素的第一个子元素的每个 <p> 元素。
:beforep:before在每个 <p> 元素的内容之前插入内容。
:afterp:after在每个 <p> 元素的内容之后插入内容。
:lang( language)p:lang(it)选择带有以 "it" 开头的 lang 属性值的每个 <p> 元素。
element1~ element2p~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-typep:first-of-type选择属于其父元素的首个 <p> 元素的每个 <p> 元素。
:last-of-typep:last-of-type选择属于其父元素的最后 <p> 元素的每个 <p> 元素。
:only-of-typep:only-of-type选择属于其父元素唯一的 <p> 元素的每个 <p> 元素。
:only-childp: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-childp:last-child选择属于其父元素最后一个子元素每个 <p> 元素。
:root:root选择文档的根元素。
:emptyp:empty选择没有子元素的每个 <p> 元素(包括文本节点)。
:target#news:target选择当前活动的 #news 元素。
:enabledinput:enabled选择每个启用的 <input> 元素。
:disabledinput:disabled选择每个禁用的 <input> 元素
:checkedinput:checked选择每个被选中的 <input> 元素。
:not( selector):not(p)选择非 <p> 元素的每个元素。
::selection::selection选择被用户选取的元素部分。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文