SeleniumBase를 사용한 하나의 범용 스크립트로 ZoomInfo 스크래핑
Source: Dev.to
시작하기 전에
ZoomInfo는 간단하고 안정적인 방법으로 스크래핑할 수 있습니다. 사이트는 핵심 데이터를 application/json 블록 안에 저장하므로 복잡한 CSS 선택자를 사용하지 않고도 검색 결과, 프로필 및 회사 상세 정보를 추출할 수 있습니다.
사전 요구 사항 및 설정
ZoomInfo는 자동화된 행동을 의심하면 누르고 있기 캡차를 표시합니다. 단순 요청 라이브러리나 헤드리스 Selenium/Playwright는 작동하지 않습니다. 지문, 헤더를 패치하고 헤드리스 모드를 숨기는 도구가 필요합니다. 예: SeleniumBase, Playwright Stealth, Patchright.
우리는 UC 모드의 SeleniumBase(Undetectable Browser 기반)를 사용할 것입니다. 다음 명령으로 설치합니다:
pip install seleniumbase
사용 가능한 데이터 포인트
| 페이지 유형 | 주요 데이터 포인트 | 비고 |
|---|---|---|
| 검색 페이지 | 이름, 직함, 프로필 링크, 회사 링크 | 처음 5페이지만. 이메일/전화/이미지는 보통 누락됨. 일부 필드는 비어 있거나 null일 수 있음. |
| 인물 프로필 | 전체 이름, 직함, 사진, 소개, 마스킹된 이메일/전화, 근무 주소, 소셜 링크, 학력·경력, 고용주 정보, 동료, 유사 프로필, 웹 언급, AI 신호 | 대부분의 데이터가 완전함. 연락처 정보는 부분적으로 숨겨짐. |
| 회사 페이지 | 법인명, 규모, 직원 수, 기술 스택, 재무 정보, 경쟁사, 임원진, 주소, 소셜 링크, 뉴스, 인수·합병, 조직도, 이메일 패턴, 채용 트렌드, 인텐트 신호, 수상 내역, 비교 대상 | 일부 연락처 정보, 과거 재무 데이터, 이메일 샘플, 인텐트 데이터는 부분적으로 누락되거나 마스킹될 수 있음. |
범용 스크래핑 스크립트
이 스크립트는 검색 페이지, 인물 프로필, 회사 페이지 모두에서 동작합니다. <script> 태그 안의 JSON 데이터를 추출하고, 불필요한 키를 제거한 뒤 파일에 저장합니다.
from seleniumbase import SB
from selenium.webdriver.common.by import By
import time, json
# 페이지 기본 URL (검색, 인물, 또는 회사)
base_url = "https://www.zoominfo.com/people-search/" # 또는 person/company URL
pages = 5 # 검색 페이지용; 단일 프로필/회사는 1로 설정
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) # JSON 스크립트가 렌더링될 때까지 대기
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)
# 데이터 저장
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 | 스크래퍼 감지 | 지연 추가, 프록시 회전 |
봇 마스킹, 프록시 회전, 일시 정지 삽입, 오류 시 장시간 대기 등을 통해 오류, 캡차, 차단을 완화할 수 있습니다.
참고
전체 단계별 설명, 시각 자료 및 팁이 포함된 자세한 가이드는 블로그의 전체 글을 확인하세요: Read the Full Article
모든 예제는 GitHub 저장소에서도 확인할 수 있습니다.