视觉LLM网页抓取:读取截图,而不是DOM
Web Data Collection Specialist
视觉模型并不读取您的 HTML;它读取的是页面的图片。这改变了“抓取”的含义:您不再寻找持有值的选择器,而是将截图交给模型,询问它看到了什么。无抓取浏览器通过 Chrome DevTools Protocol 在云端获取该截图,而多模态模型则将像素转换为结构化数据。
当 DOM 对您发起挑战时,这就是您要使用的工具——一个嵌入在图像中的价格,一个没有底层表格的图表,一个画布渲染的小部件,或是在位置中而非标签中承载意义的布局。本指南连接到抓取浏览器,捕获渲染页面的截图,并让视觉模型从图像中返回 JSON,每一步都是实时执行的。
为什么读取截图而不是 DOM
基于选择器的抓取假定您想要的数据是标记中的一个值。但往往并非如此。商店可能将价格渲染为图像以阻止机器人,仪表板可能将数字绘制到没有文本的画布元素上,而营销页面可能完全在视觉布局中编码比较。在这些情况下,HTML 要么没有值,要么如此复杂以至于选择器比它指向的对象更脆弱。
视觉模型绕过了标记。它看到的是人所看到的——渲染并布局的页面——并从图像中读取值。截图必须忠实,这就是为什么它来自真实浏览器的原因:抓取浏览器在服务器端渲染页面,运行其脚本,并捕获用户会看到的画面,因此模型是对已完成页面进行推理,而不是半成品页面。
先决条件
您需要 Python 3.9 或更高版本、playwright 客户端和 requests,一个无抓取的浏览器会话 API 密钥,以及一个多模态模型的密钥。在 app.scrapeless.com 的免费计划中获取无抓取密钥。将这两个密钥保存在环境变量中;它们通过连接 URL 和授权头部传输,而不是在源代码中。
安装
bash
pip install playwright requests
配置
bash
export SCRAPELESS_API_KEY="your_scrapeless_api_key"
export OPENROUTER_API_KEY="your_model_api_key"
使用抓取浏览器捕获截图
通过 CDP 连接到云浏览器,打开页面并捕获视口。截图是由同一个渲染页面的 Chromium 生成的 PNG,因此模型接收的正是访客所看到的内容。捕获通过 Chrome DevTools Protocol 进行,并以 PNG 图像格式 返回字节:
python
import os
from urllib.parse import urlencode
from playwright.sync_api import sync_playwright
def browser_url():
return "wss://browser.scrapeless.com/api/v2/browser?" + urlencode(
{"token": os.environ["SCRAPELESS_API_KEY"], "sessionTTL": 180, "proxyCountry": "US"})
with sync_playwright() as p:
browser = p.chromium.connect_over_cdp(browser_url())
page = browser.new_page(viewport={"width": 1280, "height": 900})
page.goto("https://quotes.toscrape.com/", wait_until="networkidle")
png = page.screenshot()
browser.close()
print("screenshot bytes:", len(png))
print("PNG signature ok:", png[:8] == b"\x89PNG\r\n\x1a\n")
运行会确认确实返回了真实的图像:
text
screenshot bytes: 55462
PNG signature ok: True
在免费计划中获取您的 API 密钥:app.scrapeless.com
使用视觉模型读取截图
将 PNG 编码为 base64 数据 URL,连同您想要的架构一起发送到多模态模型,并将回复限制为 JSON。模型读取已渲染的页面并返回字段——无需选择器,无需 DOM 遍历。Base64 遵循 Base64 数据编码标准,这就是图像在 JSON 请求中传输的方式。完整的捕获和读取流程:
python
import os, base64, json, requests
from urllib.parse import urlencode
from playwright.sync_api import sync_playwright
def browser_url():
return "wss://browser.scrapeless.com/api/v2/browser?" + urlencode(
{"token": os.environ["SCRAPELESS_API_KEY"], "sessionTTL": 180, "proxyCountry": "US"})
with sync_playwright() as p:
browser = p.chromium.connect_over_cdp(browser_url())
page = browser.new_page(viewport={"width": 1280, "height": 900})
page.goto("https://quotes.toscrape.com/", wait_until="networkidle")
png = page.screenshot()
browser.close()
img = "data:image/png;base64," + base64.b64encode(png).decode()
resp = requests.post(
"https://openrouter.ai/api/v1/chat/completions",
headers={"Authorization": f"Bearer {os.environ['OPENROUTER_API_KEY']}", "Content-Type": "application/json"},
json={"model": "google/gemini-2.5-flash-lite",
"messages": [{"role": "user", "content": [
{"type": "text", "text": '从这个报价页面的截图中返回 JSON '
'{"quotes":[{"author":..., "text":...}]} 的前 3 条报价 '
'你可以看到。仅返回 JSON。'},
{"type": "image_url", "image_url": {"url": img}}]}],
"response_format": {"type": "json_object"}, "temperature": 0},
timeout=120,
)
resp.raise_for_status()
quotes = json.loads(resp.json()["choices"][0]["message"]["content"])["quotes"]
print("从图像中提取的报价数量:", len(quotes))
print("从图像中提取的第一个作者:", quotes[0]["author"])
模型读取像素并返回记录:
text
从图像中提取的报价数量: 3
从图像中提取的第一个作者: 阿尔伯特·爱因斯坦
图像从未被解析为 HTML。作者名称来自截屏中的渲染文本,这就是为什么这种方法在一个页面中可以存活下来,而该页面将相同的值隐藏在图像标签或画布后面。
当视觉值得付出时,以及何时不值得
视觉爬取不是免费的——一张图像的令牌数量远远超过包含相同值的 HTML 片段,并且模型可能会误读小或低对比度的文本。因此,要有意识地使用它。当值确实是可视的时,它是有价值的:嵌入图像中的文本、图表和画布小部件、转换为页面的 PDF,或空间上具有意义的布局。当数据是 DOM 中的干净文本时,选择器更便宜、更快速且更准确,从标记中读取是更好的选择。将抓取浏览器与视觉模型配对的优势在于您可以在同一渲染会话中两者之间切换——在可靠的地方解析 DOM,在不可靠的地方截屏和读取。
结论
视觉模型爬取以人类的方式读取页面。无抓取浏览器呈现目标并在 CDP 云中捕获真实的截图,多模态模型将图像转换为结构化 JSON。上面的运行从像素中拉取了三条报价和作者“阿尔伯特·爱因斯坦”,代码中没有选择器。将在 DOM 无法承载值的地方使用它,并将选择器保留给已经包含干净文本的页面部分——关于什么是 LLM 爬虫 的解释说明了模型在提取中的适用性。查阅 抓取浏览器产品页面 上的功能,并在以大规模运行之前权衡图像量与定价页面之间的关系。
加入我们的社区,领取免费计划,并与其他开发人员比较构建提取管道的笔记:Discord · Telegram。
常见问题
问:我什么时候应该通过截图而不是解析 HTML 来抓取?
当值是可视而非文本时使用视觉——以图像呈现的价格、在画布上绘制的数字、没有底层表格的图表,或通过位置编码意义的布局。当数据是 DOM 中的干净文本时,CSS 选择器更便宜且更精确。
问:为什么要用抓取浏览器捕获屏幕截图,而不是本地浏览器?
因为模型只能读取屏幕截图所显示的内容。抓取浏览器服务器端呈现页面,运行其脚本,并从云 Chromium 捕获已完成的帧,因此该图像是完全呈现的页面,而不是来自本地无头浏览器的半加载页面,您还需要维护该浏览器。
问:图像如何输入请求?
PNG 字节被 base64 编码为 data:image/png;base64,... URL,并作为 image_url 内容部分与文本提示一起发送。模型以与指令相同的 JSON 请求内联接收图像。
问:模型返回可靠的结构吗?
将响应限制为 JSON 对象并提供显式模式,如示例所示。模型将仅返回您请求的字段。小或低对比度文本的视觉读取需谨慎对待,并验证必须精确的值。
问:这比 DOM 抓取更贵吗?
是的。图像消耗的令牌远远超过等效 HTML 片段,因此视觉抓取每页的成本更高。只有在它解决真正的问题——仅有视觉的数据——时才使用它,并在文本已可用的地方解析 DOM。
问:我可以混合这两种方法吗?
是的,这通常是正确的设计。一个单一的抓取浏览器会话可以同时完成两项任务:解析DOM以提取干净标记中的字段,并截图未使用干净标记的区域,从而以最经济可靠的方式读取页面的每个部分。
在Scrapeless,我们仅访问公开可用的数据,并严格遵循适用的法律、法规和网站隐私政策。本博客中的内容仅供演示之用,不涉及任何非法或侵权活动。我们对使用本博客或第三方链接中的信息不做任何保证,并免除所有责任。在进行任何抓取活动之前,请咨询您的法律顾问,并审查目标网站的服务条款或获取必要的许可。



