编写 XPath 表达式的技巧

学习为自定义解析器编写有效 XPath 表达式的实用技巧和最佳实践,确保准确的数据提取。

抓取的文档与浏览器加载的文档之间的 HTML 结构可能不同

在编写 HTML 元素选择函数时, 请确保使用抓取到的文档,而不是你浏览器中加载的在线网站版本,因为文档可能不同。造成此问题的主要原因是 JavaScript 渲染。当网站被打开时,浏览器负责加载额外的文档,例如 CSS 样式表和 JavaScript 脚本,这些都可能改变初始 HTML 文档的结构。在解析抓取的 HTML 时,Custom Parser 不会像浏览器那样加载 HTML 文档(解析器会忽略 JavaScript 指令),因此解析器与浏览器渲染的 HTML 树可能不同。

例如,请查看以下 HTML 文档:

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <div>
        <h3>This is a product</h3>
        <div id="price-container">
            <p>This is the price:</p>
        </div>
        <p>And here is some description</p>
    </div>
    <script>
        const priceContainer = document.querySelector("#price-container");
        const priceElement = document.createElement("p");
        priceElement.textContent = "123";
        priceElement.id = "price"
        priceContainer.insertAdjacentElement("beforeend", priceElement);
    </script>
</body>
</html>

如果你通过浏览器打开该文档,它会显示价格,你可以使用以下 XPath 表达式进行选择 //p[@id="price"]:

现在如果你在浏览器中禁用 JavaScript 渲染,网站将按如下方式渲染:

同样的 //p[@id="price"] XPath 表达式将不再匹配价格,因为它未被渲染。

请确保为目标元素编写所有可能的 HTML 选择器

出于多种原因,同一页面被抓取两次可能具有不同的布局(抓取时使用了不同的 User-Agent、目标网站进行 A/B 测试等)。

为解决此问题,我们建议为最初抓取的文档定义 parsing_instructions ,并立即使用同类型页面的多个其他抓取任务结果来测试这些指令。

HTML 选择器函数(xpath/xpath_one)支持 选择器回退.

推荐的 HTML 选择器编写流程

  1. 使用 网页爬虫API 抓取目标页面的 HTML 文档。

  2. 禁用 JavaScript,并在本地使用浏览器打开抓取的 HTML。如果在 之后 禁用 JavaScript 才打开了 HTML,请确保重新加载页面,使 HTML 在没有 JavaScript 的情况下重新加载。

如何编写解析指令

假设你有以下页面需要解析:

解析商品标题

创建一个新的 JSON 对象,并为其分配一个新字段。

你可以按喜好命名该字段,但有一些例外(用户自定义字段名不能以下划线开头 _ ,例如: "_title").

字段名将显示在解析结果中。

新字段必须是 JSON 对象类型的值:

如果你将这些指令提供给 Custom Parser,它将不会执行任何操作,或者会提示你没有提供任何指令。

要将标题实际解析到 title 字段中,你必须在该 title 对象内使用保留的 _fns 属性(其类型始终为 array)来定义数据处理流水线:

为了让 Custom Parser 选择标题文本,你可以使用 HTML 选择器函数 xpath_one。要在 HTML 文档上使用该函数,应将其添加到数据处理流水线中。该函数定义为一个包含必需 _fn (函数名)和必需 _args (函数参数)字段的 JSON 对象。查看完整的函数定义列表 此处.

上述解析指令应生成以下结果:

解析描述

类似地,在解析指令中,你可以定义另一个字段来解析商品描述容器、描述标题和条目。为了让描述的标题和条目嵌套在 description 对象下,指令的结构应如下所示:

给定的解析指令结构意味着 description.titledescription.items 将基于 description 元素来解析。你可以为 description 字段定义一个流水线。在此情况下,先执行它,以简化描述标题的 XPath 表达式。

在该示例中, description._fns 流水线将选择 description-container HTML 元素,它将作为解析描述标题和条目的参考点。

要解析剩余的描述字段,为字段添加两个不同的流水线 description.items,和 description.title:

注意到 xpath 函数用于替代 xpath_one 以提取所有匹配该 XPath 表达式的条目。

解析指令将生成以下结果:

解析商品变体

以下示例展示了如果你想将信息解析到 product_variants 字段(其中包含变体对象的列表)时指令的结构。在此情况下,变体对象包含 价格color 字段。

首先选择所有商品变体元素:

要将 product_variants 制作为包含 JSON 对象的列表,你需要使用 _items 迭代器来遍历找到的变体:

最后,定义如何解析 color价格 字段的指令:

在描述了 product_variants 之后,最终指令如下所示:

它将生成如下输出:

你可以在此处找到更多解析指令示例: Parsing instruction examples.

最后更新于

这有帮助吗?