🎯 一款可定制、具备反检测功能的云浏览器,由自主研发的 Chromium驱动,专为网页爬虫AI 代理设计。👉立即试用
返回博客

selectolax 网络爬虫:Python 中快速的 HTML 解析

Alex Johnson
Alex Johnson

Senior Web Scraping Engineer

23-Jul-2026

简要总结:

  • selectolax 使用 CSS 选择器解析 HTML,速度很快,因为它封装了基于 C 的 Lexbor 引擎,而不是纯 Python 的解析。
  • selectolax 不执行抓取。 它没有 HTTP 客户端,也不渲染 JavaScript;只需给它字节,它会解析,无其他。
  • 差距在一个脚本中显现。 对 JavaScript 渲染的演示页面进行普通 GET 请求,selectolax 得到 0 个引用节点;通过带有 js_render 的 Scrapeless Universal Scraping API 抓取同一 URL,则得到所有 10 个引用。
  • 本指南中的解析是真实的。 现场运行从渲染的 HTML 中提取了所有 10 个引用及其作者和标签数组,使用 csscss_first
  • 这两层干净地分开。 Scrapeless 负责抓取和渲染;selectolax 将字节转换为记录。两者之间没有交集。
  • 在抓取方面可以免费开始。app.scrapeless.com 创建你的 Scrapeless API 密钥。

selectolax 是什么,以及它不是什么

selectolax 是一个为速度而构建的 Python HTML 解析器。它绑定了 Lexbor 引擎,一个实现 HTML 标准的 C 库,因此解析文档和对其运行 CSS 选择器的操作发生在编译代码中,而不是解释器中。对于高量提取——成千上万的页面,紧密的循环——这个差异是人们选择它而不是更重的解析器的原因。

它是一个解析器,仅此而已。selectolax 没有HTTP客户端,不持久会话,也不运行JavaScript。给它一个字符串或字节,它会构建一个可以查询的树;让它去获取一个 URL,但设计上没有这种方法。因此,每个“selectolax 网页抓取”的设置都是两层:某种抓取可信 HTML 的东西,以及将其转换为数据的 selectolax。本指南使用 Scrapeless Universal Scraping API 作为第一层,因为普通 HTTP 客户端在任何用 JavaScript 构建内容的页面上会返回错误的字节。有关 Python 方面的更广泛介绍,Python 网页抓取教程 涵盖了该生态系统。

安装

selectolax 和 requests 是完整工具链。本指南编写时的版本是 selectolax 0.4.11:

bash Copy
pip install "selectolax==0.4.11" requests

将密钥保存在环境中,而不是源代码中:

bash Copy
export SCRAPELESS_API_KEY="sk_your_scrapeless_key"

获取值得解析的 HTML

解析质量受抓取保真度限制,因此从这里开始。在 JavaScript 渲染的页面上,普通 HTTP 客户端接收的文档并不是读者看到的文档:内容仅在脚本构建 DOM 后到达,这是一种由 HTML 脚本规范 定义的生命周期。以下脚本通过 selectolax 自身计算差异:

python Copy
# fidelity.py — selectolax 看到的内容:普通 GET 与服务器端渲染
import os

import requests
from selectolax.lexbor import LexborHTMLParser

URL = "https://quotes.toscrape.com/js/"

plain = requests.get(URL, timeout=60).text
print("普通 GET 字符数:", len(plain), "| 引用节点:", len(LexborHTMLParser(plain).css("div.quote")))

resp = requests.post(
    "https://api.scrapeless.com/api/v2/unlocker/request",
    headers={"Content-Type": "application/json", "x-api-token": os.environ["SCRAPELESS_API_KEY"]},
    json={"actor": "unlocker.webunlocker", "input": {"url": URL, "js_render": True}},
    timeout=120,
)
resp.raise_for_status()
rendered = resp.json().get("data", "")
print("渲染字符数:", len(rendered), "| 引用节点:", len(LexborHTMLParser(rendered).css("div.quote")))

运行显示普通抓取的引用节点数为 0,而渲染的为 10:

text Copy
普通 GET 字符数: 5806 | 引用节点: 0
渲染字符数: 8940 | 引用节点: 10

渲染、解锁和代理路由都在服务器端的一次 POST 中进行——Universal Scraping API 是抓取层,而渲染的字节是 selectolax 要解析的内容。

用 selectolax 解析

拿着真实的 HTML,selectolax 进行提取。css 返回匹配选择器的每个节点;css_first 返回第一个,因此你可以从每个记录中提取一个字段。这些选择器遵循 W3C 选择器规范,与您在 CSS 中使用的语法相同:

python Copy
# extract.py — 抓取渲染页面,然后使用 selectolax 提取记录
import os

import requests
from selectolax.lexbor import LexborHTMLParser

resp = requests.post(
    "https://api.scrapeless.com/api/v2/unlocker/request",

headers={"Content-Type": "application/json", "x-api-token": os.environ["SCRAPELESS_API_KEY"]},
json={"actor": "unlocker.webunlocker", "input": {"url": "https://quotes.toscrape.com/js/", "js_render": True}},
timeout=120,
)
resp.raise_for_status()
tree = LexborHTMLParser(resp.json().get("data", ""))

records = []
for quote in tree.css("div.quote"):
records.append({
"text": quote.css_first("span.text").text(),
"author": quote.css_first("small.author").text(),
"tags": [tag.text() for tag in quote.css("a.tag")],
})

print("记录:", len(records))
print("第一作者:", records[0]["author"])
print("第一标签:", records[0]["tags"])

Copy
实时运行返回了所有10条记录,第一条的作者和标签数组完整:

```text
记录: 10
第一作者: 阿尔伯特·爱因斯坦
第一标签: ['改变', '深刻思想', '思考', '世界']

这就是整个爬虫:一次POST请求来获取和渲染,一棵树来查询。text()返回节点的文本内容,并且构建每条记录的字典列表是可以扩展到页面上任何重复块的模式。

在免费计划中获取您的API密钥:app.scrapeless.com

高级模式

  • 使用LexborHTMLParser进行快速解析,使用HTMLParser进行温和后端解析。 selectolax通过同一API提供两种引擎;Lexbor是较新、更快的引擎,是高负载的正确默认选择。
  • 在使用css_first时预设一个default node.css_first("span.text", default=None)在缺少字段时返回None,可以防止不平衡记录的循环在与其他页面差异的页面上崩溃。
  • 使用.attributes读取属性。 对于链接和图片,node.attributes.get("href")从节点中提取属性——选择器找到元素,.attributes读取其数据。
  • 当不需要树时获取markdown。 如果您只想要可读文本,Scrapeless API可以直接返回渲染的内容;当您需要对结构化字段进行选择器级控制时,请使用selectolax。

故障排除

  • 从可以在浏览器中看到的页面中获取零节点。 内容是JavaScript渲染的,您的抓取返回了预渲染的HTML。像第一个脚本那样计算已知选择器;几乎为空的树是抓取问题,使用js_render修复,而不是选择器问题。
  • AttributeError: 'NoneType' object has no attribute 'text' css_first没有找到任何内容,而您在None上调用了.text()。传递default=None并在读取之前检查,或确认选择器与渲染的标记匹配。
  • 文本有多余的空白。 text()返回原始节点文本;调用.strip()或在节点嵌套子节点时传递deep=True/separator选项,以将其文本合并。
  • 编码看起来不正确。 传递响应字节而不是错误解码的字符串;selectolax在您传递字节时读取文档声明的编码。

结论

selectolax凭借不触及网络的解析层而赢得了自己的位置:向它提供真实的HTML,它快速返回记录,并且使用您已经熟悉的CSS选择器。决定是否可能的层是抓取——第一个脚本的0与10的计数决定了这一切——一次服务器渲染的POST弥补了这一差距。将这两者连接起来,演示页面的十个引用以干净的字典形式到达,标签和所有信息。

创建一个免费的Scrapeless账户以获取API密钥,而开发者文档涵盖了unlocker.webunlocker参数。当您计划定期工作时,请查看Scrapeless定价

常见问题

问:selectolax可以独立抓取网站吗?

不可以。selectolax解析您已经拥有的HTML;它没有HTTP客户端,也不渲染JavaScript。将其与抓取层配对——这里是Scrapeless通用抓取API,它在服务器端渲染页面——selectolax处理从返回的字节中提取。

问:为什么使用selectolax而不是BeautifulSoup?

速度。selectolax包装了基于C的Lexbor引擎,因此解析和选择器查询在编译代码中运行,这在高页面量时很重要。权衡是特性表面较小;对于多页的基于选择器的提取,通常这是正确的权衡。

问:csscss_first之间有什么区别?
css 返回匹配选择器的每个节点的列表;css_first 只返回第一个匹配项(或你提供的 default)。使用 css 循环遍历重复的块,例如搜索结果,而使用 css_first 从每个块中提取单个字段。

问:selectolax 处理 JavaScript 渲染的页面吗?

不能 — 它不会执行脚本。如果内容在初始 HTML 加载后才出现,普通的获取会让 selectolax 得到一个空树。首先通过 Scrapeless API 使用 js_render 获取页面,然后解析渲染后的 HTML,如本指南所述。

问:使用 selectolax 抓取合法吗?

解析器并不改变收集规则。仅获取公共页面,尊重网站条款和由 机器人排除协议 标准化的机器人指令,保持量的限制,并根据适用的法律处理任何个人数据。

在Scrapeless,我们仅访问公开可用的数据,并严格遵循适用的法律、法规和网站隐私政策。本博客中的内容仅供演示之用,不涉及任何非法或侵权活动。我们对使用本博客或第三方链接中的信息不做任何保证,并免除所有责任。在进行任何抓取活动之前,请咨询您的法律顾问,并审查目标网站的服务条款或获取必要的许可。

最受欢迎的文章

目录