Indeed 채용 공고 스크래핑 방법: 구조, 블록 및 SERP 경로
Indeed는 웹에서 가장 큰 채용 사이트이자 실시간 노동 시장 신호입니다. 또한 Cloudflare 뒤에 있으며 클래스 이름이 매주 회전합니다. 이를 지속적으로 추출하는 방법과 사이트를 완전히 건너뛰어야 할 때를 설명합니다.
Indeed는 월 약 5억 4,200만 방문을 기록하며, 이는 역할별 채용 수요, 급여 범위, 인력을 확충하는 회사 등을 포함한 노동 시장의 가장 깨끗한 실시간 신호 중 하나입니다. 또한 가시적인 CSS 클래스 이름이 자주 회전하여 몇 주 안에 단순한 스크래퍼를 무너뜨리는 Cloudflare 보호 React 사이트입니다. 이 가이드는 Indeed 채용 공고를 지속적으로 스크래핑하는 방법, 페이지 및 중복 제거 방법, Cloudflare 현실, 그리고 싸움을 완전히 건너뛸 수 있는 채용 SERP 수직을 설명합니다.
검색 페이지 읽기, 안정적인 속성에 고정
Indeed 데이터의 단위는 검색 결과 페이지입니다: 쿼리와 위치가 결합되어 채용 카드 페이지를 제공합니다. 함정은 Indeed가 재생성하는 해시된 클래스 이름(eu4oa1w0 같은 것들)을 선택하는 것입니다. 대신 data-testid 속성에 고정하세요. 이 속성은 훨씬 덜 자주 변경됩니다:
import requests
from bs4 import BeautifulSoup
headers = {
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 "
"(KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36",
"Accept-Language": "en-US,en;q=0.9",
}
proxies = {"http": "http://USER:PASS@gate.quantumproxies.io:8000",
"https": "http://USER:PASS@gate.quantumproxies.io:8000"}
url = "https://www.indeed.com/jobs?q=python&l=New+York%2C+NY"
html = requests.get(url, headers=headers, proxies=proxies, timeout=30).text
soup = BeautifulSoup(html, "html.parser")
jobs = []
for card in soup.select("div.job_seen_beacon"):
title = card.find("a", class_="jcs-JobTitle")
company = card.find("span", attrs={"data-testid": "company-name"})
location = card.find("div", attrs={"data-testid": "text-location"})
jobs.append({
"title": title.get_text(strip=True) if title else None,
"company": company.get_text(strip=True) if company else None,
"location": location.get_text(strip=True) if location else None,
"jk": title["href"].split("jk=")[-1][:16] if title else None,
})
print(len(jobs), "jobs on page 1")
각 카드에는 페이지 및 실행 간 중복 제거에 사용하는 안정적인 ID인 채용 키(jk)가 포함되어 있습니다. URL이 아닌 jk에 저장하세요. 동일한 게시물이 다른 추적 매개변수와 함께 나타나기 때문입니다.
페이지네이션 및 국가 사이트
Indeed는 10씩 증가하는 start 매개변수를 사용하여 페이지를 나눕니다. 그리고 이는 하나의 사이트가 아닙니다 — 각 국가는 하위 도메인입니다: 미국은 www.indeed.com, 영국은 uk.indeed.com 등입니다. 쿼리하는 국가에 맞춰 프록시 출구를 일치시켜 요청이 지리적으로 일관되도록 하세요:
def crawl(query, location, country="www", pages=5):
base = f"https://{country}.indeed.com/jobs"
for start in range(0, pages * 10, 10):
params = {"q": query, "l": location, "start": start}
html = requests.get(base, params=params, headers=headers,
proxies=proxies, timeout=30).text
# parse as above, yield rows
yield html
# freshness filter: fromage accepts only 1, 3, 7 or 14 days
# .../jobs?q=python&l=NYC&fromage=7
알아두면 좋은 특이점: Indeed의 "게시일" 필터(fromage)는 1, 3, 7 또는 14일만 허용합니다 — 다른 값은 무시되므로 이러한 버킷을 중심으로 신선도 논리를 구축하세요.

Cloudflare 현실
Indeed는 Cloudflare 뒤에 있으므로 데이터센터 IP로 단순 요청 시 결과 대신 도전 과제를 받는 경우가 많습니다. 해결책은 일반적인 안티봇 스택입니다: 일관된 브라우저 User-Agent 및 헤더 세트, 그리고 — 가장 큰 지렛대 — 자동화로 미리 점수화되지 않은 주거용 출구입니다. 주거용 프록시는 실제 사용자의 연결로 표시되어 Cloudflare가 페이지를 제공하게 합니다. 도전 과제가 나타날 경우, 브라우저 지문을 IP만큼 일치시키는 것이 중요합니다; 2026년 Cloudflare를 우회하는 방법에 대한 가이드에서 경계가 어디에 있는지 다룹니다.
단축 경로: 채용 SERP 수직
실제로 원하는 것이 Indeed의 HTML이 아닌 노동 시장 데이터라면 더 깔끔한 경로가 있습니다. Google의 채용 수직은 Indeed 및 많은 다른 보드에서 게시물을 집계하며, SERP API는 제목, 회사, 위치, 게시 날짜 및 출처가 포함된 JSON으로 구문 분석된 채용 수직을 반환합니다: 유지할 CSS 선택자가 없고 Cloudflare와 싸울 필요가 없습니다. 여러 보드에 걸쳐 안정적인 구조화된 피드를 얻기 위해 일부 필드 수준의 제어를 포기하지만, 이는 일반적으로 집계 채용 분석에 더 나은 거래입니다. 이는 채용 보드 집계기를 사이트별 스크래퍼가 아닌 SERP 피드로 구축하는 것과 같은 이유입니다.
데이터의 용도
채용 검색을 넘어, 이 데이터는 실제 분석을 추진합니다: 역할 및 도시별 급여 벤치마킹, 특정 기술에 대한 수요 추적, 경쟁자 채용 신호(경쟁자가 새로운 팀을 구성하는 것은 전략적 신호입니다), 그리고 보강 — 회사의 공개 채용과 기업 정보를 결합하여 아웃바운드에 활용합니다. Glassdoor 급여 데이터와 결합하면 단일 소스보다 더 완전한 보상 그림을 얻을 수 있습니다.

자주 묻는 질문
Indeed 채용 공고를 합법적으로 스크래핑할 수 있나요?
채용 공고는 공개 데이터이며, 공개적으로 보이는 목록을 수집하는 것은 일반적으로 방어할 수 있지만, Indeed의 약관은 자동화된 접근을 제한하며 개인 데이터를 피하고 속도 제한을 준수해야 합니다. 많은 팀이 Indeed를 직접 스크래핑하는 대신 집계된 채용 SERP 수직을 사용하여 약관 문제를 피합니다. 이는 일반 정보이며 법적 조언이 아닙니다 — 대규모 프로젝트 전에 현재 약관을 검토하세요.
내 Indeed 스크래퍼가 계속 고장 나는 이유는 무엇인가요?
두 가지 이유가 있습니다. 첫째, Indeed는 해시된 CSS 클래스 이름을 회전시키므로 이에 고정된 선택자는 몇 주 내에 실패합니다 — 대신 data-testid 속성과 채용 키에 고정하세요. 둘째, Cloudflare는 IP가 플래그되면 도전 과제를 시작합니다; 주거용 출구와 일관된 브라우저 지문이 실제 페이지 로딩을 유지합니다. 둘 다 수정하면 스크래퍼가 안정화됩니다.
여러 국가에서 채용을 어떻게 스크래핑하나요?
Indeed는 각 국가에서 자체 하위 도메인(www.indeed.com, uk.indeed.com, de.indeed.com 등)으로 서비스를 제공합니다. 올바른 하위 도메인을 쿼리하고 해당 국가의 프록시 출구를 통해 라우팅하여 요청이 지리적으로 일관되도록 하세요 — 그렇지 않으면 잘못된 결과나 리디렉션된 결과를 받을 수 있습니다. 채용 SERP 수직도 하위 도메인을 관리하지 않으려면 국가 매개변수를 허용합니다.
Google 채용 SERP가 Indeed 스크래핑보다 나은가요?
집계된 노동 시장 분석을 위해서는 보통 그렇습니다. 채용 수직은 Indeed 및 많은 다른 보드에서 구조화된 JSON으로 게시물을 반환하며, 회전하는 선택자와 Cloudflare 도전 과제를 처리할 필요가 없습니다. Indeed 고유의 일부 필드를 잃지만, 안정적인 다중 소스 피드와 훨씬 적은 유지보수를 얻습니다. Indeed의 자체 페이지에 있는 필드가 필요할 때만 직접 스크래핑하세요.
Indeed는 지속 가능한 접근을 보상합니다: 안정적인 속성에 고정하고, 채용 키로 중복 제거하고, 10씩 페이지네이션하며, 주거용 IP로 Cloudflare가 페이지를 제공하도록 하세요. Indeed의 정확한 HTML이 아닌 노동 시장 신호만 필요할 때는 채용 SERP 수직이 JSON으로 제공합니다. 실제로 필요한 필드 제어 수준에 맞는 경로를 선택하세요.