使用正则表达式进行网页抓取虽是提取网站数据的强大工具,但也有其局限性。使用正则表达式进行网页抓取的主要问题之一是,当 HTML 结构发生变化时,它可能会失败。
例如,请看以下代码示例,我们试图使用正则表达式从 h2 标签中提取文本:
<html>
<head>
<title>Example Title</title>
</head>
<body>
<h1>Page Title</h1>
<p>This is a paragraph under the title</p>
<h2>First Subtitle</h2>
<p>First paragraph under the subtitle</p>
<h2>Second Subtitle</p>
</body>
</html>
比较第一个 <h2> 标签与第二个。您可能会注意到第二个 <h2> 未正确闭合,且代码中使用了 </p> 而不是 </h2>。让我们将代码片段更新为以下内容:
import re
html = "<html><head><title>Example Title</title></head><body><h1>Page Title</h1><p>This is a paragraph under the title</p><h2>First Subtitle</h2><p>First paragraph under the subtitle</p><h2>Second Subtitle</p></body></html>"
headingTags = re.findall("<h2>(.*?)</h2>", html)
print(*headingTags, sep = "\n")
运行代码并查看输出结果:
First Subtitle
第二个标题标签中的文本缺失了。这是因为正则表达式规则无法匹配未闭合的标题标签。
解决此问题的一个方法是使用 BeautifulSoup 这样的库,它允许你遍历和搜索 HTML 树结构,而不是依赖正则表达式。使用 BeautifulSoup,你可以像这样提取网页的标题:
from bs4 import BeautifulSoup
html = "<html><head><title>Example Title</title></head><body><h1>Page Title</h1><p>This is a paragraph under the title</p><h2>First Subtitle</h2><p>First paragraph under the subtitle</p><h2>Second Subtitle</p></body></html>"
soup = BeautifulSoup(html, 'html.parser')
for headingTag in soup.findAll('h2'):
print(headingTag.text)
BeautifulSoup 能够处理格式不规范的标签,输出结果如下所示:
First Subtitle
Second Subtitle
这种方法对 HTML 结构的变化更具鲁棒性,因为它不依赖于 HTML 代码中的特定模式。如果您想进一步了解 BeautifulSoup,这篇文章是绝佳的阅读材料。
另一种解决方案是使用 WebScrapingAPI 等网络爬虫 API,它抽象化了网络爬取的复杂性,让你无需担心底层 HTML 结构,即可轻松提取所需数据。
借助 WebScrapingAPI,您只需调用一个简单的 API 接口即可从任何网站提取数据,它会自动处理 HTML 结构的变化。