作为一名 Python 开发人员,您可能熟悉 BeautifulSoup(又名 BS4)——这是一个古老的 HTML/XML 解析库,十多年来一直是 Python 网络抓取的主要内容。
但你可能不知道,Beautiful Soup 远非当今 Python 中解析 HTML 的唯一选择。事实上,有数量惊人的 BeautifulSoup 替代品,在某些情况下甚至在功能和性能上超越了 BS4。
在本综合指南中,我们将探索一些最流行、最强大的 BeautifulSoup 替代方案,用于使用 Python 进行 HTML 抓取和解析。
为什么考虑 BeautifulSoup 替代品?
在深入研究这些选项之前,您可能会想 – 为什么首先要考虑替代方案?
以下是您可能希望在 Python 网络抓取项目中超越 BeautifulSoup 的一些原因:
更好的性能 – 一些较新的解析器在基准测试中显着优于 BS4。抓取大型网站时,速度至关重要。
更多功能 – lxml 等库提供了 XPath 支持等附加功能。
更好的 HTML5 解析 – BeautifulSoup 有时会与格式错误的现代 HTML 发生冲突。
更简单的 API – 像 parsel 这样的库提供了更直观的 Pythonic API。
多线程 – 一些替代解析器允许多线程解析以利用多个 CPU 核心。
符合标准 – 您可能需要一个严格遵循 HTML 规范的解析器。
安装更简单 – BS4 有一些 C 依赖项,可能会导致安装问题,尤其是在 AWS Lambda 等受限系统上。使用纯 Python 代码的替代方案可以更轻松地部署。
因此,虽然 BS4 仍然是一个不错的选择,但其他优秀的选择也值得您考虑。让我们看一下在 Python 中进行 HTML 解析和网页抓取的一些最佳 BeautifulSoup 替代品!
lxml – 快如闪电
最流行和最强大的 BeautifulSoup 替代品之一是 xml文件。 lxml 库提供了一个极其快速、功能丰富的 API,用于使用 Python 解析 HTML 和 XML。
在基准测试中,lxml 始终明显优于 BeautifulSoup。这并不罕见 速度提高 10-100 倍 当使用 lxml 代替 BeautifulSoup 进行 HTML 解析时。
这使得 lxml 成为任何抓取大型网站或解析大型 HTML 文档的重要工具。速度优势使您能够更有效地解析标记并降低大量线程抓取的成本。
lxml 的一些主要优点:
- 惊人的 XML 和 HTML 解析速度
- 支持非常大的文档
- XPath 1.0 支持复杂的查询
- CSS 选择器支持类似于 BeautifulSoup
- 更简单的线程处理 – lxml 发布了 GIL,因此允许多线程解析
- HTML5解析支持
让我们通过一个简单的示例来了解 lxml 的实际应用:
from lxml import html
import requests
page = requests.get(‘https://en.wikipedia.org/wiki/Web_scraping‘)
tree = html.fromstring(page.content)
# Get headlines
headings = tree.xpath(‘//h1/text()|//h2/text()|//h3/text()|//h4/text()|//h5/text()|//h6/text()‘)
print(headings)
这个简单的例子展示了 lxml 的速度——它可以在几毫秒内解析和查询完整的维基百科页面!
lxml 需要考虑的一些缺点:
- 比 BeautifulSoup 更复杂的学习曲线。 XPath 查询的学习曲线比 CSS 选择器更陡峭。
- 没有像 BS4 那样的内置编码检测。
- 没有像 BS4 这样的元素的 Pythonic 对象表示。操作是通过 DOM 导航 API 完成的。
尽管如此,对于大多数生产网络抓取来说,lxml 仍然是工具包的重要组成部分。速度的提升使您能够更有效地抓取更多数据。
parsel – lxml,简化
如果您喜欢 lxml 带来的功能,但发现 API 太复杂,请查看 包.
Parsel 通过包装 lxml 并提供基于选择器的接口来从 HTML/XML 中抓取数据,从而提供了更易于使用、更具 Python 风格的 API。
Parsel 的主要优点是 简单性和可读性。 Parsel 从一开始就考虑到了 Web 抓取,而 lxml 支持更广泛的 XML 解析功能。
与 lxml 相比,parsel 提供:
- 简化的 CSS 选择器表达式
- 自动编码处理
- 更简单的属性和文本提取 API
- 整体上更直观的方法
例如,以下是如何使用解析选择器提取文本和属性:
from parsel import Selector
html = ‘‘‘<div>
<p class="summary">Some text <a href="/zh-CN/more">More</a></p>
</div>‘‘‘
sel = Selector(text=html)
print(sel.css(‘p::text‘).get()) # Some text More
print(sel.css(‘a::attr(href)‘).get()) # /more
对于来自 BeautifulSoup 或 jQuery 的任何人来说,Selector API 都会非常熟悉。但您可以在幕后获得 lxml 的所有性能优势!
总的来说,当您想要一个简单直观的抓取界面但又不想牺牲 lxml 的速度或兼容性优势时,parsel 是一个很好的选择。
html5lib – 符合标准的解析
最酷的 BeautifulSoup 替代品之一是 html5库.
html5lib 是独一无二的,因为它以与现代 Web 浏览器完全相同的方式解析 HTML。它严格遵循 HTML 规范,并输出严格遵循官方 W3C DOM 规范的文档对象模型。
html5lib 的优点包括:
- 根据HTML5浏览器规则忠实、合规的HTML解析
- 优雅地处理现实世界中格式错误的标记
- 安装简单,因为它完全用 Python 实现
- 在大多数情况下可以作为 BS4 的直接替代品
- 高度可定制和可扩展
让我们看一下 html5lib 的基本用法:
import html5lib
html = ‘<div><span>Example</span></div>‘
parser = html5lib.HTMLParser()
dom = parser.parse(html)
print(dom.getElementsByTagName(‘span‘)[0].toxml())
# <span>Example</span>
我们可以看到 html5lib 从文档中生成了一个标准的 DOM 对象。
一个缺点是 html5lib 比 lxml 等慢。但是,当您需要一个能够以兼容浏览器的方式处理格式错误的标记的解析器时,这是一个不错的选择。
替代 Python HTML 解析器
虽然 lxml、parsel 和 html5lib 是最强大的 BeautifulSoup 替代品,但还有一些其他选项:
- 查询 – jQuery 风格的 DOM 操作。
- 美汤4 – OG BeautifulSoup。速度较慢但非常平易近人的 API。
- HTML解析器 – Python 的内置 HTML 解析器。
- html分钟 – 用于缩小 HTML。
- 标记安全 – 实现 HTML/XML 解析器,将标记公开为 Python 对象。
这些库满足不同的解析需求。例如,PyQuery 提供 jQuery 式的 DOM 操作。 BeautifulSoup4 由于其简单的 API 仍然很受欢迎。
还有用于快速 HTML 解析器的 Python 绑定,例如 鹅 和 杰快 利用其他底层高速解析引擎。
虽然不能直接替代,但对于基本的解析任务,Python 的内置 HTMLParser 也可以工作。
重点是 – 不要将自己局限于 BeautifulSoup。根据许多可用的解析工具评估您的需求。
解析器如何在基准测试中进行比较
为了演示性能差异,让我们使用 BeautifulSoup、lxml、html5lib 和 Python 的 HTMLParser 对一些常见操作进行基准测试。
我创建了一个简单的 基准测试脚本 不同的解析器执行 3 个任务:
- 解析 ~3KB 维基百科 HTML 页面
- 查找所有链接
- 寻找特定元素
这是我笔记本电脑上的结果:
分析器 | 解析时间 | 查找所有链接 | 查找元素 |
---|---|---|---|
xml文件 | 3.5ms | 9ms | 0.1ms |
html5库 | 33ms | 64ms | 7ms |
美丽汤 | 12ms | 18ms | 1ms |
HTML解析器 | 4ms | 32ms | 0.5ms |
正如预期的那样,lxml 非常快 – 在某些操作上比 html10lib 快 5 倍。令人惊讶的是,HTMLParser 在基本解析方面拥有自己的优势,但在查询元素时开始滞后。
这些针对小文档的基准强调了差异。在较大的 HTML 文档上,差距会变得更大,而 lxml 的速度确实很出色。
真实的例子
现在让我们看一些使用这些替代解析器执行网络抓取任务的实际示例:
使用 lxml 抓取产品列表
在这里,我们将从电子商务网站上抓取一些产品列表。 Lxml 可以快速提取我们需要的任何数据:
from lxml import html
import requests
page = requests.get(‘https://myshop.com/products‘)
doc = html.fromstring(page.content)
# Extract product listings
products = doc.xpath(‘//div[@class="product"]‘)
for product in products:
name = product.xpath(‘.//h2[@class="name"]/text()‘)[0]
price = product.xpath(‘.//span[@class="price"]/text()‘)[0]
print(name, price)
使用 lxml,我们甚至可以快速解析大型 HTML 文档,并使用简洁的 XPath 查询来提取我们需要的任何数据。
使用 pandas 和 html5lib 抓取表格
假设我们需要将 HTML 表抓取到 pandas DataFrame 中。 Html5lib 可靠地解析表格:
import html5lib
import pandas as pd
html = ‘‘‘<table>
<tr>
<th>Name</th>
<th>Age</th>
</tr>
<tr>
<td>John</td>
<td>30</td>
</tr>
<tr>
<td>Jane</td>
<td>32</td>
</tr>
</table>‘‘‘
parser = html5lib.HTMLParser()
dom = parser.parse(html)
rows = []
for tr in dom.getElementsByTagName(‘tr‘):
rows.append([td.text for td in tr.getElementsByTagName(‘td‘)])
df = pd.DataFrame(rows[1:], columns=rows[0])
print(df)
# Name Age
# 0 John 30
# 1 Jane 32
Html5lib 对标准的遵守确保即使在有问题的标记上,表格抓取也能始终如一地工作。
使用 parsel 抓取文本
对于文本较多的页面,parsel 使提取变得容易:
from parsel import Selector
html = ‘‘‘<div>
<p>Paragraph 1</p>
<p>Paragraph 2</p>
</div>‘‘‘
sel = Selector(text=html)
content = sel.xpath(‘//div//text()‘).getall()
print(content)
# [‘Paragraph 1‘, ‘Paragraph 2‘]
Parsel 为我们提供了 BeautifulSoup 的简单性和 lxml 的速度!
选择 HTML 解析库的标准
在评估所有这些 BeautifulSoup 替代方案时,哪些标准对您的项目最重要?
迅速的 – 如果性能至关重要,lxml 很难被击败。
正确性 – 为了对有问题的页面进行可靠的解析,html5lib 表现出色。
功能集 – Lxml 提供更完整的 DOM 导航和 XPath 支持。
熟悉的API – BeautifulSoup 的 CSS 选择器是最容易学习的。
处理格式错误的标记 – Lxml 和 html5lib 能够更稳健地处理现实世界的 HTML。
符合标准 – Html5lib 最严格地遵守 HTML5 浏览器行为。
使用方便 – Parsel 和 PyQuery 提供最简单的抓取 API。
不存在适合所有场景的最佳解析器。分析您的具体要求和用例以确定最佳方案。
通常使用库的组合是最好的 - 例如用于解析的 html5lib 和用于查询的 lxml。在示例页面上测试不同的选项,以了解哪些选项可以很好、可靠地满足您的特定网页抓取需求。
无需解析器即可进行网页抓取
我们在这里重点关注 HTML 解析库。但值得注意的是,还有完全解析方法的替代方案。
可以使用以下方法在没有 HTML 解析器的情况下抓取数据:
- 常用表达 – 正则表达式可用于模式匹配原始 HTML 并提取数据。很脆弱,但有时对于简单的情况是可行的。
- 字符串操作 – 使用Python字符串方法来查找、分割和切片HTML字符串。
- HTTP请求 – 直接向 API 发出请求并抓取 API 响应。
- 浏览器自动化 – 利用 Selenium 等工具来抓取渲染的 JavaScript 内容。
- 转换为 JSON/XML 等格式 – 抓取结构化数据源而不是 HTML。
这些方法可能很有用,但通常无法扩展或可靠地工作,特别是对于复杂的站点。一般来说,为了稳健性,建议使用 HTML 解析库。
但如果你的页面非常简单或者你需要 JS 渲染,那么无解析器的方法可能就足够了。
关键精华
虽然 Beautiful Soup 解决了许多常见的 HTML 解析需求,但 lxml、parsel 和 html5lib 等替代方案值得您考虑:
xml文件 – 速度和性能的黄金标准。非常适合生产规模的网络抓取。
包 – 简单的API,方便抓取。基于 lxml 速度构建。
html5库 – 符合浏览器要求的解析,以确保准确性和标准遵守。
基准 – 在某些操作上,Lxml 比 html100lib 快 5 倍。
标准 – 速度与可读性与正确性。评估您的用例的权衡。
无解析器 – 对于简单的情况,正则表达式/字符串操作可能有效。
不要将自己局限于 BeautifulSoup – Python 生态系统提供了令人惊叹的 HTML 解析功能多样性。为每项工作利用正确的工具!