자동차 매물 스크래핑: Cars.com, Autotrader 및 CarGurus에서 가격 정보 수집하기

딜러 가격 정보는 Cars.com, Autotrader 및 CarGurus에 걸쳐 존재하며, 동일한 차량이 우편번호에 따라 다르게 가격이 매겨지고 어디에나 교차 게시됩니다. 이를 스크래핑하고 VIN으로 중복 제거하며, 봇 방어벽을 우회하는 방법을 소개합니다.

딜러 가격 정보는 한 곳에만 존재하지 않습니다. 동일한 중고차가 Cars.com, Autotrader 및 CarGurus에 동시에 게시되며, 구매자의 우편번호에 따라 다르게 가격이 매겨지고 각 사이트는 봇 방어로 페이지를 보호합니다. 이를 잘 스크래핑하는 것은 페이지를 파싱하는 것보다 세 가지에 더 중점을 둡니다: 모든 매물에 실제로 도달할 수 있도록 검색을 필터링하고, VIN으로 소스 간 동일한 차량을 중복 제거하며, 소진된 IP 없이 방어벽을 우회하는 것입니다. 이 가이드는 이 세 가지를 모두 다루며, 모든 주요 매물 사이트에 맞게 코드를 조정할 수 있습니다.

자동차 매물이 제공하는 것

각 차량 매물은 파싱 후 밀도 높은 기록을 제공합니다: 연도, 제조사, 모델 및 트림; 가격 및 주행 거리; VIN; 차체 유형, 구동 방식, 연료, 변속기, 실린더 및 문 수; 내부 및 외부 색상; 재고 번호; 기능 목록; 이미지; 그리고 딜러 세부 정보와 거래 평가가 있는 사이트에서는 거래 평가까지. 이는 각 행당 전체 평가 데이터셋입니다. 파이프라인을 구축할 때의 주요 필드는 가격, 주행 거리, VIN 및 딜러입니다 — 나머지는 보강입니다.

먼저 필터링: 모든 매물에 도달하기

매물 사이트는 고정된 페이지 크기(일반적으로 페이지당 20개)로 페이지를 나누고 단일 검색이 얼마나 깊이 갈 수 있는지를 제한합니다 — 종종 총 1,000개의 결과 정도입니다. 검색이 그보다 많은 차량과 일치하면, 추가적인 매물은 페이지 나누기를 통해 도달할 수 없습니다. 해결책은 세분화입니다: 광범위한 검색을 제조사, 모델, 연도 범위, 가격대 또는 우편번호별로 좁혀서 각 검색이 제한을 넘지 않도록 하고, 결과를 합칩니다. Cars.com은 유용하게도 이 모든 것을 URL에 인코딩하므로, 프로그래밍적으로 검색을 구축할 수 있습니다.

from urllib.parse import urlencode

def search_url(zip_code, make="", model="", max_price="", year_min=""):
    params = {
        "stock_type": "used",
        "makes[]": make,
        "models[]": model,
        "list_price_max": max_price,
        "year_min": year_min,
        "maximum_distance": "all",
        "zip": zip_code,
        "page_size": 20,
        "sort": "listed_at_desc",
    }
    return "https://www.cars.com/shopping/results/?" + urlencode(params)

print(search_url("10001", make="toyota", model="camry", year_min=2020))
자동차 매물 스크래핑의 통계 다이어그램: 페이지당 20개 매물, 검색당 1000개 도달 가능, 2-5초 지연, 사이트 간 중복 제거 키로서의 VIN
단일 검색은 약 1,000개의 결과에서 정점을 찍습니다 — 나머지에 도달하려면 제조사, 연도 또는 우편번호별로 세분화하고, 요청 속도를 조절하여 탐지되지 않도록 하세요.

방어벽을 우회하기: 주거용 프록시

Cars.com은 Cloudflare 뒤에 있으며, 다른 자동차 사이트는 Imperva와 hCaptcha 또는 reCAPTCHA를 사용하여 부하가 걸릴 때 작동합니다. 데이터센터 IP가 매물 페이지를 두드리면 빠르게 도전받습니다. 실제 ISP의 주거용 프록시는 일반 쇼핑객처럼 보이며, 이를 회전시키면 요청이 분산되어 단일 주소가 속도 제한을 초과하지 않습니다. 요청 간 2-5초 지연을 유지하세요 — 속도 조절은 IP만큼 중요합니다. 소규모, 가끔의 요청에는 데이터센터 풀로 충분하지만, 대규모의 지속적인 모니터링에는 주거용이 완료되는 실행과 CAPTCHA에서 멈추는 실행의 차이를 만듭니다.

import requests, time, random

PROXY = "http://USER:PASS@gate.quantumproxies.io:8000"
proxies = {"http": PROXY, "https": PROXY}
HEADERS = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"}

def fetch(url):
    r = requests.get(url, proxies=proxies, headers=HEADERS, timeout=20)
    r.raise_for_status()
    time.sleep(random.uniform(2, 5))   # polite, and harder to fingerprint
    return r.text

목표가 JavaScript로 매물을 렌더링하거나 지속적인 CAPTCHA를 던진다면, 실제 브라우저 지문을 가지고 있고 봇 방어 계층을 해결해주는 Scraper API가 자체 브라우저 팜을 유지하는 것보다 덜 취약합니다. 2026년에 Cloudflare를 우회하는 방법에 대한 우리의 가이드에서 그 경계가 어디에 있는지 확인할 수 있습니다.

자동차 매물 사이트를 위한 주거용 프록시 얻기

소스 간 VIN으로 중복 제거

자동차 데이터에서 가장 유용한 열은 VIN입니다. 딜러는 동일한 차량을 모든 마켓플레이스에 교차 게시하기 때문에, 원시 스크래핑 데이터는 별개의 매물처럼 보이는 중복으로 가득합니다. VIN은 물리적 차량에 대한 전 세계적으로 고유한 식별자이므로, 이를 키로 사용하면 중복을 하나의 기록으로 축소할 수 있으며, 동일한 차량이 Cars.com, Autotrader 및 CarGurus에서 어떻게 가격이 매겨지는지 또는 어떤 딜러에 의해 매겨지는지를 비교할 수 있습니다. VIN당 최저 가격을 유지하거나, 측정하는 것에 따라 소스로 태그된 모든 가격을 유지하세요.

def dedupe_by_vin(rows):
    best = {}
    for r in rows:
        vin = r.get("vin")
        if not vin:
            continue
        price = int(r["price"])
        if vin not in best or price < int(best[vin]["price"]):
            best[vin] = r          # keep the cheapest listing per car
    return list(best.values())
자동차 매물 파이프라인의 흐름 다이어그램: 필터링된 검색 URL 구축, Cloudflare를 우회하는 주거용 프록시를 통해 가져오기, 매물 필드 파싱, VIN으로 중복 제거하여 차량을 비교하고 매물을 두 번 세지 않기
필터링하고, 주거용 출구를 통해 가져오고, 파싱한 다음 VIN으로 중복을 축소하여 매물을 두 번 세지 않고 차량을 비교하세요.

지역 가격: 동일한 차량, 다른 우편번호

자동차 가격은 지역적입니다. 동일한 모델이 검색하는 우편번호에 따라 다른 가격과 재고를 보여주며, 이는 지역에 따라 딜러와 수요가 다르기 때문입니다. 그 차이를 포착하기 위해, 우편번호 세트를 훑고, 사이트가 방문자의 위치에 따라 개인화하는 경우, 각 요청을 해당 지역의 출구를 통해 라우팅하세요. 국가 및 도시 타겟팅이 가능한 주거용 풀은 지역 구매자가 보는 가격을 볼 수 있게 해주며, 이는 차익 거래, 딜러 벤치마킹 또는 한 시장에 치우치지 않은 평가 모델을 구축하는 데 필수적입니다.

zips = ["10001", "90001", "60601", "77001"]  # NY, LA, Chicago, Houston
spread = {}
for z in zips:
    url = search_url(z, make="toyota", model="camry", year_min=2021)
    rows = parse_listings(fetch(url))          # exit geo-matched to the ZIP
    spread[z] = [int(r["price"]) for r in rows]

# now compare median price by market
for z, prices in spread.items():
    prices.sort()
    print(z, "median", prices[len(prices)//2])

이는 경쟁자 가격 모니터링부동산 데이터 수집의 위치 우선 패턴과 동일합니다 — 가격이 구매자의 위치에 따라 달라지는 곳에서는 지리적 타겟팅 출구가 필수적입니다.

경매 및 도매 소스

소매 매물 사이트는 딜러가 요구하는 것을 알려주고, Copart와 같은 경매 플랫폼은 도매 수준에서 실제로 차량이 거래되는 가격을 알려줍니다 — 가격 모델의 나머지 절반입니다. 이러한 사이트는 더 강력하게 방어됩니다: 예를 들어 Copart는 행동 지문을 사용한 Imperva 웹 보호를 실행하며, 요청량이 많을 때 hCaptcha 또는 reCAPTCHA 도전이 나타납니다. 페이지 나누기도 더 엄격하여 — 페이지당 20대 차량에 약 50페이지의 하드 리미트가 있어, 단일 검색은 대략 1,000개 로트에서 제한됩니다. 전체 인벤토리에 도달하려면 소매 사이트와 마찬가지로 제조사, 모델, 연도 범위, 경매장 또는 상태별로 쿼리를 세분화하고 각 세그먼트를 자체적으로 실행해야 합니다.

이 플랫폼은 JavaScript로 결과와 페이지 나누기를 로드하고 의심스러운 트래픽에 도전하기 때문에, 주거용 IP와 최소 요청 간 2-5초 간격을 원합니다. 데이터센터 프록시는 소규모, 가끔의 요청을 처리하며, 지속적인 것은 주거용 출구에 속합니다. 그 보상은 실제 신호입니다: 입찰 기록, 판매 상태 및 로트 상태는 소매 요구 가격만으로는 제공할 수 없는 수요 예측 및 수출입 분석을 제공합니다.

모니터링, 단순히 한 번 스크래핑하지 마세요

일회성 덤프는 매물이 매일 바뀌는 시장에서 즉시 구식이 됩니다. 지속 가능한 패턴은 목표 검색을 스냅샷하고 연속 실행을 비교하는 예약된 스크래핑입니다 — 새로운 매물, 가격 하락, 판매된 차량. 각 행을 VIN으로 키로 사용하여 동일한 차량의 가격 변화를 명확히 하고, 모든 스냅샷에 타임스탬프를 찍으면 트렌드할 수 있는 시계열을 얻을 수 있습니다: 특정 모델이 얼마나 빨리 감가상각되는지, 어떤 딜러가 가격을 인하하는지, 어디에 재고가 쌓이고 있는지. 이러한 예약된 실행을 회전하는 주거용 IP를 통해 라우팅하여 동일한 주소에서의 일일 작업이 점차 차단되지 않도록 하세요.

자주 묻는 질문

Cars.com과 Autotrader를 스크래핑할 수 있나요?

예 — 매물 페이지는 공개적으로 이용 가능한 차량 데이터를 보여줍니다. 실질적인 도전은 봇 방어입니다: Cars.com은 Cloudflare를 사용하고, 다른 사이트는 CAPTCHA가 있는 Imperva를 사용합니다. 주거용 프록시, 현실적인 헤더 및 요청 간 2-5초 지연이 스크래핑을 유지합니다. 각 사이트의 서비스 약관을 존중하고 개인 데이터를 수집하지 마세요.

자동차 매물 스크래핑 시 차단을 피하는 방법은?

주거용 IP를 회전하여 단일 주소가 너무 많은 요청을 하지 않도록 하고, 요청을 2-5초 무작위 지연으로 조절하며, 실제 브라우저 User-Agent를 보내고, 큰 검색을 더 작은 검색으로 세분화하여 수천 개를 페이지로 나누지 마세요. CAPTCHA가 지속되면, 봇 방어 계층과 JavaScript 렌더링을 처리하는 Scraper API로 전환하세요.

스크래핑 시 왜 중복 차량이 발생하나요?

딜러는 동일한 차량을 여러 마켓플레이스에 교차 게시하므로, 하나의 물리적 차량이 여러 매물로 나타납니다. 사이트와 상관없이 차량을 고유하게 식별하는 VIN으로 중복을 제거하세요. VIN을 키로 사용하면 중복을 소스 간 동일한 차량의 가격 비교로 전환하여 부풀려진 수치를 방지합니다.

자동차 가격이 정말로 지역에 따라 달라지나요?

예. 재고와 가격은 지역에 따라 다르며, 많은 사이트가 검색자의 우편번호에 결과를 개인화합니다. 실제 차이를 포착하기 위해 여러 우편번호를 검색하고, 각 요청을 해당 지역의 출구를 통해 라우팅하여 지리적 타겟팅 주거용 프록시를 사용하여 지역 가격을 확인하세요, 전국적으로 왜곡된 뷰 대신에.

자동차 매물 스크래핑은 모든 차량에 도달하는 것(약 1,000개 결과 제한을 세분화), 봇 방어벽을 우회하는 것(회전하는 주거용 IP, 정중한 속도 조절), VIN으로 중복을 축소하는 것, 그리고 위치 타겟팅 출구로 지역 차이를 포착하는 것으로 귀결됩니다. 가격, 주행 거리, VIN 및 딜러를 중심으로 파이프라인을 구축하면 주요 마켓플레이스 전반에 걸쳐 딜러 가격 정보를 얻을 수 있습니다.

QuantumProxies로 자동차 매물 스크래핑 시작하기