크레이그리스트 목록 스크래핑 방법: 차량, 임대 및 일거리

크레이그리스트는 공격적인 IP 속도 제한으로 보호되는 데이터 금광입니다. 여기에는 도시별 URL 구조, 페이지당 120개 목록의 페이징 수학, 대부분의 사람들이 놓치는 RSS 단축키, 그리고 차단 목록에서 벗어나게 해주는 프록시 설정이 포함되어 있습니다.

크레이그리스트는 수백 개의 도시 사이트에 걸쳐 있는 중고차, 아파트 임대, 일거리, 판매 물품, 서비스 등 엄청난 양의 사용 가능한 공개 데이터를 보유하고 있습니다. 또한 크레이그리스트는 IP 주소별로 강력하게 속도 제한을 하기 때문에 초보자에게는 CAPTCHA와 IP 차단의 벽입니다. 좋은 소식은 사이트의 URL 구조가 간단하고 예측 가능하며, 대부분의 가이드가 건너뛰는 RSS 단축키가 있으며, 차단 문제는 거의 전적으로 IP 위생 문제라는 것입니다. 이 가이드는 도시별 URL 패턴, 페이징 수학, 파싱, RSS 경로, 그리고 스크래퍼가 차단 목록에서 벗어나게 해주는 프록시 설정을 다룹니다. 개인적 또는 연구 목적으로 스크래핑하고, 크레이그리스트의 약관을 존중하며, 이를 법적 조언이 아닌 일반 정보로 취급하십시오.

URL 패턴이 전부입니다

크레이그리스트는 도시 서브도메인과 카테고리 코드로 나뉘며, 나머지는 쿼리 매개변수입니다. 한 번 모양을 배우면 모든 도시와 섹션을 타겟팅할 수 있습니다: https://{city}.craigslist.org/search/{category}?query={q}. 카테고리 코드는 짧습니다 — sss는 모든 판매, cto는 소유자가 판매하는 차량, apa는 아파트, ggg는 일거리입니다. min_price, max_price 및 기타 필터를 매개변수로 추가하십시오. 페이지 매김은 s 매개변수를 사용하며, 각 페이지는 120개의 결과를 표시합니다 — 따라서 두 번째 페이지는 s=120, 세 번째 페이지는 s=240입니다.

import requests
from bs4 import BeautifulSoup

PROXY = "http://USER:PASS@rotating.quantumproxies.io:8000"
PROXIES = {"http": PROXY, "https": PROXY}
UA = ("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 "
      "(KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36")

def build_url(city, category, query, page=0, min_price=None, max_price=None):
    base = f"https://{city}.craigslist.org/search/{category}"
    params = [f"query={query}"]
    if min_price: params.append(f"min_price={min_price}")
    if max_price: params.append(f"max_price={max_price}")
    if page:      params.append(f"s={page * 120}")   # 120 results per page
    return base + "?" + "&".join(params)

url = build_url("minneapolis", "cto", "bmw", page=0, max_price=8000)
r = requests.get(url, headers={"User-Agent": UA}, proxies=PROXIES, timeout=20)

목록 파싱

검색 결과 행은 안정적인 클래스 세트로 표시됩니다 — 목록 블록은 .result-info이며, 내부에 .result-title, .result-price, .result-date가 있습니다. 모든 필드를 보호하십시오, 모든 목록에 가격이 있는 것은 아니기 때문입니다:

def parse_listings(html):
    soup = BeautifulSoup(html, "html.parser")
    out = []
    for row in soup.select(".result-info"):
        title_el = row.select_one(".result-title")
        price_el = row.select_one(".result-price")
        date_el  = row.select_one(".result-date")
        if not title_el:
            continue
        out.append({
            "title": title_el.get_text(strip=True),
            "url":   title_el.get("href"),
            "price": price_el.get_text(strip=True) if price_el else None,
            "date":  date_el.get("datetime") if date_el else None,
        })
    return out

listings = parse_listings(r.text)
print(len(listings), "listings on this page")

더 풍부한 기록 — 차량의 주행 거리, 임대의 침실 수 — 각 목록 URL을 따라가서 세부 페이지를 파싱하십시오. 이는 요청 수를 두 배로 늘리므로, 정확히 이때 속도 조절과 회전이 중요해집니다.

크레이그리스트 검색 URL을 도시 서브도메인, 카테고리 코드, 쿼리 및 s 페이지 매개변수로 나누는 다이어그램
크레이그리스트 URL은 완전히 예측 가능합니다: 도시 서브도메인, 카테고리 코드, 그 다음 쿼리 및 120단계 s 매개변수.

대부분의 가이드가 건너뛰는 RSS 단축키

크레이그리스트는 일반적인 공개 API가 없지만, 검색 결과에 대한 RSS 피드를 노출합니다 — 검색 URL에 &format=rss를 추가하면 HTML 대신 구조화된 XML 피드를 얻을 수 있습니다. 이는 가볍고, 전체 결과 페이지를 반복적으로 로드하는 것보다 봇 방지 휴리스틱을 덜 유발하며, 모니터링에 이상적입니다: 저장된 검색을 일정에 따라 폴링하고 새 항목을 위해 차이를 확인하십시오. HTML 페이지보다 적은 필드(제목, 링크, 타임스탬프)를 반환하므로 신선도 모니터링에 사용하고 가격 및 세부 정보가 필요할 때 HTML로 돌아가십시오.

import feedparser

# Any Craigslist search becomes a feed with &format=rss
feed_url = build_url("sfbay", "apa", "loft", max_price=3500) + "&format=rss"
raw = requests.get(feed_url, headers={"User-Agent": UA}, proxies=PROXIES, timeout=20)
feed = feedparser.parse(raw.content)

for entry in feed.entries[:5]:
    print(entry.updated, entry.title, entry.link)

크레이그리스트가 당신을 차단하는 이유와 차단되지 않는 방법

크레이그리스트는 여러 방어를 쌓아두지만, 그들은 하나의 뿌리를 공유합니다: IP 주소별로 요청을 추적하고 너무 많이 때리는 주소를 차단합니다. 구체적인 조치는 IP 속도 제한, 의심스러운 트래픽에 대한 CAPTCHA 도전, User-Agent 모니터링, 세션 추적, 임시 IP 차단입니다. 모든 것은 하나의 끊임없는 기계가 아닌 많은 일반 방문자처럼 보임으로써 극복됩니다.

차단은 IP 기반이기 때문에 종료 IP가 대부분의 작업을 수행하고 있습니다. 깨끗한 주거용 프록시 풀은 실제 가정 연결처럼 보이며, 요청별 회전은 다도시 크롤링을 매우 얇게 분산시켜 크레이그리스트의 IP별 카운터가 결코 작동하지 않게 만듭니다. 여러 도시에서 수집하고 있다면, 429 속도 제한 수정에 대한 가이드가 속도 조절 및 동시성 예산 측면을 다루고 있으며, 차단 방지 체크리스트가 이를 모두 연결합니다.

깨끗한 주거용 IP로 크레이그리스트 스크래핑

도시 간 확장

크레이그리스트 데이터의 진정한 힘은 도시 간 비교에 있습니다 — 같은 중고차나 임대가 여러 도시에서 가격이 매겨지는 것입니다. 도시 목록을 반복하고, 도시별로 새로운 회전 종료를 바인딩하고, 동시성을 제한하고, 모든 기록과 함께 도시를 저장하십시오. 특히 차량 및 임대 연구를 위해서는 동일한 패턴이 비교 파이프라인에 공급됩니다; 원시 목록을 시장 신호로 변환하는 방법에 대한 자동차 목록 스크래핑부동산 데이터 가이드를 참조하십시오.

크레이그리스트의 IP 속도 제한 및 CAPTCHA와 같은 방어를 주거용 회전 및 속도 조절과 같은 수정 사항에 매핑하는 체크리스트
모든 크레이그리스트 방어는 IP 및 속도 조절 문제입니다 — 주거용 종료를 회전하고 초당 1-2개의 요청 아래로 유지하십시오.

자주 묻는 질문

크레이그리스트를 스크래핑할 수 있습니까?

예 — 공개 검색 및 목록 페이지는 스크래핑할 수 있으며, 크레이그리스트는 검색을 위한 RSS 피드도 노출합니다. 장애물은 파싱이 아니라 공격적인 IP별 속도 제한입니다. 주거용 IP를 회전시키고, 요청 속도를 초당 1-2개로 조절하면 차량, 임대, 일거리 및 판매 데이터를 안정적으로 수집할 수 있습니다. 크레이그리스트의 약관을 존중하고 공개 데이터만 스크래핑하십시오.

크레이그리스트에 API가 있습니까?

일반적인 공개 데이터 API는 없지만, 모든 검색 URL에 &format=rss를 추가하면 RSS 피드를 반환할 수 있습니다. 이는 제목, 링크 및 타임스탬프가 포함된 구조화된 XML 피드를 제공하여 새로운 목록을 모니터링하는 데 적합합니다 — HTML 페이지는 가격 및 설명과 같은 더 많은 필드를 포함합니다.

크레이그리스트 스크래핑 시 IP 차단을 피하는 방법은 무엇입니까?

크레이그리스트는 IP 속도로 차단하므로 수정 사항은 모두 부하를 분산하고 느리게 하는 것입니다: 요청별로 주거용 IP를 회전시키고, 지터를 추가하여 초당 1-2개의 요청으로 유지하며, User-Agent를 회전시키고, 도시별로 새로운 세션을 사용하며, CAPTCHA나 403을 보는 즉시 물러서십시오. 데이터센터 IP가 한 도시를 때리면 가장 빨리 차단됩니다.

크레이그리스트 페이지 매김은 어떻게 작동합니까?

크레이그리스트는 페이지당 120개의 결과를 표시하며, s 쿼리 매개변수를 오프셋으로 사용하여 페이지를 매깁니다. 첫 번째 페이지는 s를 생략하고, 두 번째 페이지는 s=120, 세 번째 페이지는 s=240입니다. 120단계로 증가시키다가 120개 미만의 결과를 반환하는 페이지가 나오면 끝입니다.

크레이그리스트는 읽기 쉽고 차단되기 쉬운 사이트입니다 — 두 번째 문제는 전적으로 IP 위생에 관한 것입니다. URL 패턴을 확립하고, 모니터링을 위해 RSS를 사용하고, 120단계로 페이지를 넘기고, 모든 것을 인간 속도로 회전하는 주거용 IP를 통해 라우팅하십시오. 그렇게 하면 CAPTCHA가 단순히 나타나지 않습니다.

회전하는 주거용 프록시로 시작하십시오