使用 SeleniumBase 的通用脚本抓取 ZoomInfo
Source: Dev.to
开始之前
ZoomInfo 可以以一种简单且稳定的方式进行爬取。该站点将关键数据存放在 application/json 块中,您可以在不使用复杂 CSS 选择器的情况下提取搜索结果、个人资料和公司详情。
前置条件和设置
如果 ZoomInfo 怀疑有自动化操作,会显示按住不放的验证码。普通的请求库或无头 Selenium/Playwright 将无法工作。您需要能够伪装指纹、请求头并隐藏无头模式的工具,例如 SeleniumBase、Playwright Stealth 或 Patchright。
我们将使用 SeleniumBase 的 UC 模式(基于 Undetectable Browser)。使用以下命令安装:
pip install seleniumbase
可获取的数据点
| 页面类型 | 关键数据点 | 备注 |
|---|---|---|
| 搜索页面 | 姓名、职位、个人资料链接、公司链接 | 仅前 5 页。电子邮件/电话/图片通常缺失。部分字段为空或为 null。 |
| 个人资料 | 全名、职位、照片、简介、掩码邮箱/电话、工作地址、社交链接、工作与教育经历、雇主信息、同事、相似资料、网页提及、AI 信号 | 大多数数据完整。联系信息部分被隐藏。 |
| 公司页面 | 法定名称、规模、员工数、技术栈、财务信息、竞争对手、管理层、地址、社交链接、新闻、收购、组织结构图、邮箱模式、招聘趋势、意向信号、奖项、可比公司 | 部分联系信息、历史财务、邮箱示例和意向数据可能不完整或被掩码。 |
通用爬取脚本
该脚本适用于搜索页面、个人资料和公司页面。它从 <script> 标签中提取 JSON 数据,去除不必要的键,并将结果保存到文件中。
from seleniumbase import SB
from selenium.webdriver.common.by import By
import time, json
# Base URL for the page (search, person, or company)
base_url = "https://www.zoominfo.com/people-search/" # or person/company URL
pages = 5 # for search pages; set 1 for single profile/company
all_data = []
with SB(uc=True, test=True) as sb:
for page in range(1, pages + 1):
url = f"{base_url}?pageNum={page}" if pages > 1 else base_url
sb.uc_open_with_reconnect(url, 4)
time.sleep(1) # Wait for JSON scripts to render
try:
scripts = sb.find_elements('script[type="application/json"]', by=By.CSS_SELECTOR)
for el in scripts:
content = el.get_attribute("innerHTML")
data = json.loads(content)
data.pop("__nghData__", None)
data.pop("cta_config", None)
all_data.append(data)
except Exception as e:
print(f"Page {page} error:", e)
# Save the data
with open("zoominfo_data.json", "w", encoding="utf-8") as f:
json.dump(all_data, f, ensure_ascii=False, indent=2)
生成的 JSON 包含几乎所有可用数据:
- 搜索页面: 姓名、职位、个人资料链接、公司链接。电子邮件、电话和图片大多被隐藏。
- 个人页面: 完整的个人信息、掩码联系方式、工作/教育经历、同事、AI 信号。
- 公司页面: 法定名称、员工数、技术栈、财务、管理层、新闻、收购、招聘趋势、奖项等。部分字段会被部分掩码。
反爬措施
ZoomInfo 采用了强大的反机器人防护。解析数据前请检查 HTTP 状态码并相应处理。
| 状态码 | 含义 | 恢复方式 |
|---|---|---|
| 200 | 成功 | 继续 |
| 429 | 触发限流 | 等待 30‑60 秒后重试 |
| 403 | 禁止(IP 被封) | 更换 IP/代理,次日重试 |
| 503 | 服务不可用 | 5 分钟后重试 |
| 200 (empty) | 蜜罐 | 更换 IP |
| Redirect /error | 检测到爬虫 | 添加延迟,轮换代理 |
通过伪装机器人、轮换代理、添加暂停以及在错误时使用更长延迟来减轻错误、验证码和封禁的风险。
备注
想获取包含逐步解释、示例图和技巧的完整教程,请访问我们的博客全文:阅读完整文章
所有示例代码均已放在 GitHub 仓库 中。