구글 쇼핑 가격 스크래핑을 시작하기 전에 알아야 할 것
2026년에 구글 쇼핑 가격 스크래핑을 하려면 먼저 가장 중요한 기술적 분기점을 이해해야 합니다. 구글이 제공하는 Content API for Shopping은 자사 제품 피드 관리용으로 설계되었으며, 경쟁사의 가격이나 판매자 데이터를 반환하지 않습니다. 즉, 타사 경쟁 가격을 수집하려면 tbm=shop SERP HTML을 직접 파싱하거나 /shopping/product/ 제품 상세 페이지를 크롤링해야 합니다.
이 가이드는 가격 분석가와 경쟁 정보 엔지니어를 대상으로, HTML 기반 구글 쇼핑 제품 데이터 수집의 전 과정을 다룹니다. URL 패턴, CSS 셀렉터, 프록시 구성, 소프트 블록 감지, 윤리적 고려사항까지 실무에 바로 적용할 수 있는 내용을 제공합니다.
기술적 배경: 왜 이 문제가 존재하는가
구글 쇼핑은 검색 결과 페이지와 제품 상세 페이지 두 단계로 구성됩니다. 검색 결과는 https://www.google.com/search?tbm=shop&q=키워드 형태로 반환되며, 각 결과는 제품 카드 컨테이너에 들어 있습니다. 제품 상세 페이지는 https://www.google.com/shopping/product/PRODUCT_ID 경로를 사용하며, 여기서 개별 판매자 오퍼와 가격 비교 패널을 확인할 수 있습니다.
문제는 구글이 이 데이터를 공식 API로 경쟁사 분석 용도로 제공하지 않는다는 점입니다. Google Content API for Shopping 문서에 따르면, 이 API는 머천트 계정에 연결된 제품 피드의 관리와 보고만 지원합니다. 따라서 시장 가격 모니터링, 경쟁사 동향 분석, 가격 비교 플랫폼 구축을 원하는 팀은 HTML 파싱 외에 마땅한 대안이 없습니다.
더 큰 문제는 구글의 강력한 안티봇 인프라입니다. 단일 IP에서 짧은 시간에 여러 요청을 보내면 sorry/index 리다이렉트나 reCAPTCHA 챌린지로 이어지며, 반복되면 IP가 장시간 차단됩니다. 이것이 프록시가 필수적인 이유입니다.
구글의 안티봇 스택 이해하기
구글은 다층 안티봇 시스템을 운영합니다. 각 층을 이해하면 차단을 피하는 전략을 세울 수 있습니다.
1. reCAPTCHA 및 챌린지 페이지
의심스러운 트래픽이 감지되면 구글은 reCAPTCHA 챌린지를 반환합니다. 이 페이지의 URL은 보통 https://www.google.com/sorry/index?continue=... 형태이며, HTTP 상태 코드 429 또는 503을 동반합니다. 이 상태를 감지하면 즉시 해당 IP의 요청을 중단하고 새 IP로 전환해야 합니다.
2. IP별 레이트 리미트
구글은 IP별로 매우 공격적인 레이트 리미트를 적용합니다. 실무 경험상 데이터센터 IP는 분당 10~20 요청 이후 차단되는 경우가 많으며, 구글의 크롤링 가이드라인에서 권장하는 크롤러 예절과 유사한 원칙이 적용됩니다. 레지덴셜 IP는 상대적으로 더 높은 허용치를 보이지만, 여전히 무제한은 아닙니다.
3. 동적 HTML 렌더링
구글 쇼핑 결과는 JavaScript 실행 후에야 일부 요소가 로드됩니다. requests 기반 단순 파싱으로는 충분한 데이터를 얻을 수 없는 경우가 있어, 필요에 따라 헤드리스 브라우저(Playwright, Puppeteer)를 병행해야 합니다.
URL 패턴과 CSS 셀렉터
구글 쇼핑 검색 결과의 기본 URL 패턴은 다음과 같습니다:
https://www.google.com/search?tbm=shop&q=아이폰+15+프로&gl=us&hl=en
주요 파라미터:
tbm=shop— 쇼핑 검색 탭 강제q=— 검색 키워드gl=us— 지역(국가 코드)hl=en— 언어num=100— 결과 수 (최대 100)
결과 페이지의 주요 CSS 셀렉터:
| 요소 | CSS 셀렉터 | 설명 |
|---|---|---|
| 제품 카드 컨테이너 | .sh-dgr__content | 개별 제품 결과 블록 |
| 제품 결과 그리드 | .sh-pr__product-results | 전체 결과 컨테이너 |
| 가격 노드 | .a8Pemb | 표시 가격 텍스트 |
| 제품 제목 | h3.t16oLo | 제품명 |
| 판매자명 | .a2zPdd | 판매자 이름 |
| 평점 | .YzYRVb | 별점 (예: 4.5) |
| 리뷰 수 | .ZkOoUe | 리뷰 개수 |
제품 상세 페이지(/shopping/product/)에서는 판매자 오퍼 패널이 별도로 렌더링됩니다. XPath를 사용하면 다음과 같이 접근할 수 있습니다:
//div[contains(@class, 'sh-os__offer')]//span[contains(@class, 'g9WBQb')]
이 셀렉터들은 구글이 주기적으로 HTML 구조를 변경하기 때문에 안정적이지 않습니다. 프로덕션 환경에서는 다중 폴백 셀렉터와 정규식 기반 추출을 병행하는 것이 권장됩니다.
지역별 가격과 레지덴셜 프록시의 중요성
구글 쇼핑은 사용자의 지역에 따라 다른 판매자와 가격, 통화를 표시합니다. 미국 쇼퍼에게는 USD 가격의 미국 판매자가, 독일 쇼퍼에게는 EUR 가격의 유럽 판매자가 우선 노출됩니다. 이는 구글 쇼핑 가격 스크래핑에서 지역 타겟팅이 핵심임을 의미합니다.
URL 파라미터 gl과 hl만으로는 충분하지 않습니다. 구글은 IP 주소를 기준으로 지역을 보정하므로, 미국 가격을 수집하려면 미국 IP에서, 독일 가격을 수집하려면 독일 IP에서 요청해야 합니다. 특히 도시 단위 가격 차이가 중요한 경우(예: 배송비 포함 가격 비교)에는 도시 수준 지역 타겟팅이 필요합니다.
ProxyHat 레지덴셜 프록시는 사용자명에 국가 및 도시 플래그를 포함하여 지역을 지정할 수 있습니다:
user-country-US— 미국 IPuser-country-DE-city-berlin— 독일 베를린 IPuser-country-JP-city-tokyo— 일본 도쿄 IP
데이터센터 프록시로는 구글 쇼핑에서 안정적인 수집이 거의 불가능합니다. 구글은 데이터센터 IP 대역을 식별하고 즉시 차단하는 경향이 있습니다. 레지덴셜 프록시는 실제 ISP IP를 사용하므로 차단 확률이 현저히 낮습니다. ProxyHat 위치 목록에서 지원 국가와 도시를 확인할 수 있습니다.
ProxyHat을 활용한 Python 스크래핑 구현
이제 실제 코드를 살펴봅시다. 다음 예제는 requests와 BeautifulSoup를 사용하여 구글 쇼핑 검색 결과에서 제품명, 가격, 판매자, 평점을 추출합니다.
import requests
from bs4 import BeautifulSoup
import time
import random
# ProxyHat 레지덴셜 프록시 설정 (미국 IP)
proxy_host = "gate.proxyhat.com"
proxy_port = "8080"
proxy_user = "user-country-US"
proxy_pass = "YOUR_PASSWORD"
proxy_url = f"http://{proxy_user}:{proxy_pass}@{proxy_host}:{proxy_port}"
proxies = {
"http": proxy_url,
"https": proxy_url,
}
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
"Accept-Language": "en-US,en;q=0.9",
}
def scrape_google_shopping(query, gl="us", hl="en", num=20):
url = f"https://www.google.com/search?tbm=shop&q={query}&gl={gl}&hl={hl}&num={num}"
try:
resp = requests.get(url, proxies=proxies, headers=headers, timeout=15)
except requests.exceptions.RequestException as e:
print(f"요청 실패: {e}")
return []
# 소프트 블록 감지
if resp.status_code == 429 or "sorry/index" in resp.url:
print(f"소프트 블록 감지: status={resp.status_code}, url={resp.url}")
return None # None 반환 = IP 교체 필요
soup = BeautifulSoup(resp.text, "html.parser")
results = []
# 제품 카드 추출
cards = soup.select(".sh-dgr__content")
for card in cards[:5]: # 상위 5개만 (예시)
title_el = card.select_one("h3")
price_el = card.select_one(".a8Pemb")
seller_el = card.select_one(".a2zPdd")
rating_el = card.select_one(".YzYRVb")
result = {
"title": title_el.get_text(strip=True) if title_el else None,
"price": price_el.get_text(strip=True) if price_el else None,
"seller": seller_el.get_text(strip=True) if seller_el else None,
"rating": rating_el.get_text(strip=True) if rating_el else None,
}
results.append(result)
return results
# 실행 예제
if __name__ == "__main__":
data = scrape_google_shopping("iPhone 15 Pro 128GB")
if data is None:
print("IP 교체 필요 — 블록 감지")
elif len(data) == 0:
print("결과 없음 — 셀렉터 확인 필요")
else:
for item in data:
print(f"제품: {item['title']}")
print(f"가격: {item['price']}")
print(f"판매자: {item['seller']}")
print(f"평점: {item['rating']}")
print("---")
샘플 응답(트렁케이트됨):
제품: Apple iPhone 15 Pro 128GB - Titanium Blue
가격: $999.00
판매자: Best Buy
평점: 4.7
---
제품: Apple iPhone 15 Pro 128GB Unlocked
가격: $949.99
판매자: Amazon
평점: 4.6
---
독일 가격 수집 예제
독일 가격을 수집하려면 프록시 국가와 URL 파라미터를 함께 변경해야 합니다:
# 독일 베를린 IP로 전환
proxy_user_de = "user-country-DE-city-berlin"
proxy_url_de = f"http://{proxy_user_de}:{proxy_pass}@{proxy_host}:{proxy_port}"
proxies_de = {"http": proxy_url_de, "https": proxy_url_de}
headers_de = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
"Accept-Language": "de-DE,de;q=0.9",
}
url_de = "https://www.google.com/search?tbm=shop&q=iPhone+15+Pro+128GB&gl=de&hl=de&num=20"
resp = requests.get(url_de, proxies=proxies_de, headers=headers_de, timeout=15)
결과는 EUR 가격과 독일 판매자가 우선 표시됩니다. 자세한 프록시 설정은 ProxyHat 문서를 참조하세요.
페이지네이션, 배치 처리, 소프트 블록 감지
페이지네이션
구글 쇼핑 검색 결과는 일반적으로 첫 페이지에 20~40개의 제품 카드를 표시합니다. 추가 결과는 start 파라미터로 페이지네이션할 수 있습니다:
urls = [
f"https://www.google.com/search?tbm=shop&q={query}&gl={gl}&hl={hl}&start={i*20}"
for i in range(5) # 5페이지 = 최대 100개 결과
]
하지만 구글 쇼핑은 일반 검색보다 페이지네이션 한계가 더 빨리 옵니다. 보통 3~4페이지(60~80개 결과) 이후에는 결과가 급격히 줄어들거나 빈 페이지가 반환됩니다.
쿼리 배치와 랜덤 딜레이
대량의 키워드를 수집할 때는 배치 처리와 랜덤 딜레이가 필수입니다. 고정된 딜레이(예: 정확히 2초)는 봇 패턴으로 감지될 수 있으므로, 3~8초 사이의 랜덤 대기를 사용하세요:
import random
import time
queries = ["iPhone 15 Pro", "Galaxy S24 Ultra", "Pixel 8 Pro"]
for q in queries:
data = scrape_google_shopping(q)
if data is None:
# 블록 감지 — IP 교체 후 대기
time.sleep(random.uniform(30, 60))
continue
# 결과 저장 로직
save_results(q, data)
# 랜덤 딜레이
delay = random.uniform(3, 8)
time.sleep(delay)
소프트 블록 감지
하드 CAPTCHA가 나타나기 전에 소프트 블록 신호를 감지하면 IP를 선제적으로 교체할 수 있습니다. 주요 신호:
- HTTP 429 (Too Many Requests)
- HTTP 503 (Service Unavailable)
- 응답 URL에
sorry/index포함 - 결과 수가 갑자기 0으로 떨어짐 (정상 키워드인데)
- 응답 본문에 "unusual traffic" 문구 포함
이 신호들 중 하나라도 감지되면 즉시 해당 세션을 중단하고 새 IP로 전환하세요. ProxyHat의 세션 ID 기능을 사용하면 각 요청마다 새 IP를 강제할 수 있습니다:
# 매 요청마다 새 IP
proxy_user_rotate = f"user-country-US-session-{random.randint(1, 100000)}"
proxy_url = f"http://{proxy_user_rotate}:{proxy_pass}@{proxy_host}:{proxy_port}"
프록시 유형 비교: 어떤 것을 선택해야 하는가
| 프록시 유형 | 구글 쇼핑 적합성 | 차단 위험 | 속도 | 가격대 |
|---|---|---|---|---|
| 데이터센터 | 낮음 — 빠른 차단 | 매우 높음 | 빠름 (<100ms) | 저렴 |
| 레지덴셜 | 높음 — 권장 | 낮음 | 중간 (200~500ms) | 중간 |
| 모바일 | 매우 높음 — 최고 | 매우 낮음 | 느림 (500ms~2s) | 비쌈 |
대부분의 가격 모니터링 사용 사례에서는 레지덴셜 프록시가 비용과 안정성의 최적 균형점입니다. ProxyHat 요금제에서 레지덴셜, 모바일, 데이터센터 프록시 가격을 비교할 수 있습니다.
윤리와 이용약관
구글 쇼핑 스크래핑을 실행하기 전에 법적, 윤리적 고려사항을 반드시 검토해야 합니다.
공개 데이터 vs 비공개 데이터
구글 쇼핑의 검색 결과는 로그인 없이 접근 가능한 공개 데이터입니다. 하지만 구글의 서비스 약관은 자동화된 수집을 제한하는 조항을 포함하고 있습니다. 미국에서는 hiQ Labs v. LinkedIn 판결이 공개 데이터 스크래핑의 합법성을 일부 지지했지만, Computer Fraud and Abuse Act (CFAA)의 적용은 사례마다 다릅니다.
GDPR과 개인정보
가격 데이터 자체는 개인정보가 아니지만, 리뷰 작성자 정보나 사용자 식별 가능 데이터를 수집하는 경우 EU GDPR이 적용될 수 있습니다. 가격, 판매자명, 제품명 등 비식별 데이터만 수집하는 것이 안전합니다.
언제 공식 파트너십을 고려해야 하는가
대규모 엔터프라이즈 사용 사례에서는 구글의 공식 Shopping 파트너십이나 SERP API 라이선스가 더 적합할 수 있습니다. 이는 비용이 발생하지만 차단 위험이 없고 데이터 품질이 보장됩니다. 스타트업이나 중소 규모 경쟁 분석에서는 프록시 기반 HTML 파싱이 비용 효율적입니다.
ProxyHat 설정 가이드
ProxyHat을 사용한 구글 쇼핑 스크래핑 환경 구성 단계:
- ProxyHat 대시보드에서 계정 생성 및 레지덴셜 프록시 구독
- 대시보드에서 사용자명과 비밀번호 확인
- 사용자명에 지역 플래그 추가:
user-country-US - 게이트웨이:
gate.proxyhat.com:8080(HTTP) 또는:1080(SOCKS5) - 코드에 프록시 설정 적용 후 테스트
- 소프트 블록 감지 로직 구현
- 배치 처리 스케줄러 구축 (cron, Airflow 등)
웹 스크래핑 사용 사례에 대한 자세한 내용은 웹 스크래핑 사용 사례 페이지를, SERP 추적에 대한 내용은 SERP 추적 사용 사례 페이지를 참조하세요.
주요 요약 (Key Takeaways)
- Content API는 경쟁사 데이터에 사용할 수 없습니다. HTML 파싱이 유일한 실용적 경로입니다.
- 레지덴셜 프록시 + 도시 단위 지역 타겟팅이 필수입니다. 데이터센터 IP는 구글 쇼핑에서 즉시 차단됩니다.
- 소프트 블록 신호를 선제적으로 감지하세요. 429 상태 코드, sorry/index 리다이렉트, 결과 수 급감이 주요 신호입니다.
- 랜덤 딜레이(3~8초)와 세션 로테이션을 병행하세요. 고정 패턴은 봇으로 감지됩니다.
- 공개 가격 데이터만 수집하고, 개인정보는 피하세요. CFAA와 GDPR을 항상 염두에 두세요.
FAQ
구글 쇼핑 가격 스크래핑이란 무엇인가요?
구글 쇼핑 가격 스크래핑은 구글 쇼핑 검색 결과 페이지(tbm=shop)와 제품 상세 페이지에서 제품 가격, 판매자 정보, 평점 등의 데이터를 자동화된 방식으로 수집하는 작업입니다. Content API for Shopping이 자사 제품 피드 관리용만 제공되기 때문에, 경쟁사 가격 데이터를 얻으려면 HTML 파싱이 필요합니다.
구글 쇼핑 스크래핑에 프록시가 필요한 이유는?
구글은 IP별로 매우 공격적인 레이트 리미트와 안티봇 시스템을 운영합니다. 단일 IP에서 짧은 시간에 여러 요청을 보내면 sorry/index 리다이렉트나 reCAPTCHA 챌린지가 발생하며, 반복되면 장시간 차단됩니다. 레지덴셜 프록시를 사용하면 실제 ISP IP로 요청을 분산시켜 차단 위험을 크게 줄일 수 있습니다.
구글 쇼핑 스크래핑에 어떤 프록시 유형이 가장 좋나요?
레지덴셜 프록시가 가장 권장됩니다. 데이터센터 프록시는 구글이 즉시 식별하여 차단하며, 모바일 프록시는 가장 안전하지만 속도가 느리고 비용이 높습니다. 레지덴셜 프록시는 비용과 안정성의 최적 균형점이며, 도시 단위 지역 타겟팅을 지원하여 지역별 가격 차이를 정확히 수집할 수 있습니다.
구글 쇼핑 스크래핑 시 차단을 피하려면 어떻게 하나요?
차단을 피하려면 레지덴셜 프록시 사용, 3~8초 랜덤 딜레이, 세션 로테이션, 소프트 블록 감지 로직 구현이 필요합니다. HTTP 429나 sorry/index 리다이렉트가 감지되면 즉시 IP를 교체하고 30~60초 대기 후 재시도하세요. 또한 gl/hl 파라미터와 프록시 지역을 일치시켜 자연스러운 트래픽 패턴을 만드는 것이 중요합니다.
구글 쇼핑 스크래핑은 합법인가요?
공개 데이터(로그인 없이 접근 가능한 가격, 제품명 등) 수집은 일반적으로 합법으로 간주되지만, 구글의 서비스 약관은 자동화된 수집을 제한합니다. CFAA와 GDPR 적용은 사례마다 다르며, 개인정보를 수집하지 않고 공개 가격 데이터만 다루는 것이 안전합니다. 대규모 상용 사용 사례에서는 구글의 공식 SERP API 라이선스를 검토하는 것이 권장됩니다.






