如何在Python中解析HTML:选择器和验证检查

如何在Python中解析HTML

Scrapeless Web Unlocker可以为执行自己的解析和验证的Python程序提供获取或渲染的公共网页HTML。

TL;DR

  • HTML解析在获取后开始。 在构建树之前验证响应是否为预期页面。
  • Python提供内置和第三方解析器。 故意选择一个,因为格式不正确的标记可能会产生不同的树。
  • 在记录内作用范围选择器。 从同一卡片或行中提取相关字段,以避免混合邻近项目。
  • 解析不能运行页面JavaScript。 如果目标仅在浏览器执行后出现,请更改获取路径。

要在Python中解析HTML,获取标记,构建文档树,选择相关元素并规范化找到的值。解析器只是一个阶段。如果获取的页面是登录提示或JavaScriptshell,完美的选择器代码仍然会产生错误结果。首先写下你需要的确切字段和标记,指示返回的文档是预期的。

这个工作流程适用于HTML是来自本地保存的文件、允许的HTTP请求还是渲染服务。BeautifulSoup是一个方便的库,用于导航和CSS选择,而Python的标准html.parser则暴露了更低级的事件回调。选择应遵循提取任务。带有几个稳定标签的小页面不同于包含嵌套卡片和可选值的格式不正确的标记。

在解析之前获取正确的HTML

HTTP客户端下载初始响应;它不会自动执行页面脚本。检查最终URL、状态、媒体类型以及响应体中的预期标记。页面可以返回200和text/html,同时包含通知而不是数据集。在开发过程中保存一个小的代表性响应,去除凭据,以便可以根据产生早期结果的精确字节测试选择器更改。

该 HTTP语义标准 解释了为何状态和表示元数据与主体的应用含义分开。对于解析,这意味着将获取成功视为必要但不足的。如果响应被压缩或编码,请让成熟的HTTP库根据声明的元数据进行解码。避免在每个遗留页面上手动假设UTF-8。

如果记录在原始响应中缺失,但在浏览器加载页面后可见,请检查网络面板以获取允许的结构化响应。当真正需要浏览器执行时,请使用文档化的渲染路径,如 Web Unlocker JS Render。它可以在执行后返回HTML;然后Python解析器在返回的表示上工作。渲染会改变标记的来源,而不是BeautifulSoup如何解释它。

使用显式后端构建解析树

BeautifulSoup接受标记和命名解析器后端,例如Python的内置html.parser。它的 官方文档 解释了如何搜索标签、文本和属性的树。在代码中固定解析器,而不是让依赖于环境的默认值。不同的后端可以以不同的方式修复格式不正确的HTML,改变父子关系,因此选择器结果也会变化。

对于一个小的自包含输入,想象一个包含h2标题的文章元素、一个带有href的锚和一个持有价格的span。从该标记构建一个soup,首先选择文章,然后读取其中的每个字段。这个范围很重要:单独选择页面上的每个h2和每个价格span可能会在其中一篇文章缺少价格时产生不匹配的列表。面向记录的解析器将每篇文章视为提取的单位。

Python的 html.parser模块 是当你想在读取标签和数据时获得回调的另一种选择。它没有提供与BeautifulSoup相同的方便的CSS选择和树导航接口。选择它是为了狭窄的流式任务,而不是因为它在普遍意义上更正确。测试所选解析器与代表性的格式不正确和格式正确的页面。

使用稳定结构选择字段

CSS选择器可以针对语义元素、稳定属性或短的父子关系。当页面公开有意义的ID时,使用类似article[data-id]的选择器,然后在每篇文章中选择标题和链接。避免与视觉布局相关的生成类名的长链。这些类在重新设计期间可能会变化,即使数据字段在概念上保持相同。

BeautifulSoup select方法接受CSS选择器语法,而find和find_all在你需要属性测试或自定义谓词时很有用。选择器应表达记录合同,而不仅仅是恰好今天返回正确的计数。检查所选元素在代表性页面上的文本和属性。如果缺少字段是合理的,请明确表示为null或空的可选值,而不仅仅是将后续字段错移到错误记录中。

在选择后规范化提取的值。为显示文本合并布局空白,当精度重要时保留原始原始值,并根据最终响应URL解析相对href值。不要在观察到重定向后使用请求的URL作为基础。如果页面以多种货币列出价格,请将货币与数值保持在一起,而不是删除每个非数字字符并失去意义。

验证记录,而不仅仅是选择器。

返回一个节点的选择器并不能证明该节点是预期的记录。检查唯一页面标记、记录 ID 或规范 URL,以及必填字段。验证链接是否指向允许的主机,并且标题是否非空。如果某个字段是可选的,则在架构中定义其缺失。带有十个节点的解析结果仍然可能包含重复的卡片或导航预告,而不是所需的项目。

分页增加了另一个边界。遵循经过验证的下一个链接或文档中的光标,保持一个访问过的规范化 URL 或记录 ID 的集合,并在明确的结束条件处停止。固定数量的页面是上限,而不是证明集合自然结束的证据。分别测量接受的记录、拒绝的记录和选择器遗漏,以便在下游分析之前能够看到布局更改将部分批次视为完整的结果。

从允许的公共 HTML 派生的小示例可以帮助测试纯提取逻辑,但它并不能证明实时获取路径仍然返回该 HTML。保持一个集成检查,获取当前页面并验证身份。相关的 BeautifulSoup 网络抓取指南 正因如此,将静态获取与动态渲染分开。

决定何时渲染或使用结构化数据

当原始 HTML 已包含目标字段时,渲染浏览器会增加时间和状态,而不改善提取。当页面获取授权 JSON 端点以公开所需字段时,读取该响应可能比从 DOM 重建显示文本更简单。当交互或客户端代码创建目标元素时,浏览器或渲染服务是合适的。根据观察到的响应做出此决定,而不是基于“现代网站”等标签。

该 Web Unlocker 产品页面 描述了检索公共内容的选项,并提供 JavaScript 渲染。Python 脚本可以将返回的 HTML 传递给 BeautifulSoup,但仍应在解析之前检查服务响应和页面标记。不要仅仅因为脚本运行而假设渲染输出是完整的;延迟数据和交互后的视图可能需要另一个文档步骤。

遵守网站访问规则和操作负载。仅解析您被允许收集的页面,限制请求,并避免保留您的应用程序不需要的个人数据。这些决策应在解析器周围,而不是 CSS 选择器内部。正确的技术提取仍可能是一个不适合的数据实践,如果范围、目的或保留未定义。

保持提取测试与网络测试独立。一个小的保存 HTML 示例可以确认选择器读取预期标题并处理缺失链接。一个独立的实时检查可以确认当前返回的页面仍包含预期的记录容器。这些测试回答不同的问题,因此通过一个测试通过不应被报告为另一个路径有效的证据。当实时页面发生变化时,在更改应用程序存储规则之前,将其新标记与保存的示例进行比较。

结论

在 Python 中解析 HTML 是获取、树构建、作用域选择、规范化和验证的序列。解析器无法修复错误页面或执行缺失的 JavaScript。首先证明您拥有正确的表示,然后使每个选择器对记录级检查负责。

构建一个 Python HTML 提取流程

检索一个允许的公共页面,确认其身份,并用显式选择器解析返回的 HTML。

今天注册并获得 $5 的免费积分 — 无需信用卡.

立即领取您的 $5 积分 →

常见问题

BeautifulSoup 是否下载网页?

不。BeautifulSoup 解析另一个组件提供的标记。HTTP 客户端、本地文件或渲染服务必须首先提供 HTML。在创建解析树之前验证该表示。

我应该将哪个解析器传递给 BeautifulSoup?

故意选择解析器,并在代表性标记上测试它。Python 内置的 html.parser 可在没有其他解析器包的情况下使用,而替代后端可能会以不同方式解释格式不正确的 HTML。锁定后端可以使选择器的行为更具可重复性。

Python 是否可以在没有浏览器的情况下解析 JavaScript 渲染的页面?

如果其他组件已呈现它,Python 可以解析最终的 HTML,但普通的 HTTP 请求和 HTML 解析器并不执行浏览器的 JavaScript。在使用浏览器渲染之前,请检查目标是否存在于初始 HTML 或允许的结构化响应中。

应该如何处理缺失字段?

定义哪些字段是必需的,哪些字段是可选的。拒绝或标记缺少必需值的记录,并明确表示可选的缺失。不要将独立选择的标题和价格列表压缩在一起,因为一个缺失的价格可能会使后续的每条记录对齐错误。

抓取公共页面是否总是被允许?

公共可见性并不解决权限、隐私、版权或网站条款。审查适用的规则,仅收集您的项目被允许使用的内容。保持请求量的界限,并仅保留为声明的目的所必需的数据。

参考文献