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

Selenium网页抓取:实用的Python指南

Daniel Kim
Daniel Kim

Lead Scraping Automation Engineer

05-Aug-2026

TL;DR:

  • Selenium通过WebDriver协议驱动真实的Chrome,因此它看到的是一个页面使用JavaScript构建的DOM——而普通的HTTP请求无法获取的内容。
  • 下面的实时运行从一个演示页面读取了所有十个引用,该页面发送了一个空容器,并在客户端填充;而对bare requests.get的调用则返回零行。
  • 现代Selenium自动解析自己的驱动:Selenium管理器将ChromeDriver与您已安装的Chrome匹配,因此webdriver.Chrome(options=...)可在不手动下载的情况下运行。
  • Selenium的真正成本在于操作——每个工作进程都是一个完全的浏览器,从您自己的IP地址退出,这对扩展来说负担沉重,并且容易被反机器人系统进行速率限制。
  • honest-limits pivot将相同的URL发送到Scrapeless Universal Scraping API,该API在服务器端渲染页面并返回完整的HTML,无需您运行或扩展浏览器。
  • 在免费计划中获取一个Scrapeless API密钥,并自己运行两个部分。

Selenium在抓取中的作用

Selenium自动化一个真实的浏览器。您的Python代码通过WebDriver协议与ChromeDriver通信,ChromeDriver驱动Chrome,Chrome则执行浏览器所做的事情:请求页面,运行脚本,构建DOM。最后一部分就是抓取者寻求它的原因。一个在客户端组装内容的页面——由框架渲染的产品网格,通过后台请求到达的动态内容——在原始HTML中是空的,只有在脚本运行后才完整。Selenium等待执行并将完成的页面交给您。

权衡是重量。Selenium每个会话运行一个实际的Chrome,这需要内存和启动时间,请求是从您机器的IP发出的。对于少量页面来说,这很不错。本指南首先构建一个工作的Selenium抓取程序,然后展示何时运行自己的浏览器不再划算以及该如何处理。在这里的每个代码路径都是针对实时页面执行的。

安装

安装Selenium Python绑定:

bash Copy
pip install selenium

您不需要手动安装ChromeDriver。从版本4.6开始,Selenium与Selenium管理器一起提供Selenium WebDriver工具,它在首次使用时会检测您的Chrome并解析匹配的驱动程序。您需要安装最新版本的Google Chrome;绑定库会处理其余部分。

配置

为了后面指南中的pivot,将您的Scrapeless API密钥放入环境变量中,以免出现在源代码中:

bash Copy
export SCRAPELESS_API_KEY="your_scrapeless_api_key"

基本实现:渲染JavaScript页面

将Selenium指向一个在客户端构建其行的页面,一旦导航返回,元素就会出现。下面的演示发送了一个空容器,并用JavaScript填充;原始标记中没有.quote节点,而浏览器渲染的DOM中包含十个,因为Chrome首先运行了脚本,遵循了HTML解析和脚本模型

python Copy
import tempfile
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By

opts = Options()
opts.add_argument("--headless=new")
opts.add_argument("--no-sandbox")
opts.add_argument("--disable-dev-shm-usage")
opts.add_argument(f"--user-data-dir={tempfile.mkdtemp()}")

driver = webdriver.Chrome(options=opts)   # Selenium Manager解析驱动
try:
    driver.get("https://quotes.toscrape.com/js/")
    quotes = driver.find_elements(By.CSS_SELECTOR, ".quote")
    print("JS页面上的引用块数量:", len(quotes))
    print("第一位作者:", quotes[0].find_element(By.CSS_SELECTOR, ".author").text)
finally:
    driver.quit()

运行会打印数量和第一个记录:

text Copy
JS页面上的引用块数量: 10
第一位作者: 阿尔伯特·爱因斯坦

--headless=new标志使Chrome在没有可见窗口的情况下运行,这在服务器上是您所需要的。--no-sandbox--disable-dev-shm-usage保持Chrome在容器和受限环境中的稳定,而一次性--user-data-dir为每次运行提供自己的配置文件,以避免并行会话冲突。

高级模式:等待和选择

driver.get在文档加载时返回,但脚本构建的元素可能在稍后出现。与其固定时间休眠,不如等待特定条件。WebDriverWaitexpected_conditions配对,直到您命名的元素存在,因此抓取在数据存在的瞬间开始,而不是更早:

python Copy
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

WebDriverWait(driver, 10).until(
    EC.presence_of_element_located((By.CSS_SELECTOR, ".quote"))
)

优先选择稳定的选择器而不是哈希 CSS 类:一个 id、一个 data-* 属性或一个语义标签在重新设计中生存时会保留原有的样式类名称。对于您需要分页的页面,读取“下一页”链接的 href 并跟随它,而不是猜测页码。

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

诚实的限制和转折

Selenium 能很好地渲染 JavaScript;它做不到的是使运行浏览器变得便宜或使您的流量不那么显眼。每个 Selenium 工作线程都是一个完整的 Chrome,因此扩展到多个页面意味着需要扩展浏览器及其所需的内存,而每个请求都是从您自己的 IP 发出的,一个繁忙的网站可以对其实施速率限制或挑战。Selenium 对于管理的反机器人挑战没有内置的解决方案 — 它渲染所给定的页面,而它从未到达的页面则渲染为无。

Scrapeless 通用抓取 API 将操作的部分卸载到您的机器上。您发送启用 js_render 的 URL;它在管理的反机器人处理和轮换住宅出口后服务器端渲染页面,并将完成的 HTML 返回至其 data 字段。您无需启动浏览器,请求也不是通过您的 IP 发出的。您可以像解析 Selenium 的页面源代码那样解析返回的 HTML:

python Copy
import os, re, json, requests

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

authors = re.findall(r'<small class="author">(.*?)</small>', html)
print("通过通用抓取 API 渲染的引用块:", html.count('class="quote"'))
print("提取的作者数量:", len(authors))
print("第一位作者:", authors[0])

单个请求返回同一个渲染页面,服务器端:

text Copy
通过通用抓取 API 渲染的引用块: 10
提取的作者数量: 10
第一位作者: 阿尔伯特·爱因斯坦

经验法则:当您控制目标且流量较小时保留 Selenium,当工作是操作时(多个页面、被阻止的 IP 或者是 Selenium 无法清除的挑战)将提取迁移到 API。解析代码不变;只有 HTML 的来源改变了。

故障排除

驱动版本错误几乎总是意味着 Chrome 更新且旧驱动仍然存在;在 Selenium 4.6 及更高版本中,Selenium 管理器为您解析当前驱动,因此从您的 PATH 中移除手动固定的 ChromeDriver 通常可以解决此问题。在您可以在普通浏览器中看到的页面上结果为空,意味着内容在 driver.get 返回后到达 — 针对您所需的选择器添加上面的 WebDriverWait。在一个从未网络安静的页面上挂起来的运行意味着您等待了错误的条件;要等待元素,而不是网络。

保持工作在网站所声明的边界内。阅读其条款和机器人排除协议文件,只请求公共页面,并保持并发适度 — 同样的原则也适用于文档对象模型指导中,Selenium 读取这个模型。有关发现和提取的更广泛的探索,从头开始构建网络抓取器 的操作与此内容搭配良好。

结论

当一个页面需要真实的浏览器才能存在时,Selenium 占据了它的位置:它通过 WebDriver 协议驱动 Chrome,运行脚本,并将渲染的 DOM 交给您 — 从一个在其标记中不包含任何内容的页面中提取十个引文。它停止获益的地方是与该浏览器相关的操作:会话扩展的内存、您自己的 IP 的暴露,以及它无法清除的挑战。这时同一个 URL 通过 Scrapeless 通用抓取 API 返回渲染的 HTML,无需运行浏览器,而您的解析代码仍然保持不变。在扩展之前,请检查您所需的请求量与 定价页面 进行比较。
加入我们的社区以获取免费计划,并与其他构建抓取器的开发者交流经验:Discord · Telegram

常见问题

问:使用Selenium需要下载ChromeDriver吗?

不需要。Selenium 4.6及更新版本内置Selenium Manager,它在第一次使用时检测已安装的Chrome并解决相应的ChromeDriver,因此webdriver.Chrome(options=...)可以在不手动下载驱动程序的情况下工作。

问:为什么Selenium能够找到requests无法找到的元素?

Selenium运行一个真实的浏览器,执行页面的JavaScript并构建DOM,因此在查询时脚本生成的元素已经存在。简单的HTTP客户端仅接收服务器的初始标记,而在客户端渲染的页面中不包含这些内容。

问:我应该何时从Selenium切换到通用抓取API?

当操作上的难度高于渲染时就切换——有许多页面需要抓取,你的IP被限流,或者是Selenium无法处理的托管反机器人挑战。该API在服务器端渲染并返回完成的HTML,因此你可以保留解析并省去浏览器集群。

问:如何等待在页面后加载的内容?

使用WebDriverWaitexpected_conditions来阻塞,直到特定选择器存在,而不是固定的time.sleep。抓取在元素存在的那一刻开始,这比猜测的延迟更快,更可靠。

问:使用Selenium抓取数据合法吗?

抓取公共数据通常是允许的,但责任在于你自己:遵守网站的条款及其机器人指令,只收集公共页面,避免处理没有基础的个人数据,并保持请求速率适中。

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

最受欢迎的文章

目录