创建数据解析器
无论使用何种解析器,优秀的解析器都能根据预定义规则从 HTML 文档中提取相关信息。解析过程主要包括两个步骤:词法分析和语法分析。
词法分析是指对文档中的单个单词和符号进行分析,并将它们分解为更小、更易于处理的片段。
这涉及词法切分,即把文档分解为单个词法单元(如关键词、符号和数字)的过程。
让我们来看一下这个简单的 HTML 文档:
<html>
<head>
<title>Scraping</title>
</head>
<body>
<h1>Welcome to my scraping page</h1>
<p>This is a paragraph.</p>
<ul>
<li>First Scraping Item</li>
<li>Second Scraping Item</li>
</ul>
</body>
</html>
词法分析过程会将该文档切分为诸如:
- `<html>`
- `<head>`
- `<title>`
- `Scraping`
- `</title>`
- `<body>`
- `<h1>`
- `欢迎访问我的数据抓取页面`
- `</h1>`
- [...]
- `</body>`
- `</html>`
通过这种方式,HTML文档中的每个元素都被拆分为更小、更易于管理的标记,以便进行进一步的分析和处理。
语法分析是分析文档结构并确定各个标记之间如何相互关联的过程。这涉及识别数据中的模式和结构,并利用这些信息构建一种称为“语法树”的树状结构。
例如,<html> 标签是根元素,它包含 <head> 和 <body> 元素。在 <head> 元素内部,有一个 <title> 元素;而在 <body> 元素内部,则包含 <h1>、<p> 和 <a> 元素。
通过识别这些元素及其关系,您可以构建一个解析树,其中 <html> 元素作为根节点,<head> 和 <body> 作为其子节点,以此类推。
您可以利用该解析树从 HTML 文档中提取特定数据,例如 <title> 元素内的文本,或 <a> 元素的 href 属性。
最佳 HTML 解析库
在本节中,我们将探讨适用于不同编程语言的一些最流行的 HTML 解析库。这些库使从 HTML 文档中提取结构化数据变得简单,并可作为您网络爬虫项目的绝佳起点。
从 Python 的 Scrapy 和 BeautifulSoup,到 NodeJS 的 Cheerio 和 Java 的 JSoup,我们将逐一介绍这些库,并提供使用示例。
无论您是初学者还是经验丰富的开发者,本节内容都将帮助您深入了解处理 HTML 数据时可用的各种选项。
让我们开始吧!
Cheerio
Scrapy 和 BeautifulSoup
Scrapy 和 BeautifulSoup 是用于 Python 网页抓取的库。
Scrapy 是一个强大的网络爬虫框架,允许您通过选择器或 XPath 表达式从网站中提取结构化数据。
以下是一个基本的 Scrapy 示例:
import scrapy
class QuotesSpider(scrapy.Spider):
name = "quotes"
def start_requests(self):
urls = [
'https://quotes.toscrape.com/page/1/',
'https://quotes.toscrape.com/page/2/',
]
for url in urls:
yield scrapy.Request(url=url, callback=self.parse)
def parse(self, response):
page = response.url.split("/")[-2]
filename = f'quotes-{page}.html'
with open(filename, 'wb') as f:
f.write(response.body)
self.log(f'Saved file {filename}')
您可以通过以下命令运行该代码:
scrapy crawl quotes
BeautifulSoup 是一个库,它允许您像网页浏览器那样解析 HTML 和 XML 文档并从中提取数据。
以下是一个简单的 BeautifulSoup 实现示例:
from bs4 import BeautifulSoup
html_doc = """<html><head><title>Scraper</title></head>
<body>
<h1 class="title">Hello, World!</h1>
</body>"""
soup = BeautifulSoup(html_doc, 'html.parser')
print(soup.title.string)
这两个库都提供了简单便捷的 API,用于遍历、搜索和修改网页内容,非常适合用于网页抓取项目。
JSoup
如果您选择的编程语言是 Java,JSoup 是一个数据解析器,它利用 DOM、CSS 以及类似 jQuery 的方法,提供了一个用于提取和操作数据的便捷 API。
这使您能够通过简单直观的 API 解析和导航 HTML 文档,并修改文档内容。该库非常适合网页抓取、网络爬虫和数据提取项目。
以下是一个使用 JSoup 从 title 标签中提取文本的简单示例:
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
public class JSoupExample {
public static void main(String[] args) {
String html = "<html><head><title>Example Title</title></head>"
+ "<body>Hello, World!</body></html>";
Document doc = Jsoup.parse(html);
// Get the title of the document
String title = doc.title();
System.out.println("Title: " + title);
}
}Nokogiri
Nokogiri 是一个 Ruby 库,它为解析和搜索 XML 及 HTML 文档提供了易于使用的接口,并支持 XPath 和 CSS 选择器,因此常被用于网页抓取和数据提取任务。
若需更全面地了解 Ruby 生态系统中的数据解析库,可阅读这篇文章。
使用以下命令安装 nokogiri gem:
gem install nokogiri
下面的代码示例是一个简单的 Nokogiri 实现:
require "nokogiri"
html = "<!DOCTYPE html><html><head><title>Hello, World!</title></head><body>Hello, World!</body></html>"
parsed_data = Nokogiri::HTML.parse(html)
puts parsed_data.title正则表达式
正则表达式(也称为 regex)是匹配字符串中模式的强大工具。它们常用于文本处理任务,例如搜索、验证以及从文档中提取信息。
您可以通过搜索特定模式来使用正则表达式从 HTML 中提取信息,例如从 HTML 文档中提取电子邮件地址或标题。
例如,要从 HTML 文档中提取所有 URL,可以使用以下正则表达式:
/https?:\/\/[\w\.-]+\.[a-z]+/gi
该表达式将匹配任何以“http”或“https”开头、后跟冒号和两个斜杠,接着是任意组合的单词字符、点和连字符,最后以点和一个或多个小写字母结尾的字符串。“gi”标志表示全局搜索且不区分大小写。
使用正则表达式可能有些棘手,因为语法较为复杂,且要精确匹配模式可能需要反复尝试。此外,还有一些网站(如 Regex101 或 Rubular)可以帮助您测试和调试正则表达式。
如果您不想使用现成的库或正则表达式,也可以自行构建解析器。
构建自己的解析器是深入理解所处理数据的绝佳途径,若现有库或工具无法满足您的特定需求,这也是一个不错的选择。
构建解析器
构建解析器虽具挑战性,但回报颇丰。该过程涉及制定一套规则和指令,以明确数据的解析与组织方式。
你可以通过多种技术实现这一点,例如正则表达式、状态机和递归下降解析。
在构建解析器时,必须对数据的结构和格式有透彻的理解,才能为解析器设计出一套合适的规则和指令。选择合适的编程语言也是一个重要的考量因素。
构建自定义解析器的优势之一在于,您可以根据具体数据和用例进行量身定制。与使用通用库或工具相比,这往往能带来更高效、更有效的解析器。
此外,构建自己的解析器还是一次极好的学习经历,因为它能让你更深入地理解数据解析背后的核心概念和技术。
从零开始构建解析器也存在一些缺点:
- 设计和实现过程可能耗时且需要投入大量精力,特别是如果您不熟悉解析算法和数据结构的话。
- 要让自建解析器的性能达到经过性能优化的现有库或工具的水平,可能相当困难。
- 随着数据格式或结构的变更,解析器的维护和更新可能会变得困难。
- 代码的调试和错误排查可能较为困难,特别是当你对解析过程不熟悉时。
- 它可能容易出现错误和漏洞,导致解析器无法按预期工作。
- 对于复杂的解析,可能很难实现所有规则和边界情况。
- 它可能不如现有的库和工具高效,因为后者经过了优化且已被广泛使用。
总而言之,从头开始构建自定义解析器存在一系列缺点,例如开发时间长、维护成本高以及出错风险大。通常建议使用现有的库或工具,或者如果正则表达式能满足您的具体用例要求,也可以使用正则表达式。
Schema.org 元数据
解析 Schema.org 元数据是一种利用 Web 架构标准从网页中提取结构化数据的方法。Schema.org 背后的社区负责管理这些标准,并推动在 Web 上使用架构来处理结构化数据。
解析 Schema 元数据具有多种用途,例如查找活动更新信息,或供研究人员收集研究数据。此外,聚合房地产列表、招聘信息和天气预报等数据的网站也能从解析 Schema 数据中获益。
您可以使用多种 Schema 格式,包括 JSON-LD、RDFa 和 Microdata。
JSON-LD(链接数据的 JavaScript 对象表示法)是一种使用 JSON 编码链接数据的格式。该标准的设计使其既便于人类阅读和编写,也便于机器进行解析和生成。
以下是一个关于某本书的网页中 JSON-LD 的示例:
<script type="application/ld+json">
{
"@context": "http://schema.org",
"@type": "Book",
"name": "The Adventures of Tom Sawyer",
"author": "Mark Twain",
"datePublished": "1876-12-01",
"description": "The Adventures of Tom Sawyer is a novel about a young boy growing up along the Mississippi River in the mid-1800s. It is a classic of American literature and has been loved by generations of readers.",
"publisher": "Penguin Books",
"image": "https://www.example.com/images/tom_sawyer.jpg"
}
</script>
万维网联盟(W3C)推荐的 RDFa(即属性中的资源描述框架)用于在 XML 和 HTML 中嵌入 RDF 语句。
下文展示了 RDFa 在 HTML 页面中的呈现形式。您可以注意到标签属性是如何被用于存储额外数据的。
<!DOCTYPE html>
<html>
<head>
<title>RDFa Example</title>
</head>
<body>
<div about="http://example.com/books/the-great-gatsby" typeof="schema:Book">
<h1 property="schema:name">The Great Gatsby</h1>
<div property="schema:author" typeof="schema:Person">
<span property="schema:name">F. Scott Fitzgerald</span>
</div>
<div property="schema:review" typeof="schema:Review">
<span property="schema:author" typeof="schema:Person">
<span property="schema:name">John Doe</span>
</span>
<span property="schema:reviewBody">
A classic novel that explores themes of wealth, love, and the decline of the American Dream.
</span>
<span property="schema:ratingValue">4.5</span>
</div>
</div>
</body>
</html>
微数据(Microdata)是 WHATWG 制定的 HTML 规范,用于在网页现有内容中嵌套元数据,并可使用 schema.org 或自定义词汇表。
以下是 HTML 中微数据的示例:
<div itemscope itemtype="http://schema.org/Product">
<span itemprop="name">Shiny new gadget</span>
<img itemprop="image" src="shinygadget.jpg" alt="A shiny new gadget" />
<div itemprop="offerDetails" itemscope itemtype="http://schema.org/Offer">
<span itemprop="price">$19.99</span>
<link itemprop="availability" href="http://schema.org/InStock" />
</div>
</div>
目前有许多工具可用于解析不同语言的架构,例如 Zyte 的 Extruct 和 RDFLib 库,这些工具使利用 Web 架构标准从网页中提取结构化数据变得十分容易。
高级解析器
到目前为止,我们讨论了数据解析的基础知识,包括词法分析和语法分析的基本概念。我们还考察了各种用于数据解析的开源库、正则表达式的应用、从零开始构建解析器,以及使用 schema.org 解析数据的方法。
您随时可以依赖 WebScrapingAPI、SERP API 或 Amazon API 等网络解析器。这些网络解析器让您能够实时抓取数据,而无需担心维护、编码或基础设施问题。
使用付费级网页解析器具有以下优势:
- 可靠性:Web解析器通常比免费或开源的替代方案更稳定可靠,后者往往容易出现漏洞和错误。
- 速度:Web解析器经过速度和性能优化,可让您快速高效地提取数据。
- 可扩展性:网页解析器能够处理海量数据和高流量,非常适合大规模的抓取和数据提取项目。
- 高级功能:网页解析器通常包含IP轮换、用户代理伪装和验证码破解等高级功能,可帮助您绕过反爬虫措施并访问被封锁的网站。
- 技术支持与维护:Web解析器提供客户支持及定期软件更新,确保您能使用最新功能并获得漏洞修复。
但坦白说:付费网页解析器并非只有优点。以下是一些缺点:
- 成本:与开源选项相比,高级网页解析器的使用成本可能更高
- 定制化受限:与自行开发解析器相比,付费网络解析器的功能可能更为有限
- 对服务的依赖:若服务中断或出现故障,可能会影响您的数据解析能力
- 数据控制受限:使用付费网页解析器时,您对可访问和处理的数据可能控制较少
- 受制于服务商的数据源:付费网页解析器提供的数据质量和相关性可能受限于服务商的数据源。




