主页
avatar

Kared

【全面指南】Python BeautifulSoup 库

BeautifulSoup 是一个用于从HTML或XML文件中提取数据的Python库。它创建了一个解析树,使用户能够方便地访问和修改页面内容。BeautifulSoup 提供了一些简单的、Python式的函数来导航、搜索和修改解析树。可以参考 BeautifulSoup 官方文档 进行学习。

1. BeautifulSoup 基础入门

让我们以一个简单的 HTML 结构为起点:

<html>
    <body>
        <p class="title">标签树</p>
    </body>
</html>

Beautiful Soup 是一个功能强大的库,专门用于解析、遍历和维护 HTML 或 XML 的“标签树”。

考虑以下简单的 <p> 标签:

<p class="title">标签树</p>
  • p:元素名(Name),它们通常成对出现。
  • class="title":属性(Attributes),一个标签可以包含零个或多个属性。
  • <p>…</p>:标签(Tag),是构成 HTML 文档的基础。

基本元素详解

  • Tag(标签): 是构成 HTML 或 XML 文档的基本单位,以 < 开始,以 > 结束。
  • Name(标签名): 标签的名称,比如 <p> 标签的名字是 ‘p’。
  • Attributes(属性): 标签的属性,通常以键值对的形式存在,可以通过 tag.attrs 获取。
  • NavigableString(可导航字符串): 标签内非属性的字符串内容,可以通过 tag.string 获取。
  • Comment(注释): 特殊类型的 NavigableString,用于表示标签内的注释内容。

示例代码:

import requests
from bs4 import BeautifulSoup

html = requests.get("https://python123.io/ws/demo.html").text
soup = BeautifulSoup(html, "html.parser")

print("标签示例:")
print(soup.title)
print(soup.a)

print("标签名示例:")
print("a 标签的名称:", soup.a.name)
print("a 标签父元素的名称:", soup.a.parent.name)

print("属性示例:")
print(soup.a.attrs)
print("类属性:", soup.a.attrs["class"])
print("id 属性:", soup.a.attrs["id"])

print("非属性字符串示例:")
print(soup.a.string)
print(soup.p.string)

print("注释部分示例:")
print(type(soup.a.string))
print(type(soup.p.string))

这段代码演示了如何通过 BeautifulSoup 提取 HTML 标签的不同组成部分,并打印它们。

2. 掌握 BeautifulSoup 的 HTML 遍历技巧

Beautiful Soup 库,也被称为 beautifulsoup4 或 bs4,通常以以下方式导入:

from bs4 import BeautifulSoup

HTML 内容遍历

Beautiful Soup 提供了多种遍历 HTML 内容的方法:

向下遍历

  • .contents: 获取子节点的列表,包含了标签中的所有直接子节点。
  • .children: 子节点的迭代器,用于遍历子节点,适合于循环访问每一个子节点。
  • .descendants: 子孙节点的迭代器,可以遍历标签下的所有子孙节点,非常适合需要深层次遍历的场景。

向上遍历

  • .parent: 获取单个父节点,是访问节点的直接父节点的简便方法。
  • .parents: 父节点的迭代器,可以遍历到从当前节点到根节点的所有父节点,适用于需要回溯的场景。

横向遍历

  • .next_sibling: 获取下一个兄弟节点,它可以让你访问同一层级的下一个节点。
  • .previous_sibling: 获取上一个兄弟节点,与 .next_sibling 相反,它返回前一个节点。
  • .next_siblings: 后续所有兄弟节点的迭代器,可以用来遍历一个节点之后的所有兄弟节点。
  • .previous_siblings: 前面所有兄弟节点的迭代器,适用于需要向前遍历兄弟节点的情况。

.prettify() 方法可以使 HTML 输出更加易读:

html = requests.get("https://python123.io/ws/demo.html").text
soup = BeautifulSoup(html, "html.parser")
print(soup.prettify())

这将以格式化的方式输出整个 HTML 文档。

3. 选择合适的解析器

Beautiful Soup 支持多种解析器,这些解析器有各自的优势:

  • html.parser: BeautifulSoup 的内置 HTML 解析器,不需要额外安装,适合基本的文档解析需求。
  • lxml: 一个非常快速的 HTML 和 XML 解析器,需要通过 pip 安装。
  • html5lib: 以浏览器的方式解析 HTML 文档的解析器,虽然速度较慢,但解析方式与浏览器极为相似。

安装不同的解析器很简单,只需使用 pip:

pip install lxml
pip install html5lib

4. 信息标记和提取

信息的标记

  • 标记化的信息:标记化后的信息可以构建成结构化的数据模型,增强了数据的可操作性和可理解性。
  • 标记结构的重要性:标记结构本身就像信息的骨架,对于信息的传递、存储及展示至关重要。
  • 程序处理的便利性:标记化的信息更容易被计算机程序所解析和利用。

常见的信息标记形式

  • XML: 是最早的通用信息标记语言,具有很好的扩展性,但相对较为繁琐。
  • JSON: 一种轻量级的数据交换格式,易于人阅读和编写,同时也易于机器解析和生成。
  • YAML: 一种人性化的数据序列化标准,适合所有的编程语言。

信息提取策略

在标记化的信息中提取关键内容,可以采用以下策略:

完整解析

  • 使用专门的标记解析器,例如 BeautifulSoup,可以实现对信息的精确解析。
  • 优点是解析结果准确,缺点是过程可能比较繁琐,速度相对较慢。

直接搜索

  • 利用文本搜索方法,可以快速地查找到关键信息,但可能会牺牲一些准确性。

结合解析与搜索

  • 结合使用解析器和搜索函数,可以在保证一定准确性的同时提高效率。

5. 利用 BeautifulSoup 进行 HTML 内容查找

BeautifulSoup 提供了丰富的方法来查找 HTML 文档中的特定内容:

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

参数详解:

  • name: 可以是一个标签名称或者一个标签名称的列表,用于查找所有匹配的标签。
  • attrs: 是一个字典,用于搜索具有特定属性的标签。
  • recursive: 布尔值。如果是 True(默认值),Beautiful Soup 会检查标签的所有子孙节点。如果是 False,只会检查标签的直接子节点。
  • string: 用于搜索文档中字符串内容。它可以是一个字符串、正则表达式或者字符串列表。

示例代码:

soup = BeautifulSoup(html, "html.parser")
all_a_tags = soup.find_all("a")
class_py1 = soup.find_all("a", {"class": "py1"})
print(all_a_tags)
print(class_py1)

这段代码会打印出 HTML 文档中所有的 <a> 标签,以及所有类属性为 "py1"<a> 标签。

除了 find_all 方法,BeautifulSoup 还提供了其他查找函数,包括:

  • .find(): 用于查找单个结果,返回第一个匹配的标签。

.find_parents().find_parent(): 用于向上搜索文档树,查找符合条件的父节点或所有父节点。

  • .find_next_siblings().find_next_sibling(): 用于搜索当前节点之后的兄弟节点。
  • .find_previous_siblings().find_previous_sibling(): 用于搜索当前节点之前的兄弟节点。
  • .find_all_next().find_next(): 用于搜索当前节点之后的所有节点和下一个节点。
  • .find_all_previous().find_previous(): 用于搜索当前节点之前的所有节点和上一个节点。

每个函数都有各自的搜索范围和用途,可以根据实际需求选择合适的方法。

CSS 选择器

BeautifulSoup 还支持 CSS 选择器,通过 .select() 方法可以使用 CSS 选择器来查找节点:

soup = BeautifulSoup(html, "html.parser")
tags = soup.select("div.myClass > a")

在这个例子中,.select() 方法搜索所有在 div 元素的 myClass 类里的直接子节点 a 标签。CSS 选择器是一个非常强大的功能,可以让你以与 CSS 相同的方式选择 HTML 元素。

正则表达式

当你需要对查找条件进行复杂的匹配时,可以使用正则表达式:

import re
soup = BeautifulSoup(html, "html.parser")
tags = soup.find_all(re.compile("^b"))

这段代码查找所有以字母 ‘b’ 开头的标签,例如 <body><b> 等。

Lambda 表达式

对于更加复杂的搜索,可以使用 lambda 表达式作为参数:

soup = BeautifulSoup(html, "html.parser")
tags = soup.find_all(lambda tag: tag.get_text() == "Python")

这里,find_all 方法使用了一个 lambda 函数来筛选出所有标签文本内容为 “Python” 的标签。

6. 结果的输出与导航

一旦你找到了需要的标签,你可能会想要获取标签的内容或者进一步导航到其他相关的标签。BeautifulSoup 提供了简单的方法来实现这些功能。

获取内容

  • .get_text(): 提取标签内的文本内容。
  • .attrs: 获取标签的所有属性。
  • .get('attribute'): 获取标签的特定属性值。

导航

  • .parent: 访问标签的父节点。
  • .children: 访问标签的直接子节点。
  • .descendants: 访问标签的所有子孙节点。
  • .next_sibling.previous_sibling: 访问标签的下一个和上一个兄弟节点。

输出

最后,你可能需要将处理的结果输出到文件或控制台:

with open("output.html", "w", encoding="utf-8") as file:
    file.write(soup.prettify())

这段代码将格式化后的 HTML 内容写入到名为 “output.html” 的文件中。

通过以上方法,你可以有效地利用 BeautifulSoup 库进行 HTML 和 XML 的解析和数据提取。

虽然 BeautifulSoup 非常强大,但它并不适用于所有的网页解析场景,特别是那些依赖于 JavaScript 动态生成内容的网页。在处理这类网页时,你可能需要使用像 Selenium 这样的工具来处理 JavaScript 渲染的内容。

Python BeautifulSoup Web Scraping