2026 无头 Firefox 代理抓取实战
TL;DR:无头 Firefox 适合必须执行 JavaScript、滚动或保持 Cookie 的页面;静态 HTML 和可合法调用的 JSON 接口应优先使用普通 HTTP 客户端。接入代理前先跑通无代理基线,再按完整页面任务固定代理会话,用显式等待验证价格、SKU 等字段,并分别统计导航失败、字段失败与限制页。
先判断是否需要 Selenium
Firefox 无头模式虽然不显示窗口,仍会执行脚本、计算布局、维护 Cookie,并加载异步接口和页面资源。它适用于以下场景:
- 价格或库存由 JavaScript 写入 DOM;
- 列表滚动到底部后才加载下一批数据;
- 配送地区、登录状态或 Cookie 会改变结果;
- 数据位于 iframe、弹窗或交互式筛选器中;
- 任务必须点击按钮或完成多步导航。
若字段已在初始 HTML 中,或页面调用了获准访问的 JSON 接口,直接发送 HTTP 请求通常更快、更省内存。先检查页面源代码,再查看开发者工具中的 Fetch/XHR;只有直接请求无法复现必要状态时,才使用 Selenium。
建立无代理基线
先排除浏览器、驱动和运行环境问题,否则代理接入后很难判断故障来自哪一层。
python -m venv .venv
source .venv/bin/activate # Linux 或 macOS
# .venv\Scripts\Activate.ps1 # Windows PowerShell
python -m pip install -U selenium
python -m pip freeze > requirements.lock
firefox --version
python --version
运行最小测试:
from selenium import webdriver
from selenium.webdriver.firefox.options import Options
options = Options()
options.add_argument("-headless")
driver = webdriver.Firefox(options=options)
try:
driver.set_page_load_timeout(30)
driver.get("https://example.com/")
assert driver.title == "Example Domain"
finally:
driver.quit()
新版 Selenium 通常通过 Selenium Manager 查找并缓存兼容驱动。离线服务器或禁止下载可执行文件的环境应预装 GeckoDriver;生产镜像还应固定 Python、Selenium、Firefox 和操作系统版本,并在升级后用同一组 URL 回归测试。
为 Firefox 配置住宅代理
HTTP 和 HTTPS 流量可使用以下配置:
from selenium import webdriver
from selenium.webdriver.firefox.options import Options
PROXY_HOST = "proxy.example.net"
PROXY_PORT = 10000
options = Options()
options.add_argument("-headless")
options.page_load_strategy = "eager"
options.set_preference("network.proxy.type", 1)
options.set_preference("network.proxy.http", PROXY_HOST)
options.set_preference("network.proxy.http_port", PROXY_PORT)
options.set_preference("network.proxy.ssl", PROXY_HOST)
options.set_preference("network.proxy.ssl_port", PROXY_PORT)
options.set_preference("network.proxy.no_proxies_on", "")
driver = webdriver.Firefox(options=options)
driver.set_window_size(1440, 900)
driver.set_page_load_timeout(30)
eager 会在文档进入可交互状态后返回,不等待全部图片和子资源完成;它不能保证价格或库存已经写入页面,仍需等待业务字段。
使用 SOCKS5 与远程 DNS
将 HTTP(S) 首选项替换为:
options.set_preference("network.proxy.type", 1)
options.set_preference("network.proxy.socks", PROXY_HOST)
options.set_preference("network.proxy.socks_port", PROXY_PORT)
options.set_preference("network.proxy.socks_version", 5)
options.set_preference("network.proxy.socks_remote_dns", True)
options.set_preference("network.proxy.no_proxies_on", "")
远程 DNS 可减少本地解析位置与代理出口国家不一致的问题。上线前应访问自有或获准使用的检测端点,核对出口 IP、国家和自治系统;还要检查目标页面的货币、语言和库存地区,因为这些结果也会受 Cookie、账户地址和浏览器语言影响。
处理代理认证
Firefox 的 network.proxy.* 首选项不直接保存用户名和密码。无头环境应优先选择:
- IP 白名单:适合有固定公网 IP 的运行节点;
- 本地认证转发器:Firefox 连接
127.0.0.1,转发器向上游提交凭据; - 受控扩展:仅在固定 Firefox 版本中充分测试后使用。
凭据应从环境变量或密钥服务读取。日志只保存代理会话 ID,不能记录包含密码的完整代理 URL。
用业务条件代替固定休眠
固定 sleep(10) 既浪费已提前完成的 8 秒,也无法区分慢请求、错误页和选择器失效。使用显式等待,同时验证价格、SKU 和加载遮罩:
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
def product_ready(driver):
prices = driver.find_elements(By.CSS_SELECTOR, "[data-testid='price']")
skus = driver.find_elements(By.CSS_SELECTOR, "[data-testid='sku']")
loading = driver.find_elements(By.CSS_SELECTOR, ".skeleton,.loading")
if loading or not prices or not skus:
return False
price = prices[0].text.strip()
sku = skus[0].text.strip()
return {"price": price, "sku": sku} if price and sku else False
record = WebDriverWait(
driver, 30, poll_frequency=0.5
).until(product_ready)
项目应把隐式等待保持为 0,统一使用显式等待,避免两类超时叠加后产生难以预测的等待时间。有效记录至少要满足以下条件:
- 价格非空且可转换为数值;
- 货币符合目标国家或配送地区;
- SKU 或商品 ID 存在;
- 加载骨架和遮罩已经消失;
- 最终 URL 不是登录页、验证码页或地区选择页。
页面成功打开但价格为空,应计为字段失败,而不是成功任务。
按业务事务管理代理会话
轮换会话适合彼此独立的商品页、搜索结果或公开列表。每个 URL 可以使用新会话,但从 driver.get() 到字段提取完成期间必须保持同一出口 IP,避免主文档和异步接口来自不同地区。
粘性会话适合登录、设置配送国家、购物车和多步表单。同一任务应绑定 Selenium 实例、浏览器配置文件、Cookie 与代理会话;出口 IP 变化后应从检查点重建状态,而不是把旧 Cookie 直接附加到另一个地区。
代理的直接收益包括按国家或城市验证本地化页面、避免单个出口成为全部任务的故障点,以及用粘性会话保持多步流程的一致身份。代价是新增认证、流量费用、出口质量差异和会话管理,因此应按有效记录而不是原始请求量评估。
分层排查错误并限制重试
建议采用有限退避:
第 1 次失败:等待 2 秒,在同一会话重试
第 2 次失败:等待 4 秒,重建浏览器和代理会话
第 3 次失败:等待 8 秒,进行最后一次尝试
仍失败:进入离线或人工复核队列
只有连接超时、临时 DNS 错误和短暂端点故障适合自动重试。验证码、权限拒绝、无效选择器和登录跳转必须停止并分类;提交订单、发送消息等非幂等操作不得自动重放。
| 错误或现象 | 常见原因 | 处理动作 |
|---|---|---|
SessionNotCreatedException | Firefox、驱动或 Selenium 不兼容 | 运行无代理基线并固定兼容版本 |
InvalidSelectorException | CSS 或 XPath 语法无效 | 在浏览器控制台验证选择器 |
NoSuchElementException | 元素未加载、位于 iframe 或定位器过期 | 显式等待,切换 iframe,检查 DOM |
TimeoutException | 导航慢、字段未出现或错误页 | 分开记录导航超时与字段超时 |
StaleElementReferenceException | DOM 更新后旧元素引用失效 | 在重试体内重新定位元素 |
ElementClickInterceptedException | Cookie 横幅或遮罩挡住目标 | 等待遮罩消失并滚动到元素 |
HTTP 407 | 白名单或凭据错误 | 独立测试代理认证,修复后再运行 |
HTTP 403、429 | 权限、频率或访问策略问题 | 降低并发并复核授权,不盲目重试 |
失败时保存 requested_url、final_url、耗时、异常类型、代理会话 ID、浏览器版本、截图和 HTML 快照。快照可能包含姓名、地址或令牌,必须脱敏并设置访问权限和保留期限。
用有效记录衡量性能与成本
从生产任务中抽取 50–100 个代表性 URL,覆盖不同地区、动态页面、有货、缺货和下架状态。每种配置运行 3 轮,并保持并发数、机器规格、URL 顺序和时间窗口一致。
导航成功率 = 到达预期页面数 ÷ 总任务数
字段完整率 = 必填字段合格数 ÷ 到达预期页面数
有效产出率 = 有效记录数 ÷ 总任务数
限制页比例 = 验证码、登录页等数量 ÷ 总任务数
每千条代理成本 = 代理费用 ÷ 有效记录数 × 1000
例如,1,000 个任务到达目标页 920 次,其中 874 条字段合格;消耗 14.2 GB,单价按 $0.73/GB 计算,则代理费用约 $10.37,每千条有效记录的代理成本约 $11.86。报告耗时应同时包含第 50 和第 95 百分位,避免少量 60 秒超时被平均值掩盖。
市场监测项目可参考面向市场研究的网页抓取指南,把采集失败、字段校验失败和分析误差分开管理。
EProxies 规格与容量规划
EProxies 提供 7200 万个以上住宅 IP,覆盖 195 个以上国家和地区,支持 HTTP(S) 和 SOCKS5。当前公布的服务运行时间指标为 98.2%,并由 99.9% 运行时间 SLA 支持;按量住宅代理从 $0.25/GB 起,300 GB 阶梯约为 $0.73/GB,ISP SOCKS5 从 $0.95/IP 起,不限流量方案从 $79/月 起。
入口价、阶梯价可能对应不同套餐或条件,应以控制台和合同为准。容量规划还要比较最低消费、并发限制、地区附加费、流量有效期,并设置每个域名的并发上限、单任务最大重试次数、每日费用上限和紧急停止开关。
合规边界
代理改变网络出口,但不提供访问授权,也不会取消网站条款、版权、合同和数据保护义务。robots.txt 不是授权机制;登录墙、验证码或明确拒绝访问应触发权限复核,而不是增加重试频率。
采集前应确认页面访问权限、自动化条款、数据类型、跨境传输要求、保留期限以及请求对网站的负载。跨地区项目可参考不同地区的网页抓取法律指南;社交平台项目可阅读How to Scrape Social Media Data Legally in 2026,公益研究可参考Web Scraping for Non-Profit Organizations in 2026。
常见问题
使用代理进行网页抓取有哪些好处?
代理可按国家或城市访问本地化页面,验证价格、语言、库存和搜索结果,并把任务分散到多个出口,降低单个 IP 故障对整个队列的影响。粘性会话还能让登录、配送地区和购物车流程保持同一网络身份;这些收益不等于获得访问授权,也必须计入流量成本、认证复杂度和出口质量差异。
如何排查常见的 Selenium 错误?
先运行无代理最小脚本,确认 Firefox、GeckoDriver 与 Selenium 版本兼容,再依据异常类型检查选择器、iframe、遮罩、DOM 更新和显式等待。对 TimeoutException 保存最终 URL、截图和 HTML;对 StaleElementReferenceException 重新定位元素;对 HTTP 407 检查代理认证,而 403、429 或验证码应触发限速与权限复核。
使用 Selenium 抓取网页有哪些最佳实践?
只在必须执行 JavaScript 或完成交互时使用 Selenium,并优先采用稳定 ID、data-* 属性或短 CSS 选择器;复杂文本匹配和跨层级定位再使用 XPath。使用显式等待、固定任务内代理会话、try/finally 关闭浏览器,并为每条记录保存来源 URL、采集时间、提取器版本和校验状态。并发应逐步增加,以第 95 百分位耗时、限制页比例和每千条有效记录成本确定上限。
如何确认 Selenium 请求确实经过代理?
访问自有或获准使用的出口检测端点,记录 IP、国家和自治系统,再核对目标页的货币、语言与库存地区。出口 IP 正确但业务地区错误时,应检查 Cookie、账户地址、浏览器语言和粘性会话状态。
代理认证返回 HTTP 407 怎么处理?
先确认任务使用 IP 白名单还是账号密码认证,再用独立连接测试代理端点。不要重复刷新目标页;认证修复前,重试只会增加耗时和失败日志。
本文由 EProxies 团队撰写,经内部质量标准核查与人工审核后发布。