리뷰 데이터는 브랜드 모니터링, 시장 조사, 경쟁사 분석, 제품 개선 피드백 수집에 필수적입니다. 하지만 Trustpilot, G2, 구글 비즈니스와 같은 주요 리뷰 플랫폼은 스크래핑을 적극적으로 차단합니다. 프록시로 리뷰 데이터 수집 방법을 이해하면 이러한 제한을 우회하면서도 합법적인 공개 데이터에 안정적으로 접근할 수 있습니다.
이 가이드는 개발자와 데이터 엔지니어가 리뷰 데이터셋을 구축하기 위해 필요한 실용적인 구현 방법을 코드 예제와 함께 제공합니다.
⚠️ 법적 고지: 이 가이드는 공개적으로 접근 가능한 리뷰 데이터의 수집만을 다룹니다. 각 플랫폼의 이용약관(Terms of Service)을 반드시 준수하고, 미국의 CFAA/GDPR 등 관련 법률을 확인하세요. 개인정보(PII) 수집은 피하고, robots.txt와 API 이용 약관을 존중해야 합니다. 공식 API가 제공되는 경우 API 사용을 우선하세요. 자세한 내용은 Google robots.txt 문서를 참조하세요.
프록시로 리뷰 데이터 수집 방법: 왜 필요한가
리뷰 플랫폼들이 스크래핑을 제한하는 이유는 단순합니다. 서버 부하를 줄이고, 리뷰 데이터의 상업적 가치를 보호하며, 봇 트래픽으로 인한 서비스 품질 저하를 방지하기 위해서입니다. 구체적인 문제는 다음과 같습니다:
- 속도 제한(Rate Limiting): 단일 IP에서 짧은 시간에 너무 많은 요청을 보내면 HTTP 429 Too Many Requests 응답이 반환됩니다. Trustpilot은 약 50 requests/min 수준의 제한을 적용하며, G2는 더 엄격한 제한을 사용합니다.
- 지역/로케일 개인화: 구글 비즈니스 리뷰는 사용자의 위치와 언어 설정에 따라 다른 리뷰가 표시됩니다. 한국 IP로 접속하면 한국어 리뷰가 우선 노출되어, 전체 리뷰를 수집할 수 없습니다.
- 봇 탐지 시스템: Cloudflare, Datadome, PerimeterX 등의 봇 탐지 솔루션이 HTTP 헤더, 쿠키, TLS 지문, 행동 패턴을 분석합니다. Cloudflare 봇 관리 문서에 따르면, 이러한 시스템은 단순한 User-Agent 검사 이상의 정교한 탐지를 수행합니다.
이러한 이유로 프록시가 리뷰 수집에 도움이 되는 이유는 명확합니다. 회전형 주거 프록시(residential proxy)를 사용하면 각 요청이 서로 다른 실제 ISP IP에서 오는 것처럼 보이게 할 수 있어, 속도 제한과 지역 차단을 우회할 수 있습니다. 데이터센터 IP와 달리 주거 IP는 실제 인터넷 사용자의 IP와 구별이 어렵기 때문에 봇 탐지 시스템을 통과할 확률이 훨씬 높습니다.
주요 리뷰 플랫폼 비교
| 플랫폼 | 봇 탐지 강도 | 속도 제한 | 지역 개인화 | 추천 프록시 유형 |
|---|---|---|---|---|
| Trustpilot | 중간 | ~50 req/min | 낮음 | 주거 프록시 (회전형) |
| G2 | 높음 (Cloudflare) | 엄격 | 중간 | 주거 프록시 + 스티키 세션 |
| 구글 비즈니스 | 매우 높음 | 동적 | 매우 높음 (hl/gl) | 국가 타겟팅 주거 프록시 |
ProxyHat의 지원 지역 페이지에서 190개 이상의 국가별 프록시 위치를 확인할 수 있습니다.
Trustpilot 리뷰 수집 — __NEXT_DATA__ JSON 활용
Trustpilot은 Next.js로 구축되어 있어, 각 페이지의 HTML 내에 __NEXT_DATA__라는 JSON 객체가 포함되어 있습니다. HTML 요소를 일일이 파싱하는 것보다 이 JSON을 직접 추출하는 것이 훨씬 안정적이며, 사이트 구조 변경에도 덜 취약합니다.
Trustpilot 비즈니스 프로필 URL 형식은 https://www.trustpilot.com/review/{company-domain}?page=N입니다. ?page=N 파라미터로 페이지네이션을 처리합니다.
import requests
import json
import re
import time
# ProxyHat 회전형 주거 프록시 - 미국 IP
proxy_url = "http://user-country-US:pass@gate.proxyhat.com:8080"
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": "text/html,application/xhtml+xml",
"Accept-Language": "en-US,en;q=0.9",
}
def scrape_trustpilot_reviews(company_domain, max_pages=10):
all_reviews = []
for page in range(1, max_pages + 1):
url = f"https://www.trustpilot.com/review/{company_domain}?page={page}"
resp = requests.get(url, headers=headers, proxies=proxies, timeout=30)
if resp.status_code == 429:
print(f"Rate limited on page {page}, backing off...")
time.sleep(10)
continue
if resp.status_code != 200:
print(f"Page {page}: HTTP {resp.status_code}")
break
# __NEXT_DATA__ JSON 추출
match = re.search(
r'<script id="__NEXT_DATA__" type="application/json">(.*?)</script>',
resp.text, re.DOTALL
)
if match:
data = json.loads(match.group(1))
reviews = data.get("props", {}).get("pageProps", {}).get("reviews", [])
if not reviews:
print(f"No more reviews on page {page}")
break
for r in reviews:
all_reviews.append({
"author": r.get("consumer", {}).get("displayName"),
"rating": r.get("rating"),
"title": r.get("title"),
"text": r.get("text"),
"date": r.get("dates", {}).get("publishedDate"),
"page": page,
})
time.sleep(2) # 요청 간격 유지
return all_reviews
reviews = scrape_trustpilot_reviews("example.com", max_pages=5)
print(f"수집된 리뷰: {len(reviews)}개")이 방식의 장점은 HTML 구조가 변경되어도 JSON 스키마는 비교적 안정적이라는 점입니다. ProxyHat 문서에서 인증 및 프록시 설정에 대한 자세한 정보를 확인할 수 있습니다.
G2 리뷰 수집 — 강화된 봇 차단 우회
G2는 Cloudflare 봇 관리를 사용하여 더 공격적인 봇 탐지를 수행합니다. 단순한 User-Agent 설정만으로는 충분하지 않으며, 주거 프록시와 현실적인 HTTP 헤더 조합이 필수적입니다. G2 리뷰 수집 시 scrape g2 reviews proxy 전략의 핵심은 요청 간 랜덤 대기 시간과 페이지별 IP 회전입니다.
import requests
import time
import random
from bs4 import BeautifulSoup
# ProxyHat 주거 프록시 - 페이지별 IP 회전
def get_proxy():
# 세션 플래그 없음 = 각 요청마다 새 IP
return {
"http": "http://user-country-US:pass@gate.proxyhat.com:8080",
"https": "http://user-country-US:pass@gate.proxyhat.com:8080",
}
headers = {
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) "
"AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/120.0.0.0 Safari/537.36",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
"Accept-Language": "en-US,en;q=0.9",
"Accept-Encoding": "gzip, deflate, br",
"DNT": "1",
"Connection": "keep-alive",
"Upgrade-Insecure-Requests": "1",
}
def scrape_g2_reviews(product_slug, max_pages=5):
all_reviews = []
for page in range(1, max_pages + 1):
url = f"https://www.g2.com/products/{product_slug}/reviews?page={page}"
proxy = get_proxy() # 각 페이지마다 새 IP
try:
resp = requests.get(url, headers=headers, proxies=proxy, timeout=30)
except Exception as e:
print(f"Page {page} error: {e}")
time.sleep(random.uniform(5, 10))
continue
if resp.status_code == 403:
print(f"Blocked on page {page}, retrying...")
time.sleep(random.uniform(3, 7))
continue
if resp.status_code == 429:
print(f"Rate limited on page {page}")
time.sleep(15)
continue
soup = BeautifulSoup(resp.text, "html.parser")
review_items = soup.find_all("div", itemprop="review")
for item in review_items:
rating_meta = item.find("meta", itemprop="ratingValue")
body = item.find("div", itemprop="reviewBody")
author = item.find("span", itemprop="author")
all_reviews.append({
"author": author.get_text(strip=True) if author else None,
"rating": rating_meta["content"] if rating_meta else None,
"text": body.get_text(strip=True) if body else None,
"page": page,
})
print(f"Page {page}: {len(review_items)} reviews")
time.sleep(random.uniform(2, 5)) # 랜덤 대기
return all_reviews
reviews = scrape_g2_reviews("slack", max_pages=3)
print(f"수집된 G2 리뷰: {len(reviews)}개")G2의 별점 분포(star distribution)는 제품 페이지 상단에 그래프로 표시되며, HTML에서 data-star-rating 속성을 찾아 추출할 수 있습니다.
구글 비즈니스 리뷰 스크래핑 — 지역 타겟팅
구글 비즈니스 리뷰는 hl(언어)과 gl(지역) 파라미터에 따라 표시되는 리뷰가 달라집니다. 한국 IP로 접속하면 한국어 리뷰가, 미국 IP로 접속하면 영어 리뷰가 우선 표시됩니다. google business reviews scraping에서 가장 중요한 것은 일관된 로케일을 유지하는 것입니다.
ProxyHat의 국가 타겟팅 기능(user-country-US)을 사용하면 미국 주거 IP로 일관된 로케일을 보장할 수 있습니다:
import requests
# 미국 주거 IP로 일관된 로케일 보장
proxy_url = "http://user-country-US:pass@gate.proxyhat.com:8080"
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_business_reviews(place_id, hl="en", gl="us"):
"""구글 비즈니스 공개 리뷰 페이지에서 데이터 수집"""
url = f"https://www.google.com/maps/place/?q=place_id:{place_id}"
params = {"hl": hl, "gl": gl}
resp = requests.get(
url, headers=headers, proxies=proxies,
params=params, timeout=30
)
print(f"Status: {resp.status_code}, Length: {len(resp.text)} bytes")
# 구글 맵스 응답에서 리뷰 데이터 추출
# 실제 구현 시 응답 구조 분석 필요
# 공식 Places API 사용을 권장
return resp.text
# 예시: 공개 리뷰 수집 (place_id는 공개 정보)
result = scrape_google_business_reviews(
"ChIJN1t_tDeuEmsRUsoyG83frY4",
hl="en", gl="us"
)💡 팁: 구글 비즈니스 리뷰는 지역에 따라 다른 리뷰가 우선 표시됩니다.
user-country-US로 미국 IP를 사용하면 미국 사용자가 보는 리뷰를 일관되게 수집할 수 있습니다. 여러 국가의 리뷰를 수집하려면user-country-DE,user-country-JP등으로 변경하세요. ProxyHat 지원 지역에서 전체 국가 목록을 확인하세요.
구글의 봇 탐지는 가장 정교하므로, scrape reviews data with proxies를 수행할 때 구글 비즈니스는 공식 Places API 사용을 최우선으로 고려하세요. API가 제공하는 데이터가 제한적이거나 비용이 발생하는 경우에만 웹 스크래핑을 대안으로 사용하세요.
ProxyHat으로 IP 로테이션 구현하기
ProxyHat에서는 사용자명에 플래그를 추가하여 지역 타겟팅과 세션 관리를 수행합니다. 두 가지 핵심 패턴을 알아보겠습니다.
1. 페이지별 IP 회전 (Per-request rotation)
각 요청마다 새로운 IP를 할당받으려면 세션 플래그 없이 연결합니다. 이 방식은 속도 제한을 우회하는 데 가장 효과적입니다:
import requests
import time
# 세션 플래그 없음 = 각 요청마다 자동으로 새 IP
proxy = "http://user-country-US:pass@gate.proxyhat.com:8080"
proxies = {"http": proxy, "https": proxy}
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
"AppleWebKit/537.36",
"Accept-Language": "en-US,en;q=0.9",
}
for page in range(1, 11):
url = f"https://www.trustpilot.com/review/example.com?page={page}"
resp = requests.get(url, headers=headers, proxies=proxies, timeout=30)
print(f"Page {page}: HTTP {resp.status_code}")
if resp.status_code == 429:
time.sleep(10)
else:
time.sleep(2)2. 스티키 세션 (Sticky session)
여러 페이지에 걸쳐 동일한 IP를 유지해야 하는 경우, 세션 ID를 사용합니다. G2처럼 쿠키 기반 세션을 확인하는 사이트에서 유용합니다:
import requests
import time
# 동일한 세션 ID로 여러 요청 시 같은 IP 유지
session_id = "review-scraper-001"
proxy = f"http://user-session-{session_id}:pass@gate.proxyhat.com:8080"
proxies = {"http": proxy, "https": proxy}
headers = {
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) "
"AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/120.0.0.0 Safari/537.36",
"Accept-Language": "en-US,en;q=0.9",
}
# 같은 IP로 연속 요청 (쿠키/세션 일관성 유지)
for page in range(1, 6):
url = f"https://www.g2.com/products/slack/reviews?page={page}"
resp = requests.get(url, headers=headers, proxies=proxies, timeout=30)
print(f"Page {page}: HTTP {resp.status_code}")
time.sleep(3)스티키 세션은 최대 30분 동안 동일한 IP를 유지합니다. 세션이 만료되면 자동으로 새 IP가 할당됩니다.
ProxyHat 요금제에서 트래픽 기반 및 IP 기반 요금제를 확인할 수 있으며, 웹 스크래핑 사용 사례 페이지에서 더 많은 구현 예제를 볼 수 있습니다.
Node.js로 리뷰 수집 자동화
Node.js 환경에서는 https-proxy-agent 패키지를 사용하여 ProxyHat에 연결할 수 있습니다. 다음은 Trustpilot 리뷰를 수집하는 Node.js 예제입니다:
const axios = require('axios');
const { HttpsProxyAgent } = require('https-proxy-agent');
// ProxyHat 주거 프록시 - 미국 IP
const proxyAgent = new HttpsProxyAgent(
'http://user-country-US:pass@gate.proxyhat.com:8080'
);
async function scrapeReviews(companyDomain, maxPages = 5) {
const allReviews = [];
for (let page = 1; page <= maxPages; page++) {
const url = `https://www.trustpilot.com/review/${companyDomain}?page=${page}`;
try {
const response = await axios.get(url, {
httpsAgent: proxyAgent,
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': 'text/html,application/xhtml+xml',
'Accept-Language': 'en-US,en;q=0.9',
},
timeout: 30000,
});
// __NEXT_DATA__ 추출
const match = response.data.match(
/<script id="__NEXT_DATA__" type="application\/json">(.*?)<\/script>/s
);
if (match) {
const data = JSON.parse(match[1]);
const reviews = data.props?.pageProps?.reviews || [];
if (reviews.length === 0) {
console.log(`No more reviews on page ${page}`);
break;
}
reviews.forEach(r => {
allReviews.push({
author: r.consumer?.displayName,
rating: r.rating,
title: r.title,
text: r.text,
date: r.dates?.publishedDate,
page: page,
});
});
console.log(`Page ${page}: ${reviews.length} reviews`);
}
await new Promise(r => setTimeout(r, 2000)); // 2초 대기
} catch (err) {
console.error(`Page ${page} error: ${err.message}`);
await new Promise(r => setTimeout(r, 5000));
}
}
return allReviews;
}
scrapeReviews('example.com', 5).then(r => {
console.log(`수집된 리뷰: ${r.length}개`);
});자주 발생하는 실수와 해결 방법
- 동일한 User-Agent 반복 사용: 모든 요청에 동일한 User-Agent를 사용하면 봇 탐지 시스템에 쉽게 걸립니다. User-Agent 리스트를 준비하고 랜덤으로 선택하세요.
- 요청 간격이 너무 짧음: 1초 미만의 간격으로 요청을 보내면 즉시 차단됩니다. 최소 2초 이상의 대기 시간을 두고, 랜덤 요소를 추가하세요.
- 데이터센터 프록시 사용: 데이터센터 IP는 봇 탐지 시스템이 쉽게 식별합니다. 리뷰 플랫폼에서는 반드시 주거 프록시를 사용하세요.
- 지역 타겟팅 무시: 구글 비즈니스 리뷰 수집 시 지역을 지정하지 않으면, 매 요청마다 다른 국가의 리뷰가 반환되어 데이터 일관성이 깨집니다.
user-country-US와 같이 국가를 명시하세요. - HTTP 상태 코드 무시: 429, 403 응답을 무시하고 계속 요청을 보내면 IP가 영구 차단될 수 있습니다. 상태 코드를 확인하고 적절히 대응하세요.
- 쿠키/세션 불일치: 스티키 세션이 필요한 사이트에서 페이지별로 다른 IP를 사용하면 세션이 끊겨 차단될 수 있습니다. G2와 같은 사이트에서는
-session-플래그를 사용하세요.
공식 API를 사용해야 하는 경우
모든 스크래핑 작업이 프로젝트를 통한 웹 수집을 필요로 하는 것은 아닙니다. 다음과 같은 경우에는 공식 API를 사용하는 것이 더 효율적이고 합법적입니다:
- 구글 비즈니스: Places API가 리뷰 데이터를 제공합니다. 웹 스크래핑보다 안정적이며 ToS를 위반하지 않습니다.
- Trustpilot: Trustpilot API가 비즈니스 리뷰를 제공합니다. 인증이 필요하지만 데이터 품질이 보장됩니다.
- 대량 데이터 필요: 수만 개 이상의 리뷰가 필요한 경우, 스크래핑보다 API나 데이터 파트너십이 더 비용 효율적일 수 있습니다.
공식 API가 제공하는 데이터가 충분하지 않거나, API가 존재하지 않는 플랫폼의 경우에만 웹 스크래핑을 대안으로 사용하세요. 이 경우에도 robots.txt를 확인하고, 각 플랫폼의 ToS를 준수해야 합니다.
핵심 요약
Key Takeaways:
- 주거 프록시는 필수: Trustpilot, G2, 구글 비즈니스 모두 봇 탐지 시스템을 사용하므로 데이터센터 IP로는 차단되기 쉽습니다. ProxyHat 주거 프록시(
gate.proxyhat.com:8080)를 사용하세요.- Trustpilot은 __NEXT_DATA__ 활용: HTML 파싱 대신 페이지 내 포함된 JSON을 추출하면 더 안정적으로 리뷰를 수집할 수 있습니다.
- G2는 헤더와 대기 시간이 핵심: 현실적인 HTTP 헤더와 랜덤 대기 시간(2~5초)을 사용하고, 페이지별 IP 회전을 적용하세요.
- 구글 비즈니스는 지역 타겟팅:
user-country-US로 일관된 로케일을 유지하고, 가능하면 공식 Places API를 우선 고려하세요.- 스티키 세션 vs 회전: 쿠키 기반 세션을 확인하는 사이트(G2)에는 스티키 세션(
-session-)을, 단순 페이지네이션(Trustpilot)에는 회전 IP를 사용하세요.- 합법성 우선: 공개 데이터만 수집하고, PII 수집을 피하며, 공식 API가 있는 경우 API를 먼저 사용하세요.
리뷰 데이터 수집에 대한 더 많은 사용 사례는 SERP 추적 사용 사례 페이지에서 확인할 수 있으며, ProxyHat 설정에 대한 자세한 정보는 공식 문서를 참조하세요.






