使用BeautifulSoup4解析XML

柔情只为你懂 2022-04-15 05:35 366阅读 0赞

Beautiful Soup 是一个用来从HTML或XML文件中提取数据的Python库,它利用大家所喜欢的解析器提供了许多惯用方法用来对文档树进行导航、查找和修改。

帮助文档英文版:https://www.crummy.com/software/BeautifulSoup/bs4/doc/

帮助文档中文版:https://www.crummy.com/software/BeautifulSoup/bs4/doc.zh/

入门示例

以下是电影《爱丽丝梦游仙境》中的一段HTML内容:

20181122100852783.png

我们以此为例,对如何使用BeautifulSoup解析HTML页面内容进行简单入门示例:

  1. from bs4 import BeautifulSoup
  2. # 《爱丽丝梦游仙境》故事片段
  3. html_doc = """
  4. <html>
  5. <head><title>The Dormouse's story</title></head>
  6. <body>
  7. <p class="title"><b>The Dormouse's story</b></p>
  8. <p class="story">Once upon a time there were three little sisters; and their names were
  9. <a href="http://example.com/elsie" class="sister" id="link1">Elsie</a>,
  10. <a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and
  11. <a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>;
  12. and they lived at the bottom of a well.</p>
  13. <p class="story">...</p>
  14. </body>
  15. </html>
  16. """
  17. # 构造解析树
  18. soup = BeautifulSoup(html_doc, "html.parser")
  19. # 美化输出
  20. #soup.prettify())
  21. # 获取第一个 title 标签
  22. soup.title
  23. # <title>The Dormouse's story</title>
  24. # 获取第一个 title 标签的名称
  25. soup.title.name
  26. # title
  27. # 获取第一个 title 标签的文本内容
  28. soup.title.string
  29. # The Dormouse's story
  30. # 获取第一个 title 标签的父标签的名称
  31. soup.title.parent.name
  32. # head
  33. # 获取第一个 p 标签
  34. soup.p
  35. # <p class="title"><b>The Dormouse's story</b></p>
  36. # 获取第一个 p 标签的 class 属性
  37. soup.p['class']
  38. # ['title']
  39. # 获取第一个 a 标签
  40. soup.a
  41. # <a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>
  42. # 查找所有的 a 标签
  43. soup.find_all('a')
  44. # [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>,
  45. # <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>,
  46. # <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]
  47. # 获取所有的 a 标签的 href 属性
  48. for link in soup.find_all('a'):
  49. print(link.get('href'))
  50. # http://example.com/elsie
  51. # http://example.com/lacie
  52. # http://example.com/tillie
  53. # 查找 id = link3 的 a 标签
  54. soup.find(id="link3")
  55. # <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>
  56. # 获取解析树的文本内容
  57. print(soup.get_text())
  58. # The Dormouse's story
  59. #
  60. # The Dormouse's story
  61. # Once upon a time there were three little sisters; and their names were
  62. # Elsie,
  63. # Lacie and
  64. # Tillie;
  65. # and they lived at the bottom of a well.
  66. # ...

解析器

Beautiful Soup除了支持Python标准库中的HTML解析器外,还支持一些第三方的解析器,其中一个就是 lxml 。

下表列出了主要的解析器,以及它们的优缺点:


































解析器

使用方法

优势

劣势

Python标准库

BeautifulSoup(markup, “html.parser”)

Python的内置标准库

执行速度适中

文档容错能力强

Python 2.7.3 or 3.2.2)前 的版本中文档容错能力差

lxml HTML 解析器

BeautifulSoup(markup, “lxml”)

速度快

文档容错能力强

需要安装C语言库

lxml XML 解析器

BeautifulSoup(markup, [“lxml”, “xml”])

BeautifulSoup(markup, “xml”)

速度快

唯一支持XML的解析器

需要安装C语言库

html5lib

BeautifulSoup(markup, “html5lib”)

最好的容错性

以浏览器的方式解析文档

生成HTML5格式的文档

速度慢

不依赖外部扩展

推荐使用lxml作为解析器,因为效率更高。 在Python2.7.3之前的版本和Python3中3.2.2之前的版本,必须安装lxml或html5lib, 因为那些Python版本的标准库中内置的HTML解析方法不够稳定。

注意:如果一段HTML或XML文档格式不正确的话,那么在不同的解析器中返回的结果可能是不一样的。

解析器之间的区别

Beautiful Soup为不同的解析器提供了相同的接口,但解析器本身是有区别的,同一篇文档被不同的解析器解析后可能会生成不同结构的树型文档,区别最大的是HTML解析器和XML解析器,看下面片段被解析成HTML结构:

  1. html_soup = BeautifulSoup("<a><b/></a>", "lxml")
  2. print(html_soup)
  3. # <html><body><a><b></b></a></body></html>

因为空标签不符合HTML标准,所以解析器把它解析成

同样的文档使用XML解析如下(解析XML需要安装lxml库)。注意,空标签依然被保留,并且文档前添加了XML头,而不是被包含在标签内:

  1. xml_soup = BeautifulSoup("<a><b/></a>", "xml")
  2. print(xml_soup)
  3. # <?xml version="1.0" encoding="utf-8"?>
  4. # <a><b/></a>

HTML解析器之间也有区别,如果被解析的HTML文档是标准格式,那么解析器之间没有任何差别,只是解析速度不同,结果都会返回正确的文档树。

但是如果被解析文档不是标准格式,那么不同的解析器返回结果可能不同。下面例子中,使用lxml解析错误格式的文档,结果

标签被直接忽略掉了:

  1. soup = BeautifulSoup("<a></p>", "lxml")
  2. print(soup)
  3. # <html><body><a></a></body></html>

使用html5lib库解析相同文档会得到不同的结果:

  1. soup = BeautifulSoup("<a></p>", "html5lib")
  2. print(soup)
  3. # <html><head></head><body><a><p></p></a></body></html>

html5lib库没有忽略掉

标签,而是自动补全了标签,还给文档树添加了标签。

使用pyhton内置库解析结果如下:

  1. soup = BeautifulSoup("<a></p>", "html.parser")
  2. print(soup)
  3. # <a></a>

与lxml 库类似的,Python内置库忽略掉了

标签,与html5lib库不同的是标准库没有尝试创建符合标准的文档格式或将文档片段包含在标签内,与lxml不同的是标准库甚至连标签都没有尝试去添加。

因为文档片段“

”是错误格式,所以以上解析方式都能算作”正确”,html5lib库使用的是HTML5的部分标准,所以最接近”正确”,不过所有解析器的结构都能够被认为是”正常”的。

不同的解析器可能影响代码执行结果,如果在分发给别人的代码中使用了 BeautifulSoup ,那么最好注明使用了哪种解析器,以减少不必要的麻烦。

创建文档对象

将一段文档传入BeautifulSoup 的构造方法,就能得到一个文档的对象, 可以传入一段字符串或一个文件句柄。

  1. from bs4 import BeautifulSoup
  2. soup = BeautifulSoup(open("index.html"))
  3. soup = BeautifulSoup("<html>data</html>")

首先,文档被转换成Unicode,并且HTML的实例都被转换成Unicode编码。

  1. soup = BeautifulSoup("Sacré bleu!")
  2. print(soup)
  3. # <html><body><p>Sacré bleu!</p></body></html>

然后,Beautiful Soup选择最合适的解析器来解析这段文档,如果手动指定解析器那么Beautiful Soup会选择指定的解析器来解析文档。

对象的种类

Beautiful Soup将复杂HTML文档转换成一个复杂的树形结构,每个节点都是Python对象,所有对象可以归纳为4种:Tag 、NavigableString、 BeautifulSoup、Comment 。

Tag

Tag 对象与XML或HTML原生文档中的tag相同:

  1. from bs4 import BeautifulSoup
  2. soup = BeautifulSoup('<b class="boldest">Extremely bold</b>',"html.parser")
  3. # 获取第一个 b 标签
  4. tag = soup.b
  5. # 获取对象类型
  6. type(tag)
  7. # <class 'bs4.element.Tag'>
  8. # 获取标签的名称
  9. tag.name
  10. # b
  11. # 修改标签的名称
  12. tag.name = "blockquote"
  13. tag
  14. # <blockquote class="boldest">Extremely bold</blockquote>
  15. # 查看标签的 class 属性
  16. tag['class']
  17. # ['boldest']
  18. # 修改标签的 class 属性
  19. tag['class'] = 'verybold'
  20. # 查看标签的 class 属性内容
  21. tag.get('class')
  22. # verybold
  23. # 为标签新增 id 属性
  24. tag['id'] = 'title'
  25. tag
  26. # <blockquote class="verybold" id="title">Extremely bold</blockquote>
  27. # 查看标签的所有属性
  28. tag.attrs
  29. # {'class': ['verybold'], 'id': 'title'}
  30. # 删除标签的 id 属性
  31. del tag['id']
  32. tag
  33. # <blockquote class="verybold">Extremely bold</blockquote>

可遍历字符串

字符串常被包含在tag内,Beautiful Soup用 NavigableString 类来包装tag中的字符串:

  1. from bs4 import BeautifulSoup
  2. soup = BeautifulSoup('<b class="boldest">Extremely bold</b>', "html.parser")
  3. # 获取第一个 b 标签
  4. tag = soup.b
  5. # 获取标签的文本内容
  6. tag.string
  7. # Extremely bold
  8. # 获取标签的文本内容的类型
  9. type(tag.string)
  10. # <class 'bs4.element.NavigableString'>

BeautifulSoup

BeautifulSoup 对象表示的是一个文档的全部内容,大部分时候,可以把它当作 Tag 对象,它支持 遍历文档树 和 搜索文档树 中描述的大部分的方法。

因为 BeautifulSoup 对象并不是真正的HTML或XML的tag,所以它没有name和attribute属性。但有时查看它的 .name 属性是很方便的,所以 BeautifulSoup 对象包含了一个值为 “[document]” 的特殊属性 .name 。

  1. soup = BeautifulSoup('<b class="boldest">Extremely bold</b>',"html.parser")
  2. soup.name
  3. # [document]

注释及特殊字符串

Tag、NavigableString、BeautifulSoup 几乎覆盖了html和xml中的所有内容,但是还有一些特殊对象,容易让人担心的内容是文档的注释部分:

  1. markup = "<b><!--Hey, buddy. Want to buy a used parser?--></b>"
  2. soup = BeautifulSoup(markup)
  3. comment = soup.b.string
  4. type(comment)
  5. # <class 'bs4.element.Comment'>

Comment 对象是一个特殊类型的 NavigableString 对象:

  1. comment
  2. # Hey, buddy. Want to buy a used parser?

但是当它出现在HTML文档中时, Comment 对象会使用特殊的格式输出:

  1. soup.b.prettify()
  2. # <b>
  3. # <!--Hey, buddy. Want to buy a used parser?-->
  4. # </b>

Beautiful Soup中定义的其它类型都可能会出现在XML的文档中: CData,ProcessingInstruction, Declaration,Doctype。与 Comment 对象类似。这些类都是 NavigableString 的子类,只是添加了一些额外的方法的字符串独享。下面是用CDATA来替代注释的例子:

  1. from bs4 import CData
  2. cdata = CData("A CDATA block")
  3. comment.replace_with(cdata)
  4. print(soup.b.prettify())
  5. # <b>
  6. # <![CDATA[A CDATA block]]>
  7. # </b>

子节点

一个Tag可能包含多个字符串或其它的Tag,这些都是这个Tag的子节点。Beautiful Soup提供了许多操作和遍历子节点的属性。

注意: Beautiful Soup中字符串节点不支持这些属性,因为字符串没有子节点。

继续拿上面的《爱丽丝梦游仙境》的文档来做示例:

  1. from bs4 import BeautifulSoup
  2. # 《爱丽丝梦游仙境》故事片段
  3. html_doc = """
  4. <html>
  5. <head><title>The Dormouse's story</title></head>
  6. <body>
  7. <p class="title"><b>The Dormouse's story</b></p>
  8. <p class="story">Once upon a time there were three little sisters; and their names were
  9. <a href="http://example.com/elsie" class="sister" id="link1">Elsie</a>,
  10. <a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and
  11. <a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>;
  12. and they lived at the bottom of a well.</p>
  13. <p class="story">...</p>
  14. </body>
  15. </html>
  16. """
  17. # 构造解析树
  18. soup = BeautifulSoup(html_doc, "html.parser")
  19. # 通过点取属性的方式获得当前名字的第一个tag
  20. soup.body.p.b
  21. # <b>The Dormouse's story</b>
  22. # 查找所有的 a 标签
  23. soup.find_all('a')
  24. # [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>,
  25. # <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>,
  26. # <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]
  27. # 通过 .contents 属性获取tag 的子节点列表
  28. soup.head.contents
  29. # [<title>The Dormouse's story</title>]
  30. # 通过 .children 生成器对tag的子节点进行遍历
  31. for child in soup.head.children:
  32. print(child)
  33. # <title>The Dormouse's story</title>
  34. # 通过 .descendants 生成器对tag的后代节点进行遍历
  35. for descendant in soup.head.descendants:
  36. print(descendant)
  37. # <title>The Dormouse's story</title>
  38. # The Dormouse's story
  39. # 通过 .string 属性获取唯一 NavigableString 类型子节点
  40. soup.head.title.string
  41. # The Dormouse's story
  42. # 通过 .string 属性获取唯一子节点的NavigableString 类型子节点
  43. soup.head.string
  44. # The Dormouse's story
  45. # 通过 .strings 属性获取 tag 中的多个字符串
  46. for string in soup.strings:
  47. print(repr(string))
  48. # 通过 .stripped_strings 属性获取 tag 中去除多余空白内容的多个字符串
  49. for string in soup.stripped_strings:
  50. print(repr(string))

注意:如果tag包含了多个子节点,tag就无法确定 .string 方法应该调用哪个子节点的内容, .string 的输出结果是 None 。

父节点

每个tag或字符串都有父节点,还是以上面的《爱丽丝梦游仙境》的文档来举例:

  1. from bs4 import BeautifulSoup
  2. # 《爱丽丝梦游仙境》故事片段
  3. html_doc = """
  4. <html>
  5. <head><title>The Dormouse's story</title></head>
  6. <body>
  7. <p class="title"><b>The Dormouse's story</b></p>
  8. <p class="story">Once upon a time there were three little sisters; and their names were
  9. <a href="http://example.com/elsie" class="sister" id="link1">Elsie</a>,
  10. <a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and
  11. <a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>;
  12. and they lived at the bottom of a well.</p>
  13. <p class="story">...</p>
  14. </body>
  15. </html>
  16. """
  17. # 构造解析树
  18. soup = BeautifulSoup(html_doc, "html.parser")
  19. # 通过 .parent 属性来获取 title 标签的父节点
  20. soup.title.parent
  21. # <head><title>The Dormouse's story</title></head>
  22. # 通过 .parent 属性来获取 title 标签的内字符串的父节点
  23. soup.title.string.parent
  24. # <title>The Dormouse's story</title>
  25. # 文档的顶层节点 <html> 的父节点是 BeautifulSoup 对象
  26. type(soup.html.parent)
  27. # <class 'bs4.BeautifulSoup'>
  28. # BeautifulSoup 对象的 .parent 是None
  29. soup.parent
  30. for parent in soup.a.parents:
  31. print(parent.name)
  32. # p
  33. # body
  34. # html
  35. # [document]

兄弟节点

为了示例如何使用BeautifulSoup来查找兄弟节点,需要对上例中的《爱丽丝梦游仙境》文档进行修改,删掉一些换行符、字符串和标签。具体示例代码如下:

  1. from bs4 import BeautifulSoup
  2. # 《爱丽丝梦游仙境》故事片段
  3. html_doc = """
  4. <html>
  5. <body>
  6. <p class="title"><b>Schindler's List</b></p>
  7. <p class="names"><a href="http://example.com/Oskar" id="name1">Oskar Schindler</a><a href="http://example.com/Itzhak" id="name2">Itzhak Stern</a><a href="http://example.com/Helen" id="name3">Helen Hirsch</a></p>
  8. </body>
  9. </html>
  10. """
  11. # 构造解析树
  12. soup = BeautifulSoup(html_doc, "html.parser")
  13. # 获取 ID = name2 的 a 标签
  14. name2 = soup.find("a", {"id":{"name2"}})
  15. # <a href="http://example.com/Itzhak" id="name2">Itzhak Stern</a>
  16. # 获取前一个兄弟节点
  17. name1 = name2.previous_sibling
  18. # <a href="http://example.com/Oskar" id="name1">Oskar Schindler</a>
  19. # 获取前一个兄弟节点
  20. name3 = name2.next_sibling
  21. # <a href="http://example.com/Helen" id="name3">Helen Hirsch</a>
  22. name1.previous_sibling
  23. # None
  24. name3.next_sibling
  25. # None
  26. # 通过 .next_siblings 属性对当前节点的兄弟节点进行遍历
  27. for sibling in soup.find("a", {"id":{"name1"}}).next_siblings:
  28. print(repr(sibling))
  29. # <a href="http://example.com/Itzhak" id="name2">Itzhak Stern</a>
  30. # <a href="http://example.com/Helen" id="name3">Helen Hirsch</a>
  31. # 通过 .previous_siblings 属性对当前节点的兄弟节点进行遍历
  32. for sibling in soup.find("a", {"id":{"name3"}}).previous_siblings:
  33. print(repr(sibling))
  34. # <a href="http://example.com/Itzhak" id="name2">Itzhak Stern</a>
  35. # <a href="http://example.com/Oskar" id="name1">Oskar Schindler</a>

注意:标签之间包含的字符串、字符或者换行符等内容均会被看作节点。

回退和前进

继续用上一章节《兄弟节点》中的HTML文档进行回退和前进示例:

  1. from bs4 import BeautifulSoup
  2. # 《爱丽丝梦游仙境》故事片段
  3. html_doc = """
  4. <html>
  5. <body>
  6. <p class="title"><b>Schindler's List</b></p>
  7. <p class="names"><a href="http://example.com/Oskar" id="name1">Oskar Schindler</a><a href="http://example.com/Itzhak" id="name2">Itzhak Stern</a><a href="http://example.com/Helen" id="name3">Helen Hirsch</a></p>
  8. </body>
  9. </html>
  10. """
  11. # 构造解析树
  12. soup = BeautifulSoup(html_doc, "html.parser")
  13. # 获取 ID = name2 的 a 标签
  14. name2 = soup.find("a", {"id":{"name2"}})
  15. # <a href="http://example.com/Itzhak" id="name2">Itzhak Stern</a>
  16. # 获取前一个节点
  17. name2.previous_element
  18. # Oskar Schindler
  19. # 获取前一个节点的前一个节点
  20. name2.previous_element.previous_element
  21. # <a href="http://example.com/Oskar" id="name1">Oskar Schindler</a>
  22. # 获取后一个节点
  23. name2.next_element
  24. # Itzhak Stern
  25. # 获取后一个节点的后一个节点
  26. name2.next_element.next_element
  27. # <a href="http://example.com/Helen" id="name3">Helen Hirsch</a>
  28. # 通过 .next_elements 属性对当前节点的后面节点进行遍历
  29. for element in soup.find("a", {"id":{"name1"}}).next_elements:
  30. print(repr(element))
  31. # 'Oskar Schindler'
  32. # <a href="http://example.com/Itzhak" id="name2">Itzhak Stern</a>
  33. # 'Itzhak Stern'
  34. # <a href="http://example.com/Helen" id="name3">Helen Hirsch</a>
  35. # 'Helen Hirsch'
  36. # '\n'
  37. # '\n'
  38. # '\n'
  39. # 通过 .previous_elements 属性对当前节点的前面节点进行遍历
  40. for element in soup.find("a", {"id":{"name1"}}).previous_elements:
  41. print(repr(element))
  42. # <p class="names"><a href="http://example.com/Oskar" id="name1">Oskar Schindler</a><a href="http://example.com/Itzhak" id="name2">Itzhak Stern</a><a href="http://example.com/Helen" id="name3">Helen Hirsch</a></p>
  43. # '\n'
  44. # "Schindler's List"
  45. # <b>Schindler's List</b>
  46. # <p class="title"><b>Schindler's List</b></p>
  47. # '\n'
  48. # <body>
  49. # <p class="title"><b>Schindler's List</b></p>
  50. # <p class="names"><a href="http://example.com/Oskar" id="name1">Oskar Schindler</a><a href="http://example.com/Itzhak" id="name2">Itzhak Stern</a><a href="http://example.com/Helen" id="name3">Helen Hirsch</a></p>
  51. # </body>
  52. # '\n'
  53. # <html>
  54. # <body>
  55. # <p class="title"><b>Schindler's List</b></p>
  56. # <p class="names"><a href="http://example.com/Oskar" id="name1">Oskar Schindler</a><a href="http://example.com/Itzhak" id="name2">Itzhak Stern</a><a href="http://example.com/Helen" id="name3">Helen Hirsch</a></p>
  57. # </body>
  58. # </html>
  59. # '\n'

搜索文档树

  1. find_all( name , attrs , recursive , text , **kwargs )
  2. find( name , attrs , recursive , text , **kwargs )
  3. find_parents( name , attrs , recursive , text , **kwargs )
  4. find_parent( name , attrs , recursive , text , **kwargs )
  5. find_next_siblings( name , attrs , recursive , text , **kwargs )
  6. find_next_sibling( name , attrs , recursive , text , **kwargs )
  7. find_previous_siblings( name , attrs , recursive , text , **kwargs )
  8. find_previous_sibling( name , attrs , recursive , text , **kwargs )
  9. find_all_next( name , attrs , recursive , text , **kwargs )
  10. find_next( name , attrs , recursive , text , **kwargs )
  11. find_all_previous( name , attrs , recursive , text , **kwargs )
  12. find_previous( name , attrs , recursive , text , **kwargs )

Beautiful Soup定义了很多搜索方法,这里着重对 find_all() 的用法进行举例。

  1. from bs4 import BeautifulSoup
  2. from bs4 import NavigableString
  3. import re
  4. # 《爱丽丝梦游仙境》故事片段
  5. html_doc = """
  6. <html>
  7. <head><title>The Dormouse's story</title></head>
  8. <body>
  9. <p class="title"><b>The Dormouse's story</b></p>
  10. <p class="story">Once upon a time there were three little sisters; and their names were
  11. <a href="http://example.com/elsie" class="sister" id="link1">Elsie</a>,
  12. <a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and
  13. <a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>;
  14. and they lived at the bottom of a well.</p>
  15. <p class="story">...</p>
  16. </body>
  17. </html>
  18. """
  19. # 构造解析树
  20. soup = BeautifulSoup(html_doc, "html.parser")
  21. # 传入字符串,根据标签名称查找(b)标签
  22. soup.find_all('b')
  23. # [<b>The Dormouse's story</b>]
  24. # 传入两个字符串参数,返回 class = title 的 p 标签
  25. soup.find_all("p", "title")
  26. # [<p class="title"><b>The Dormouse's story</b></p>]
  27. # 返回 id = link2 的标签
  28. soup.find_all(id='link2')
  29. # [<a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>]
  30. # href 匹配 elsie 并且 id = link1 的标签
  31. soup.find_all(href=re.compile("elsie"), id='link1')
  32. # [<a class="sister" href="http://example.com/elsie" id="link1">three</a>]
  33. # 返回 id = link1 的标签
  34. print(soup.find_all(attrs={"id": "link1"}))
  35. # [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>]
  36. # 返回 class = sister 的 a 标签
  37. soup.find_all("a", class_="sister")
  38. # [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>,
  39. # <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>,
  40. # <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]
  41. def has_six_characters(css_class):
  42. return css_class is not None and len(css_class) == 6
  43. # 返回 class 属性为6个字符的 标签
  44. soup.find_all(class_=has_six_characters)
  45. # [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>,
  46. # <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>,
  47. # <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]
  48. # 返回字符串
  49. soup.find_all(text=["Tillie", "Elsie", "Lacie"])
  50. # 返回前两个 a 标签
  51. soup.find_all("a", limit=2)
  52. # 返回 title 标签,不级联查询
  53. soup.html.find_all("title", recursive=False)
  54. # 使用 CSS 选择器进行过滤
  55. soup.select("head > title")
  56. # 传入正则表达式,根据标签名称查找匹配(以字母 b 开头)标签
  57. for tag in soup.find_all(re.compile("^b")):
  58. print(tag.name)
  59. # body
  60. # b
  61. # 传入正则表达式,根据标签名称查找匹配(包含字母 t)标签
  62. for tag in soup.find_all(re.compile("t")):
  63. print(tag.name)
  64. # html
  65. # title
  66. # 传入列表,根据标签名称查找(a和b)标签
  67. soup.find_all(["a", "b"])
  68. # [<b>The Dormouse's story</b>,
  69. # <a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>,
  70. # <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>,
  71. # <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]
  72. # 传入True,返回除字符串节点外的所有标签
  73. for tag in soup.find_all(True):
  74. print(tag.name)
  75. def has_class_but_no_id(tag):
  76. return tag.has_attr('class') and not tag.has_attr('id')
  77. # 传入自定义方法,返回仅包含 class 属性但不包含 id 属性的所有标签
  78. soup.find_all(has_class_but_no_id)

发表评论

表情:
评论列表 (有 0 条评论,366人围观)

还没有评论,来说两句吧...

相关阅读

    相关 使用DOM4j解析XML

             Dom4j是一个简单、灵活的开放源代码的库。Dom4j是由早期开发JDOM的人分离出来而后独立开发的。与JDOM不同的是,dom4j使用接口和抽象基类,虽然D