搜索文档树

Beautiful Soup定义了很多搜索方法,这里着重介绍2个: find() 和 find_all() .其它方法的参数和用法类似,请读者举一反三.

再以“爱丽丝”文档作为例子:

  1. html_doc = """
  2. <html><head><title>The Dormouse's story</title></head>
  3. <body>
  4. <p class="title"><b>The Dormouse's story</b></p>
  5.  
  6. <p class="story">Once upon a time there were three little sisters; and their names were
  7. <a href="http://example.com/elsie" class="sister" id="link1">Elsie</a>,
  8. <a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and
  9. <a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>;
  10. and they lived at the bottom of a well.</p>
  11.  
  12. <p class="story">...</p>
  13. """
  14.  
  15. from bs4 import BeautifulSoup
  16. soup = BeautifulSoup(html_doc, 'html.parser')

使用 find_all() 类似的方法可以查找到想要查找的文档内容

过滤器

介绍 find_all() 方法前,先介绍一下过滤器的类型 [3] ,这些过滤器贯穿整个搜索的API.过滤器可以被用在tag的name中,节点的属性中,字符串中或他们的混合中.

字符串

最简单的过滤器是字符串.在搜索方法中传入一个字符串参数,Beautiful Soup会查找与字符串完整匹配的内容,下面的例子用于查找文档中所有的<b>标签:

  1. soup.find_all('b')
  2. # [<b>The Dormouse's story</b>]

如果传入字节码参数,Beautiful Soup会当作UTF-8编码,可以传入一段Unicode 编码来避免Beautiful Soup解析编码出错

正则表达式

如果传入正则表达式作为参数,Beautiful Soup会通过正则表达式的 match() 来匹配内容.下面例子中找出所有以b开头的标签,这表示<body>和<b>标签都应该被找到:

  1. import re
  2. for tag in soup.find_all(re.compile("^b")):
  3. print(tag.name)
  4. # body
  5. # b

下面代码找出所有名字中包含”t”的标签:

  1. for tag in soup.find_all(re.compile("t")):
  2. print(tag.name)
  3. # html
  4. # title

列表

如果传入列表参数,Beautiful Soup会将与列表中任一元素匹配的内容返回.下面代码找到文档中所有<a>标签和<b>标签:

  1. soup.find_all(["a", "b"])
  2. # [<b>The Dormouse's story</b>,
  3. # <a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>,
  4. # <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>,
  5. # <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]

True

True 可以匹配任何值,下面代码查找到所有的tag,但是不会返回字符串节点

  1. for tag in soup.find_all(True):
  2. print(tag.name)
  3. # html
  4. # head
  5. # title
  6. # body
  7. # p
  8. # b
  9. # p
  10. # a
  11. # a
  12. # a
  13. # p

方法

如果没有合适过滤器,那么还可以定义一个方法,方法只接受一个元素参数 [4] ,如果这个方法返回 True表示当前元素匹配并且被找到,如果不是则反回 False

下面方法校验了当前元素,如果包含 class 属性却不包含 id 属性,那么将返回 True:

  1. def has_class_but_no_id(tag):
  2. return tag.has_attr('class') and not tag.has_attr('id')

将这个方法作为参数传入 find_all() 方法,将得到所有<p>标签:

  1. soup.find_all(has_class_but_no_id)
  2. # [<p class="title"><b>The Dormouse's story</b></p>,
  3. # <p class="story">Once upon a time there were...</p>,
  4. # <p class="story">...</p>]

返回结果中只有<p>标签没有<a>标签,因为<a>标签还定义了”id”,没有返回<html>和<head>,因为<html>和<head>中没有定义”class”属性.

通过一个方法来过滤一类标签属性的时候, 这个方法的参数是要被过滤的属性的值, 而不是这个标签. 下面的例子是找出 href 属性不符合指定正则的 a 标签.

  1. def not_lacie(href):
  2. return href and not re.compile("lacie").search(href)
  3. soup.find_all(href=not_lacie)
  4. # [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>,
  5. # <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]

标签过滤方法可以使用复杂方法. 下面的例子可以过滤出前后都有文字的标签.

  1. from bs4 import NavigableString
  2. def surrounded_by_strings(tag):
  3. return (isinstance(tag.next_element, NavigableString)
  4. and isinstance(tag.previous_element, NavigableString))
  5.  
  6. for tag in soup.find_all(surrounded_by_strings):
  7. print tag.name
  8. # p
  9. # a
  10. # a
  11. # a
  12. # p

现在来了解一下搜索方法的细节

find_all()

find_all( name , attrs , recursive , string , **kwargs )

find_all() 方法搜索当前tag的所有tag子节点,并判断是否符合过滤器的条件.这里有几个例子:

  1. soup.find_all("title")
  2. # [<title>The Dormouse's story</title>]
  3.  
  4. soup.find_all("p", "title")
  5. # [<p class="title"><b>The Dormouse's story</b></p>]
  6.  
  7. soup.find_all("a")
  8. # [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>,
  9. # <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>,
  10. # <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]
  11.  
  12. soup.find_all(id="link2")
  13. # [<a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>]
  14.  
  15. import re
  16. soup.find(string=re.compile("sisters"))
  17. # u'Once upon a time there were three little sisters; and their names were\n'

有几个方法很相似,还有几个方法是新的,参数中的 string 和 id 是什么含义? 为什么 find_all("p", "title")返回的是CSS Class为”title”的<p>标签? 我们来仔细看一下 find_all() 的参数

name 参数

name 参数可以查找所有名字为 name 的tag,字符串对象会被自动忽略掉.

简单的用法如下:

  1. soup.find_all("title")
  2. # [<title>The Dormouse's story</title>]

重申: 搜索 name 参数的值可以使任一类型的 过滤器 ,字符窜,正则表达式,列表,方法或是 True .

keyword 参数

如果一个指定名字的参数不是搜索内置的参数名,搜索时会把该参数当作指定名字tag的属性来搜索,如果包含一个名字为 id 的参数,Beautiful Soup会搜索每个tag的”id”属性.

  1. soup.find_all(id='link2')
  2. # [<a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>]

如果传入 href 参数,Beautiful Soup会搜索每个tag的”href”属性:

  1. soup.find_all(href=re.compile("elsie"))
  2. # [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>]

搜索指定名字的属性时可以使用的参数值包括 字符串 , 正则表达式 , 列表True .

下面的例子在文档树中查找所有包含 id 属性的tag,无论 id 的值是什么:

  1. soup.find_all(id=True)
  2. # [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>,
  3. # <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>,
  4. # <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]

使用多个指定名字的参数可以同时过滤tag的多个属性:

  1. soup.find_all(href=re.compile("elsie"), id='link1')
  2. # [<a class="sister" href="http://example.com/elsie" id="link1">three</a>]

有些tag属性在搜索不能使用,比如HTML5中的 data-* 属性:

  1. data_soup = BeautifulSoup('<div data-foo="value">foo!</div>')
  2. data_soup.find_all(data-foo="value")
  3. # SyntaxError: keyword can't be an expression

但是可以通过 find_all() 方法的 attrs 参数定义一个字典参数来搜索包含特殊属性的tag:

  1. data_soup.find_all(attrs={"data-foo": "value"})
  2. # [<div data-foo="value">foo!</div>]

按CSS搜索

按照CSS类名搜索tag的功能非常实用,但标识CSS类名的关键字 class 在Python中是保留字,使用 class做参数会导致语法错误.从Beautiful Soup的4.1.1版本开始,可以通过 class_ 参数搜索有指定CSS类名的tag:

  1. soup.find_all("a", class_="sister")
  2. # [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>,
  3. # <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>,
  4. # <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]

class_ 参数同样接受不同类型的 过滤器 ,字符串,正则表达式,方法或 True :

  1. soup.find_all(class_=re.compile("itl"))
  2. # [<p class="title"><b>The Dormouse's story</b></p>]
  3.  
  4. def has_six_characters(css_class):
  5. return css_class is not None and len(css_class) == 6
  6.  
  7. soup.find_all(class_=has_six_characters)
  8. # [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>,
  9. # <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>,
  10. # <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]

tag的 class 属性是 多值属性 .按照CSS类名搜索tag时,可以分别搜索tag中的每个CSS类名:

  1. css_soup = BeautifulSoup('<p class="body strikeout"></p>')
  2. css_soup.find_all("p", class_="strikeout")
  3. # [<p class="body strikeout"></p>]
  4.  
  5. css_soup.find_all("p", class_="body")
  6. # [<p class="body strikeout"></p>]

搜索 class 属性时也可以通过CSS值完全匹配:

  1. css_soup.find_all("p", class_="body strikeout")
  2. # [<p class="body strikeout"></p>]

完全匹配 class 的值时,如果CSS类名的顺序与实际不符,将搜索不到结果:

  1. soup.find_all("a", attrs={"class": "sister"})
  2. # [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>,
  3. # <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>,
  4. # <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]

string 参数

通过 string 参数可以搜搜文档中的字符串内容.与 name 参数的可选值一样, string 参数接受 字符串 , 正则表达式 , 列表True . 看例子:

  1. soup.find_all(string="Elsie")
  2. # [u'Elsie']
  3.  
  4. soup.find_all(string=["Tillie", "Elsie", "Lacie"])
  5. # [u'Elsie', u'Lacie', u'Tillie']
  6.  
  7. soup.find_all(string=re.compile("Dormouse"))
  8. [u"The Dormouse's story", u"The Dormouse's story"]
  9.  
  10. def is_the_only_string_within_a_tag(s):
  11. ""Return True if this string is the only child of its parent tag.""
  12. return (s == s.parent.string)
  13.  
  14. soup.find_all(string=is_the_only_string_within_a_tag)
  15. # [u"The Dormouse's story", u"The Dormouse's story", u'Elsie', u'Lacie', u'Tillie', u'...']

虽然 string 参数用于搜索字符串,还可以与其它参数混合使用来过滤tag.Beautiful Soup会找到 .string方法与 string 参数值相符的tag.下面代码用来搜索内容里面包含“Elsie”的<a>标签:

  1. soup.find_all("a", string="Elsie")
  2. # [<a href="http://example.com/elsie" class="sister" id="link1">Elsie</a>]

limit 参数

find_all() 方法返回全部的搜索结构,如果文档树很大那么搜索会很慢.如果我们不需要全部结果,可以使用 limit 参数限制返回结果的数量.效果与SQL中的limit关键字类似,当搜索到的结果数量达到 limit 的限制时,就停止搜索返回结果.

文档树中有3个tag符合搜索条件,但结果只返回了2个,因为我们限制了返回数量:

  1. soup.find_all("a", limit=2)
  2. # [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>,
  3. # <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>]

recursive 参数

调用tag的 find_all() 方法时,Beautiful Soup会检索当前tag的所有子孙节点,如果只想搜索tag的直接子节点,可以使用参数 recursive=False .

一段简单的文档:

  1. <html>
  2. <head>
  3. <title>
  4. The Dormouse's story
  5. </title>
  6. </head>
  7. ...

是否使用 recursive 参数的搜索结果:

  1. soup.html.find_all("title")
  2. # [<title>The Dormouse's story</title>]
  3.  
  4. soup.html.find_all("title", recursive=False)
  5. # []

这是文档片段

  1. <html>
  2. <head>
  3. <title>
  4. The Dormouse's story
  5. </title>
  6. </head>
  7. ...

<title>标签在 <html> 标签下, 但并不是直接子节点, <head> 标签才是直接子节点. 在允许查询所有后代节点时 Beautiful Soup 能够查找到 <title> 标签. 但是使用了 recursive=False 参数之后,只能查找直接子节点,这样就查不到 <title> 标签了.

Beautiful Soup 提供了多种DOM树搜索方法. 这些方法都使用了类似的参数定义. 比如这些方法: find_all()nameattrstextlimit. 但是只有 find_all() 和 find() 支持 recursive 参数.

像调用 find_all() 一样调用tag

find_all() 几乎是Beautiful Soup中最常用的搜索方法,所以我们定义了它的简写方法. BeautifulSoup 对象和 tag 对象可以被当作一个方法来使用,这个方法的执行结果与调用这个对象的 find_all() 方法相同,下面两行代码是等价的:

  1. soup.find_all("a")
  2. soup("a")

这两行代码也是等价的:

  1. soup.title.find_all(string=True)
  2. soup.title(string=True)

find()

find( name , attrs , recursive , string , **kwargs )

find_all() 方法将返回文档中符合条件的所有tag,尽管有时候我们只想得到一个结果.比如文档中只有一个<body>标签,那么使用 find_all() 方法来查找<body>标签就不太合适, 使用 find_all 方法并设置 limit=1 参数不如直接使用 find() 方法.下面两行代码是等价的:

  1. soup.find_all('title', limit=1)
  2. # [<title>The Dormouse's story</title>]
  3.  
  4. soup.find('title')
  5. # <title>The Dormouse's story</title>

唯一的区别是 find_all() 方法的返回结果是值包含一个元素的列表,而 find() 方法直接返回结果.

find_all() 方法没有找到目标是返回空列表, find() 方法找不到目标时,返回 None .

  1. print(soup.find("nosuchtag"))
  2. # None

soup.head.title 是 tag的名字 方法的简写.这个简写的原理就是多次调用当前tag的 find() 方法:

  1. soup.head.title
  2. # <title>The Dormouse's story</title>
  3.  
  4. soup.find("head").find("title")
  5. # <title>The Dormouse's story</title>

find_parents() 和 find_parent()

find_parents( name , attrs , recursive , string , **kwargs )

find_parent( name , attrs , recursive , string , **kwargs )

我们已经用了很大篇幅来介绍 find_all() 和 find() 方法,Beautiful Soup中还有10个用于搜索的API.它们中的五个用的是与 find_all() 相同的搜索参数,另外5个与 find() 方法的搜索参数类似.区别仅是它们搜索文档的不同部分.

记住: find_all() 和 find() 只搜索当前节点的所有子节点,孙子节点等. find_parents() 和 find_parent() 用来搜索当前节点的父辈节点,搜索方法与普通tag的搜索方法相同,搜索文档搜索文档包含的内容. 我们从一个文档中的一个叶子节点开始:

  1. a_string = soup.find(string="Lacie")
  2. a_string
  3. # u'Lacie'
  4.  
  5. a_string.find_parents("a")
  6. # [<a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>]
  7.  
  8. a_string.find_parent("p")
  9. # <p class="story">Once upon a time there were three little sisters; and their names were
  10. # <a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>,
  11. # <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a> and
  12. # <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>;
  13. # and they lived at the bottom of a well.</p>
  14.  
  15. a_string.find_parents("p", class="title")
  16. # []

文档中的一个<a>标签是是当前叶子节点的直接父节点,所以可以被找到.还有一个<p>标签,是目标叶子节点的间接父辈节点,所以也可以被找到.包含class值为”title”的<p>标签不是不是目标叶子节点的父辈节点,所以通过 find_parents() 方法搜索不到.

find_parent() 和 find_parents() 方法会让人联想到 .parent 和 .parents 属性.它们之间的联系非常紧密.搜索父辈节点的方法实际上就是对 .parents 属性的迭代搜索.

find_next_siblings() 合 find_next_sibling()

find_next_siblings( name , attrs , recursive , string , **kwargs )

find_next_sibling( name , attrs , recursive , string , **kwargs )

这2个方法通过 .next_siblings 属性对当tag的所有后面解析 [5] 的兄弟tag节点进行迭代, find_next_siblings() 方法返回所有符合条件的后面的兄弟节点, find_next_sibling() 只返回符合条件的后面的第一个tag节点.

  1. first_link = soup.a
  2. first_link
  3. # <a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>
  4.  
  5. first_link.find_next_siblings("a")
  6. # [<a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>,
  7. # <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]
  8.  
  9. first_story_paragraph = soup.find("p", "story")
  10. first_story_paragraph.find_next_sibling("p")
  11. # <p class="story">...</p>

find_previous_siblings() 和 find_previous_sibling()

find_previous_siblings( name , attrs , recursive , string , **kwargs )

find_previous_sibling( name , attrs , recursive , string , **kwargs )

这2个方法通过 .previous_siblings 属性对当前tag的前面解析 [5] 的兄弟tag节点进行迭代, find_previous_siblings() 方法返回所有符合条件的前面的兄弟节点, find_previous_sibling() 方法返回第一个符合条件的前面的兄弟节点:

  1. last_link = soup.find("a", id="link3")
  2. last_link
  3. # <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>
  4.  
  5. last_link.find_previous_siblings("a")
  6. # [<a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>,
  7. # <a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>]
  8.  
  9. first_story_paragraph = soup.find("p", "story")
  10. first_story_paragraph.find_previous_sibling("p")
  11. # <p class="title"><b>The Dormouse's story</b></p>

find_all_next() 和 find_next()

find_all_next( name , attrs , recursive , string , **kwargs )

find_next( name , attrs , recursive , string , **kwargs )

这2个方法通过 .next_elements 属性对当前tag的之后的 [5] tag和字符串进行迭代, find_all_next() 方法返回所有符合条件的节点, find_next() 方法返回第一个符合条件的节点:

  1. first_link = soup.a
  2. first_link
  3. # <a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>
  4.  
  5. first_link.find_all_next(string=True)
  6. # [u'Elsie', u',\n', u'Lacie', u' and\n', u'Tillie',
  7. # u';\nand they lived at the bottom of a well.', u'\n\n', u'...', u'\n']
  8.  
  9. first_link.find_next("p")
  10. # <p class="story">...</p>

第一个例子中,字符串 “Elsie”也被显示出来,尽管它被包含在我们开始查找的<a>标签的里面.第二个例子中,最后一个<p>标签也被显示出来,尽管它与我们开始查找位置的<a>标签不属于同一部分.例子中,搜索的重点是要匹配过滤器的条件,并且在文档中出现的顺序而不是开始查找的元素的位置.

find_all_previous() 和 find_previous()

find_all_previous( name , attrs , recursive , string , **kwargs )

find_previous( name , attrs , recursive , string , **kwargs )

这2个方法通过 .previous_elements 属性对当前节点前面 [5] 的tag和字符串进行迭代, find_all_previous() 方法返回所有符合条件的节点, find_previous() 方法返回第一个符合条件的节点.

  1. first_link = soup.a
  2. first_link
  3. # <a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>
  4.  
  5. first_link.find_all_previous("p")
  6. # [<p class="story">Once upon a time there were three little sisters; ...</p>,
  7. # <p class="title"><b>The Dormouse's story</b></p>]
  8.  
  9. first_link.find_previous("title")
  10. # <title>The Dormouse's story</title>

find_all_previous("p") 返回了文档中的第一段(class=”title”的那段),但还返回了第二段,<p>标签包含了我们开始查找的<a>标签.不要惊讶,这段代码的功能是查找所有出现在指定<a>标签之前的<p>标签,因为这个<p>标签包含了开始的<a>标签,所以<p>标签一定是在<a>之前出现的.

CSS选择器

Beautiful Soup支持大部分的CSS选择器 http://www.w3.org/TR/CSS2/selector.html [6] , 在 Tag 或 BeautifulSoup 对象的 .select() 方法中传入字符串参数, 即可使用CSS选择器的语法找到tag:

  1. soup.select("title")
  2. # [<title>The Dormouse's story</title>]
  3.  
  4. soup.select("p nth-of-type(3)")
  5. # [<p class="story">...</p>]

通过tag标签逐层查找:

  1. soup.select("body a")
  2. # [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>,
  3. # <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>,
  4. # <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]
  5.  
  6. soup.select("html head title")
  7. # [<title>The Dormouse's story</title>]

找到某个tag标签下的直接子标签 [6] :

  1. soup.select("head > title")
  2. # [<title>The Dormouse's story</title>]
  3.  
  4. soup.select("p > a")
  5. # [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>,
  6. # <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>,
  7. # <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]
  8.  
  9. soup.select("p > a:nth-of-type(2)")
  10. # [<a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>]
  11.  
  12. soup.select("p > #link1")
  13. # [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>]
  14.  
  15. soup.select("body > a")
  16. # []

找到兄弟节点标签:

  1. soup.select("#link1 ~ .sister")
  2. # [<a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>,
  3. # <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]
  4.  
  5. soup.select("#link1 + .sister")
  6. # [<a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>]

通过CSS的类名查找:

  1. soup.select(".sister")
  2. # [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>,
  3. # <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>,
  4. # <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]
  5.  
  6. soup.select("[class~=sister]")
  7. # [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>,
  8. # <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>,
  9. # <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]

通过tag的id查找:

  1. soup.select("#link1")
  2. # [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>]
  3.  
  4. soup.select("a#link2")
  5. # [<a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>]

同时用多种CSS选择器查询元素:

  1. soup.select("#link1,#link2")
  2. # [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>,
  3. # <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>]

通过是否存在某个属性来查找:

  1. soup.select('a[href]')
  2. # [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>,
  3. # <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>,
  4. # <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]

通过属性的值来查找:

  1. soup.select('a[href="http://example.com/elsie"]')
  2. # [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>]
  3.  
  4. soup.select('a[href^="http://example.com/"]')
  5. # [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>,
  6. # <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>,
  7. # <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]
  8.  
  9. soup.select('a[href$="tillie"]')
  10. # [<a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]
  11.  
  12. soup.select('a[href*=".com/el"]')
  13. # [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>]

通过语言设置来查找:

  1. multilingual_markup = """
  2. <p lang="en">Hello</p>
  3. <p lang="en-us">Howdy, y'all</p>
  4. <p lang="en-gb">Pip-pip, old fruit</p>
  5. <p lang="fr">Bonjour mes amis</p>
  6. """
  7. multilingual_soup = BeautifulSoup(multilingual_markup)
  8. multilingual_soup.select('p[lang|=en]')
  9. # [<p lang="en">Hello</p>,
  10. # <p lang="en-us">Howdy, y'all</p>,
  11. # <p lang="en-gb">Pip-pip, old fruit</p>]

返回查找到的元素的第一个

  1. soup.select_one(".sister")
  2. # <a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>

对于熟悉CSS选择器语法的人来说这是个非常方便的方法.Beautiful Soup也支持CSS选择器API, 如果你仅仅需要CSS选择器的功能,那么直接使用 lxml 也可以, 而且速度更快,支持更多的CSS选择器语法,但Beautiful Soup整合了CSS选择器的语法和自身方便使用API.

<wiz_tmp_tag id="wiz-table-range-border" contenteditable="false" style="display: none;">

 

bs4--官文--搜索文档树的更多相关文章

  1. 使用requests爬取梨视频、bilibili视频、汽车之家,bs4遍历文档树、搜索文档树,css选择器

    今日内容概要 使用requests爬取梨视频 requests+bs4爬取汽车之家 bs4遍历文档树 bs4搜索文档树 css选择器 内容详细 1.使用requests爬取梨视频 # 模拟发送http ...

  2. Python爬虫系列(六):搜索文档树

    今天早上,写的东西掉了.这个烂知乎,有bug,说了自动保存草稿,其实并没有保存.无语 今晚,我们将继续讨论如何分析html文档. 1.字符串 #直接找元素soup.find_all('b') 2.正则 ...

  3. bs4--官文--修改文档树

    修改文档树 Beautiful Soup的强项是文档树的搜索,但同时也可以方便的修改文档树 修改tag的名称和属性 在 Attributes 的章节中已经介绍过这个功能,但是再看一遍也无妨. 重命名一 ...

  4. bs4--官文--遍历文档树

    遍历文档树 还拿”爱丽丝梦游仙境”的文档来做例子: html_doc = """ <html><head><title>The Dor ...

  5. 使用Python爬虫库BeautifulSoup遍历文档树并对标签进行操作详解(新手必学)

    为大家介绍下Python爬虫库BeautifulSoup遍历文档树并对标签进行操作的详细方法与函数下面就是使用Python爬虫库BeautifulSoup对文档树进行遍历并对标签进行操作的实例,都是最 ...

  6. 【Lucene3.6.2入门系列】第14节_SolrJ操作索引和搜索文档以及整合中文分词

    package com.jadyer.solrj; import java.util.ArrayList; import java.util.List; import org.apache.solr. ...

  7. es之java搜索文档

    1:搜索文档数据(单个索引) @Test public void getSingleDocument(){ GetResponse response = client.prepareGet(" ...

  8. SearchRequest用于与搜索文档、聚合、定制查询有关的任何操作

    SearchRequest用于与搜索文档.聚合.定制查询有关的任何操作,还提供了在查询结果的基于上,对于匹配的关键词进行突出显示的方法. 1,首先创建搜索请求对象:SearchRequest sear ...

  9. 算法进阶面试题05——树形dp解决步骤、返回最大搜索二叉子树的大小、二叉树最远两节点的距离、晚会最大活跃度、手撕缓存结构LRU

    接着第四课的内容,加入部分第五课的内容,主要介绍树形dp和LRU 第一题: 给定一棵二叉树的头节点head,请返回最大搜索二叉子树的大小 二叉树的套路 统一处理逻辑:假设以每个节点为头的这棵树,他的最 ...

随机推荐

  1. 2、linux基础知识与技能

    2.1.linux内核.发行版linux本身指的是一个操作系统内核,只有内核是无法直接使用的.我们需要的,可以使用的操作系统是一个包含了内核和一批有用的应用程序的一个集合体,这个就叫linux发行版. ...

  2. spring assert 用法

    spring在提供一个强大的应用开发框架的同时也提供了很多优秀的开发工具类,合理的运用这些工具,将有助于提高开发效率.增强代码质量.下面就最常用的Assert工具类,简要介绍一下它的用法.Assert ...

  3. Python网络编程中的服务器架构(负载均衡、单线程、多线程和同步、异步等)

    这篇文章主要介绍服务器架构. 网络服务需要面对两个挑战. 第一个问题是核心挑战,要编写出能够正确处理请求并构造合适响应的代码. 第二个挑战是如何将网络代码部署到随系统自动启动的Windows服务或者是 ...

  4. P3818 小A和uim之大逃离 II

    题目背景 话说上回……还是参见 https://www.luogu.org/problem/show?pid=1373 吧 小a和uim再次来到雨林中探险.突然一阵南风吹来,一片乌云从南部天边急涌过来 ...

  5. 写TXT文件

    #region 写日志 private static void writelog(string strwrite) { string strPath = "d:/log.txt"; ...

  6. Spring MVC 示例

    Srping MVC项目结构如下: 一.首先创建一个Dynamic Web Project 二.WebContent/WEB-INF/文件夹下新增 web.xml,配置servlet 容器对于web. ...

  7. ABAP数据转换规则

    数据转换规则: 可以将基本数据类型的源字段内容赋给其它基本数据类型的目标字段(除了数据类型 D 无法赋给数据类型 T,反之亦然).ABAP/4 也支持结构化数据和基本数据对象之间或结构不同的数据对象之 ...

  8. 兼容IE9以下的获取兄弟节点

    function fileCheck(ele){ function getNextElement(node){ //兼容IE9以下的 获取兄弟节点 var NextElementNode = node ...

  9. Android Framework中的Application Framework层介绍

    Android的四层架构相比大家都很清楚,老生常谈的说一下分别为:Linux2.6内核层,核心库层,应用框架层,应用层.我今天重点介绍一下应用框架层Framework,其实也是我自己的学习心得. Fr ...

  10. 判断JS数据类型的几种方法

    原文转自http://www.cnblogs.com/onepixel/p/5126046.html! 说到数据类型,我们先说一下JavaScript 中常见的几种数据类型: 基本类型:string, ...