Python으로 Amazon 리뷰를 스크래핑하는 방법: 로그인 벽 우회부터 감성 분석까지

최종 업데이트: August 21, 2026
Python으로 Amazon 리뷰를 스크래핑하는 방법: 로그인 벽 우회부터 감성 분석까지
AI 요약

이 글은 Amazon 리뷰를 Python으로 수집하는 실전 방법을 다룹니다. 쿠키 기반 인증으로 로그인 벽을 넘고, data-hook 셀렉터로 안정적으로 리뷰를 추출하며, 별점 필터와 정렬 조합으로 10페이지 제한을 우회하는 방법을 설명합니다. 또한 봇 차단 대응, CSV/Excel 내보내기, TextBlob과 Transformers를 활용한 감성 분석까지 소개합니다. 마지막으로 코드 유지보수 없이 같은 작업을 처리하는 Thunderbit 노코드 대안도 비교합니다.

제 Amazon 리뷰 스크래퍼는 6주 동안 아무 문제 없이 잘 돌아갔습니다. 그런데 어느 날 아침, 200 OK만 뜨고 화면은 텅 빈 페이지가 나왔죠. 에러도 없고 CAPTCHA도 없고, 한때 수백 개의 리뷰가 있던 자리에는 빈 HTML만 덩그러니 남아 있었습니다.

이런 상황이 낯익다면, 당신만 그런 게 아닙니다. 2025년 말 Amazon은 전체 리뷰 페이지를 로그인해야만 볼 수 있게 막기 시작했고, 엄청나게 많은 Python 스크래핑 스크립트가 하룻밤 사이에 멈춰 버렸습니다. 저는 지난 몇 달 동안 Thunderbit에서 AI 스크래퍼를 만들면서, 동시에 제 개인 Python 리뷰 파이프라인도 계속 돌려 왔습니다. 그래서 처음 스크립트가 먹통이 됐을 때 이런 가이드가 있었으면 얼마나 좋았을까 하는 마음으로 이 글을 쓰게 됐습니다. 여기서는 실제로 먹히는 방식인 쿠키 기반 인증, Amazon의 CSS 난독화를 버텨내는 안정적인 셀렉터, 10페이지 페이지네이션 제한을 우회하는 법, 봇 차단 대응, 그리고 원본 리뷰 텍스트를 실제 비즈니스 인사이트로 바꾸는 감성 분석 보너스까지 다룹니다. 그리고 중간쯤 읽다가 “이 모든 코드를 직접 유지하고 싶진 않다”는 생각이 든다면, Thunderbit가 이 작업을 Python 없이도 약 2분 만에 끝내는 방법도 함께 보여드리겠습니다.

Amazon 리뷰 스크래핑이란 무엇이며 왜 중요할까?

Amazon 리뷰 스크래핑은 별점, 리뷰 본문, 작성자 이름, 날짜, Verified Purchase 배지 같은 고객 리뷰 데이터를 Amazon 상품 페이지에서 프로그램으로 뽑아내는 작업입니다. Amazon이 2010년에 Product Advertising API에서 리뷰 콘텐츠를 없앤 뒤 다시 되돌리지 않았기 때문에, 이 데이터에 접근하는 프로그램 방식은 사실상 웹 스크래핑뿐입니다.

데이터도 이 필요성을 뒷받침합니다. 쇼핑객의 95%는 구매 전에 리뷰를 읽고, 94%는 Amazon을 상품 리뷰의 1순위 출처로 꼽습니다. 상품 페이지에 리뷰를 단 5개만 보여줘도 전환율이 270%까지 오를 수 있습니다. 리뷰 감성을 체계적으로 분석하는 기업은 고객 유지율이 최대 15% 높아진다는 결과도 있습니다. 이건 추상적인 데이터 과학 이야기가 아닙니다. 경쟁 정보, 제품 개선 신호, 마케팅 문구가 모두 Amazon 서버에 그대로 쌓여 있는 셈이죠.

왜 Python으로 Amazon 리뷰를 스크래핑할까

Python은 이런 작업에서 여전히 가장 많이 선택되는 대표 언어입니다. 2024 Stack Overflow Developer Survey에서 가장 선호되는 언어 1위였고, requests, BeautifulSoup, pandas, Scrapy 같은 생태계 덕분에 전업 개발자가 아니어도 웹 스크래핑을 비교적 쉽게 시작할 수 있습니다.

팀마다 이 데이터를 활용하는 방식도 꽤 다릅니다.

활용 사례추출하는 정보
제품 / R&D반복되는 불만 파악, 개선 우선순위 설정1~2점 리뷰 텍스트, 키워드 빈도
영업경쟁사 제품 감성 모니터링평점, 리뷰 수 추이
마케팅광고 문구에 쓸 고객 언어 찾기긍정적 표현, 기능 언급
이커머스 운영자사 제품 감성 변화 추적별점 분포, Verified Purchase 비율
시장 조사카테고리 리더 간 기능 비교여러 ASIN의 리뷰 데이터셋

어떤 주방용품 브랜드는 부정적 리뷰를 분석해 22%가 “논스틱 코팅이 벗겨진다”고 언급한다는 사실을 발견했고, 제품을 다시 설계한 뒤 60일 만에 Best Seller 1위 자리를 되찾았습니다. 또 한 피트니스 트래커 회사는 리뷰 텍스트에서 “밴드가 따갑다”는 표현을 포착해 라텍스 알레르기 문제를 찾아냈고, 저자극 버전을 출시해 반품률을 40% 줄였습니다. 이런 결과가 바로 엔지니어링 투자를 정당화하는 ROI입니다.

왜 Amazon 리뷰 스크래퍼가 멈췄을까: 로그인 벽

2024년 11월 14일, Amazon은 전체 상품 리뷰 페이지를 보려면 로그인을 요구하기 시작했습니다. 이 변화는 커뮤니티 포럼스크래핑 벤더 블로그 곳곳에서 확인됐습니다. 시크릿 창에서 /product-reviews/{ASIN}/에 접속하면 리뷰 데이터 대신 로그인 페이지로 리다이렉트됩니다.

python-web-scraping-diagram.webp

문제는 꽤 미묘합니다. 스크립트는 200 OK를 받지만, HTML 본문에는 리뷰 대신 로그인 폼(name="email", id="ap_password")이 들어 있습니다. 에러 코드도 없고 CAPTCHA도 없습니다. 그냥... 쓸모 있는 내용이 아무것도 없는 거죠.

Amazon은 봇 방지와 지역 규정 준수를 위해 이런 식으로 바꿨습니다. 그리고 적용도 늘 일정하지는 않아서, 특히 첫 페이지에서는 새 브라우저 창이 벽이 작동하기 전에 몇 개의 리뷰를 먼저 보여주기도 합니다. 하지만 대규모로 돌리는 스크래퍼라면 로그인 벽이 항상 켜져 있다고 가정하는 편이 안전합니다.

Amazon의 국가별 도메인(.de, .co.uk, .co.jp)은 로그인 벽을 각각 따로 적용합니다. 한 포럼 사용자의 말대로라면 “국가마다 로그인이 따로 필요하다”는 뜻입니다. .com 쿠키는 .co.uk에서 통하지 않습니다.

Featured Reviews와 Full Reviews: 로그인 없이 아직 가능한 것

Amazon 상품 페이지(/dp/{ASIN}/)는 여전히 인증 없이 약 8개의 “featured reviews”를 보여줍니다. 이 리뷰들은 Amazon 알고리즘이 골라낸 것으로, 짧게 감성만 확인하기에는 좋지만 정렬, 필터, 페이지네이션은 불가능합니다.

반면 전체 리뷰 페이지(/product-reviews/{ASIN}/)는 새순 정렬, 별점 필터링, 수백 개 리뷰를 넘기는 페이지네이션이 가능하지만 로그인이 필요합니다.

몇 개만 빨리 분위기를 보고 싶다면 상품 페이지를 스크래핑하면 됩니다. 수백 개, 수천 개가 필요하다면 인증 처리가 필수입니다.

시작하기 전에 필요한 것: Python 환경과 라이브러리

코드를 쓰기 전에 준비할 것은 다음과 같습니다.

  • 난이도: 중급 (Python에 익숙하고 기본 HTML 구조를 이해하는 수준)
  • 소요 시간: 전체 파이프라인 약 45분, 기본 스크래핑 약 10분
  • 준비물: Python 3.8+, Chrome 브라우저, 유효한 Amazon 계정

핵심 라이브러리를 설치합니다.

pip install requests beautifulsoup4 lxml pandas textblob

선택 사항(고급 감성 분석용):

pip install transformers torch

ASIN이란? Amazon의 10자리 상품 식별자입니다. 상품 URL 어디에서든 찾을 수 있는데, 예를 들어 amazon.com/dp/B0BCNKKZ91에서 ASIN은 B0BCNKKZ91입니다. 이 값을 리뷰 URL에 넣게 됩니다.

1단계: 쿠키 기반 인증으로 로그인 벽 넘기

가장 안정적인 방법은 브라우저에서 Amazon에 로그인한 뒤 세션 쿠키를 복사해서 Python requests.Session()에 넣는 것입니다. 이렇게 하면 Selenium으로 로그인 자동화를 할 때 자주 걸리는 CAPTCHA와 SMS 2FA를 피할 수 있습니다.

필요한 쿠키는 다음 7개입니다.

쿠키 이름용도
session-id세션 식별자
session-id-time세션 타임스탬프
session-token세션 토큰
ubid-main사용자 브라우징 식별자
at-main기본 인증 토큰
sess-at-main세션 범위 인증
x-main사용자 이메일 기반 식별자

Chrome DevTools에서 쿠키 추출하는 방법

  1. Chrome에서 amazon.com에 로그인합니다
  2. DevTools를 엽니다(F12 또는 우클릭 → 검사)
  3. ApplicationStorageCookieshttps://www.amazon.com으로 이동합니다
  4. 표에 있는 각 쿠키 이름을 찾아 값을 복사합니다
  5. Python에서 쓸 수 있게 세미콜론 구분 문자열로 정리합니다

세션은 이렇게 설정합니다.

import requests

session = requests.Session()

# 여기에 쿠키 값을 붙여 넣으세요
cookies = {
    "session-id": "YOUR_SESSION_ID",
    "session-id-time": "YOUR_SESSION_ID_TIME",
    "session-token": "YOUR_SESSION_TOKEN",
    "ubid-main": "YOUR_UBID_MAIN",
    "at-main": "YOUR_AT_MAIN",
    "sess-at-main": "YOUR_SESS_AT_MAIN",
    "x-main": "YOUR_X_MAIN",
}

headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/147.0.0.0 Safari/537.36",
    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
    "Accept-Language": "en-US,en;q=0.5",
}

session.cookies.update(cookies)
session.headers.update(headers)

중요: 모든 요청에서 같은 session 객체를 재사용하세요. 그래야 쿠키가 일관되게 유지되고 실제 브라우저 세션처럼 보입니다. 쿠키는 보통 며칠에서 몇 주 정도 유지되지만, 다시 로그인 페이지로 튕기기 시작하면 브라우저에서 새로 갱신해야 합니다.

.com이 아닌 마켓플레이스에서는 쿠키 이름이 조금씩 다릅니다. 예를 들어 amazon.de는 at-main 대신 at-acbde, amazon.co.uk는 at-acbuk을 사용합니다. 마켓플레이스마다 독립 세션이 필요합니다.

2단계: 요청을 만들고 BeautifulSoup로 리뷰 HTML 파싱하기

Amazon 리뷰 URL 형식은 다음과 같습니다.

https://www.amazon.com/product-reviews/{ASIN}/ref=cm_cr_arp_d_viewopt_srt?sortBy=recent&pageNumber=1

핵심 함수는 다음과 같습니다.

from bs4 import BeautifulSoup
import time, random

def get_soup(session, url):
    time.sleep(random.uniform(2, 5))  # 예의 있는 지연
    response = session.get(url, timeout=15)

    # 로그인 벽 감지
    if "ap_email" in response.text or "Amazon Sign-In" in response.text:
        raise Exception("로그인 벽이 감지되었습니다 — 쿠키를 새로 갱신하세요")

    if response.status_code != 200:
        raise Exception(f"HTTP {response.status_code}")

    return BeautifulSoup(response.text, "lxml")

작은 팁 하나: 리뷰 페이지를 열기 전에 먼저 상품 페이지를 방문하세요. 세션에 자연스러운 브라우징 패턴이 생깁니다.

# 먼저 상품 페이지 방문(실제 브라우징처럼 보이게 함)
product_url = f"https://www.amazon.com/dp/{asin}"
session.get(product_url, timeout=15)
time.sleep(random.uniform(1, 3))

# 그다음 리뷰 페이지 접근
reviews_url = f"https://www.amazon.com/product-reviews/{asin}/ref=cm_cr_arp_d_viewopt_srt?sortBy=recent&pageNumber=1"
soup = get_soup(session, reviews_url)

3단계: 안정적인 셀렉터로 리뷰 데이터 추출하기(CSS 클래스에 의존하지 않기)

이 부분에서 2022~2023년 튜토리얼 대부분이 무너집니다. Amazon은 CSS 클래스 이름을 난독화하고, 일정 주기로 바꿉니다. 한 개발자가 포럼에서 짜증 섞인 말로 표현했듯이 “span 태그 클래스 이름에는 하나의 규칙도 없었다”는 수준이죠.

해결책은 이겁니다. Amazon은 리뷰 요소에 data-hook 속성을 쓰는데, 이것들은 놀라울 정도로 안정적입니다. Amazon 자체 프런트엔드 코드가 의존하는 의미 있는 식별자라서 임의로 바뀌지 않습니다.

리뷰 필드안정적인 셀렉터(data-hook)깨지기 쉬운 셀렉터(class)
리뷰 본문[data-hook="review-body"].review-text-content (변경됨)
별점[data-hook="review-star-rating"].a-icon-alt (모호함)
리뷰 제목[data-hook="review-title"].review-title (가끔만)
작성자 이름span.a-profile-name비교적 안정적
리뷰 날짜[data-hook="review-date"].review-date (지역별 차이)
Verified Purchase[data-hook="avp-badge"]span.a-size-mini

data-hook 셀렉터를 사용한 추출 코드는 다음과 같습니다.

import re

def extract_reviews(soup):
    reviews = []
    review_divs = soup.select('[data-hook="review"]')

    for div in review_divs:
        # 별점
        rating_el = div.select_one('[data-hook="review-star-rating"]')
        rating = None
        if rating_el:
            rating_text = rating_el.get_text(strip=True)
            match = re.search(r'(\d\.?\d?)', rating_text)
            if match:
                rating = float(match.group(1))

        # 제목
        title_el = div.select_one('[data-hook="review-title"]')
        title = title_el.get_text(strip=True) if title_el else ""

        # 본문
        body_el = div.select_one('[data-hook="review-body"]')
        body = body_el.get_text(strip=True) if body_el else ""

        # 작성자
        author_el = div.select_one('span.a-profile-name')
        author = author_el.get_text(strip=True) if author_el else ""

        # 날짜와 국가
        date_el = div.select_one('[data-hook="review-date"]')
        date_text = date_el.get_text(strip=True) if date_el else ""
        # 형식: "Reviewed in the United States on January 15, 2025"
        country_match = re.search(r'Reviewed in (.+?) on', date_text)
        date_match = re.search(r'on (.+)$', date_text)
        country = country_match.group(1) if country_match else ""
        date = date_match.group(1) if date_match else ""

        # Verified Purchase
        verified_el = div.select_one('[data-hook="avp-badge"]')
        verified = bool(verified_el)

        reviews.append({
            "author": author,
            "rating": rating,
            "title": title,
            "content": body,
            "date": date,
            "country": country,
            "verified": verified,
        })

    return reviews

저는 이 셀렉터 조합을 여러 ASIN에 대해 몇 달째 돌리고 있는데, data-hook 속성은 한 번도 바뀐 적이 없습니다. 반면 CSS 클래스는 같은 기간에 최소 두 번은 바뀌었습니다.

4단계: 페이지네이션과 Amazon의 10페이지 제한 처리하기

Amazon은 pageNumber 파라미터를 정렬/필터 조합당 10페이지, 즉 최대 약 100개 리뷰로 제한합니다. 10페이지를 넘기면 “다음 페이지” 버튼이 사라집니다.

기본 페이지네이션 루프는 이렇게 생겼습니다.

all_reviews = []

for page in range(1, 11):
    url = f"https://www.amazon.com/product-reviews/{asin}/ref=cm_cr_arp_d_viewopt_srt?sortBy=recent&pageNumber={page}"
    soup = get_soup(session, url)
    page_reviews = extract_reviews(soup)

    if not page_reviews:
        break  # 이 페이지에 더 이상 리뷰가 없음

    all_reviews.extend(page_reviews)
    print(f"Page {page}: {len(page_reviews)} reviews")

Amazon 리뷰를 10페이지 이상 가져오는 방법

우회 방법은 필터 버킷을 나누는 것입니다. filterByStarsortBy의 각 조합은 서로 독립적인 10페이지 창을 가집니다.

별점 필터 값: one_star, two_star, three_star, four_star, five_star
정렬 값: recent, helpful(기본값)

5개의 별점 필터 × 2개의 정렬 조합을 모두 쓰면 제품당 최대 100페이지, 즉 1,000개 리뷰까지 접근할 수 있습니다. 별점 분포가 고르지 않은 상품이라면 실제로 거의 전체 리뷰 세트에 가까운 결과를 얻는 경우도 많습니다.

star_filters = ["one_star", "two_star", "three_star", "four_star", "five_star"]
sort_orders = ["recent", "helpful"]
all_reviews = []
seen_titles = set()  # 간단한 중복 제거

for star in star_filters:
    for sort in sort_orders:
        for page in range(1, 11):
            url = (
                f"https://www.amazon.com/product-reviews/{asin}"
                f"?filterByStar={star}&sortBy={sort}&pageNumber={page}"
            )
            soup = get_soup(session, url)
            page_reviews = extract_reviews(soup)

            if not page_reviews:
                break

            for review in page_reviews:
                # 제목 + 작성자 조합으로 중복 제거
                key = (review["title"], review["author"])
                if key not in seen_titles:
                    seen_titles.add(key)
                    all_reviews.append(review)

            print(f"[{star}/{sort}] Page {page}: {len(page_reviews)} reviews")

print(f"Total unique reviews: {len(all_reviews)}")

버킷 간 중복은 반드시 생기므로 중복 제거가 중요합니다. 저는 리뷰 제목 + 작성자 이름 조합을 빠른 키로 씁니다. 완벽하진 않지만 대부분의 중복은 잡아냅니다.

5단계: 봇 차단 방어 피하기(회전, 속도 제한, 재시도)

Amazon은 AWS WAF Bot Control을 사용하고 있고, 그 강도도 훨씬 더 세졌습니다. User-Agent만 바꾸거나 지연만 넣는 식의 단일 방어는 더 이상 충분하지 않습니다.

기법구현 방식
User-Agent 회전실제 브라우저 문자열 10개 이상에서 무작위 선택
지수 백오프503 발생 시 2초 → 4초 → 8초 재시도 지연
요청 속도 제한페이지 사이에 random.uniform(2, 5)초 지연
프록시 회전Residential proxy 순환 사용
세션 핑거프린트세션별로 일관된 쿠키 + 헤더 유지
TLS 위장운영 환경에서는 기본 requests 대신 curl_cffi 사용

운영 환경에 맞는 재시도 래퍼는 다음과 같습니다.

import time, random

USER_AGENTS = [
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/147.0.0.0 Safari/537.36",
    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/147.0.0.0 Safari/537.36",
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:149.0) Gecko/20100101 Firefox/149.0",
    "Mozilla/5.0 (Macintosh; Intel Mac OS X 15_7_5) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Safari/605.1.15",
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36",
]

def scrape_with_retries(session, url, max_retries=3):
    for attempt in range(max_retries):
        try:
            session.headers["User-Agent"] = random.choice(USER_AGENTS)
            time.sleep(random.uniform(2, 5))

            response = session.get(url, timeout=15)

            # 차단 감지
            if "validateCaptcha" in response.url or "Robot Check" in response.text:
                wait = (2 ** attempt) * 5
                print(f"CAPTCHA가 감지되었습니다. {wait}초 대기 중...")
                time.sleep(wait)
                continue

            if response.status_code in (429, 503):
                wait = (2 ** attempt) * 2
                print(f"요청 제한 발생({response.status_code}). {wait}초 대기 중...")
                time.sleep(wait)
                continue

            if "ap_email" in response.text:
                raise Exception("로그인 벽 — 쿠키가 만료되었습니다")

            return BeautifulSoup(response.text, "lxml")

        except Exception as e:
            if attempt == max_retries - 1:
                raise
            print(f"시도 {attempt + 1} 실패: {e}")

    return None

프록시에 대한 참고 사항: Amazon은 AWS, GCP, Azure, DigitalOcean 같은 알려진 데이터센터 IP 대역을 네트워크 수준에서 차단합니다. 수백 페이지 이상 스크래핑한다면 사실상 Residential proxy가 필수입니다. 사용량에 따라 월 50~200달러 이상이 들 수 있습니다. 소규모 프로젝트(하루 100요청 미만)라면 집 IP에서 조심스럽게 속도를 조절해도 되는 경우가 많습니다.

Amazon은 TLS 핑거프린트도 확인합니다. Python 기본 requests 라이브러리는 WAF가 미리 차단하는 잘 알려진 JA3 해시를 갖고 있습니다. 운영용 스크래퍼라면 실제 브라우저 TLS 스택을 흉내 내는 curl_cffi를 고려해 보세요. 튜토리얼 수준의 스크래핑(몇백 페이지 정도)이라면 헤더만 잘 잡은 requests로도 충분한 경우가 많습니다.

6단계: 스크래핑한 Amazon 리뷰를 CSV 또는 Excel로 내보내기

리뷰를 모았다면 pandas로 바로 쓸 수 있는 형식으로 저장하는 건 아주 쉽습니다.

import pandas as pd

df = pd.DataFrame(all_reviews)
df.to_csv("amazon_reviews.csv", index=False)
print(f"Exported {len(df)} reviews to amazon_reviews.csv")

예시 출력:

authorratingtitlecontentdatecountryverified
Sarah M.5.0올해 가장 잘 산 물건배터리가 하루 종일 가고, 화면도 정말 훌륭해요...January 15, 2025the United StatesTrue
Mike T.2.02주 만에 실망충전 포트가 작동하지 않기 시작했어요...February 3, 2025the United StatesTrue
Priya K.4.0가격 대비 훌륭함필요한 건 다 해주고, 무거운 앱에서만 약간 느려요...March 10, 2025the United StatesFalse

Excel로 내보내려면 df.to_excel("amazon_reviews.xlsx", index=False)를 쓰면 됩니다. (openpyxl 필요)

Google Sheets의 경우 gspread 라이브러리를 사용할 수 있지만, Google Cloud 설정을 8단계 이상 거쳐야 합니다. 프로젝트 생성, 두 개의 API 활성화, 서비스 계정 자격 증명 생성, 시트 공유까지 해야 하죠. 스크래핑보다 준비 과정이 더 많게 느껴진다면, 그건 맞는 말입니다. (Thunderbit처럼 한 번 클릭으로 Google Sheets에 내보내는 도구가 갑자기 매력적으로 보이는 이유이기도 합니다.)

보너스: Python 5줄로 스크래핑한 리뷰에 감성 분석 추가하기

대부분의 스크래핑 튜토리얼은 CSV 내보내기에서 끝납니다. 하지만 감성 점수를 매겨야 원시 데이터가 실제 비즈니스 의사결정으로 바뀝니다.

가장 빠른 기본값은 TextBlob입니다.

from textblob import TextBlob

df["sentiment"] = df["content"].apply(lambda x: TextBlob(str(x)).sentiment.polarity)

이렇게 하면 각 리뷰마다 -1.0(매우 부정적)에서 +1.0(매우 긍정적)까지의 polarity 점수가 나옵니다. 예시 출력:

content (축약)ratingsentiment
"배터리가 하루 종일 가고, 화면도 정말 훌륭해요..."5.00.65
"충전 포트가... 후에 작동을 멈췄어요"2.0-0.40
"필요한 건 다 해주고, 무거운 앱에서만..."4.00.25
"완전 쓰레기예요. 바로 반품했습니다."1.0-0.75
"그냥 그래요. 특별하진 않지만 작동은 해요."3.00.10

재미있는 건 별점과 감성 점수가 엇갈리는 행입니다. 예를 들어 3점 리뷰인데 문장은 긍정적이거나, 5점 리뷰인데 표현은 부정적인 경우죠. 이런 차이는 별점만 봐서는 보이지 않는 미묘한 고객 의견을 드러내 줍니다.

ai-review-analysis.webp

운영 수준의 정확도가 필요하다면 Hugging Face Transformers를 추천합니다. VADER는 제품 리뷰가 아니라 트윗으로 학습되었고, transformer 모델은 레키콘 기반 도구보다 리뷰 분류에서 98% 이상의 정확도를 보입니다. nlptown/bert-base-multilingual-uncased-sentiment 모델은 1~5점 별점을 직접 예측하기도 합니다.

from transformers import pipeline

clf = pipeline("sentiment-analysis",
               model="nlptown/bert-base-multilingual-uncased-sentiment")
df["predicted_stars"] = df["content"].apply(
    lambda x: int(clf(str(x)[:512])[0]["label"][0])
)

Amazon 리뷰는 J자형 분포를 따릅니다. 5점에 큰 스파이크가 있고, 1점에도 작은 스파이크가 있으며, 중간 점수대는 움푹 꺼집니다. 즉 평균 별점은 실제 품질을 보여주는 좋은 지표가 아닌 경우가 많습니다. 1점 리뷰 군집을 나눠 반복되는 주제를 찾아보세요. 대개 바로 고칠 수 있는 단 하나의 결함이 숨어 있습니다.

솔직한 트레이드오프: 직접 만드는 Python vs 유료 스크래핑 API vs Thunderbit

저는 Amazon용 Python 스크래퍼를 직접 유지해 본 적이 있는데, 솔직히 말하면 자주 깨집니다. 셀렉터는 바뀌고, 쿠키는 만료되고, Amazon은 새로운 봇 감지 레이어를 배포하고, 그러다 보면 어느새 토요일 아침이 데이터 분석이 아니라 스크래퍼 디버깅으로 날아가 버립니다. 포럼 사용자들도 비슷한 불만을 말합니다. “지난달에는 잘 되던” DIY 스크립트가 이제는 계속 패치가 필요하다는 거죠.

세 가지 주요 접근법을 비교하면 이렇습니다.

기준직접 만든 Python(BS4/Selenium)유료 스크래핑 APIThunderbit(노코드)
초기 설정 시간1~3시간30분(API 키)2분
비용무료(+ 프록시 비용)월 $50~200+무료 플랜 제공
로그인 벽 처리쿠키 수동 관리보통 처리됨자동 처리
유지보수높음(셀렉터 깨짐)낮음(제공사가 유지)없음(AI가 적응)
페이지네이션커스텀 코드 필요내장내장
다국가 지원도메인별 별도 세션보통 지원브라우저 기반 = 로케일 반영
감성 분석직접 코드 추가일부 포함Sheets로 내보내 어디서든 분석 가능
최적 용도학습, 완전한 제어대규모/운영 파이프라인빠른 데이터 수집, 비개발 팀

Python은 완전한 제어가 가능하고, 웹 스크래핑이 내부적으로 어떻게 돌아가는지 배우기에도 가장 좋은 방법입니다. 유료 API(ScrapingBee, Oxylabs, Bright Data)는 가동 시간이 비용보다 더 중요한 운영 파이프라인에 적합합니다. 그리고 매주 경쟁사 리뷰를 확인해야 하는 이커머스 운영팀이나 광고 문구용 고객 언어를 뽑아야 하는 마케팅팀처럼, 개발 부담 없이 리뷰 데이터가 필요한 팀에게는 세 번째 길도 있습니다.

Thunderbit로 Amazon 리뷰 스크래핑하기(노코드, 유지보수 없음)

저희는 Python 스크래퍼를 직접 관리하는 일이 너무 번거롭다고 느껴질 때를 위해 Thunderbit를 만들었습니다. 작업 흐름은 이렇습니다.

  1. Thunderbit Chrome Extension 설치
  2. 브라우저에서 Amazon 상품 리뷰 페이지로 이동(이미 로그인되어 있으므로 로그인 벽은 문제되지 않음)
  3. “AI Suggest Fields” 클릭 — Thunderbit가 페이지를 읽고 Author, Rating, Title, Review Text, Date, Verified Purchase 같은 열을 제안
  4. “Scrape” 클릭 — 내장 페이지네이션과 함께 데이터가 바로 추출됨
  5. Excel, Google Sheets, Airtable, Notion으로 내보내기

가장 큰 장점은 Thunderbit의 AI가 매번 페이지 구조를 새로 읽는다는 점입니다. 유지보수할 CSS 셀렉터도 없고, 쿠키 관리도 없고, 봇 방지 코드도 없습니다. Amazon이 HTML을 바꿔도 AI가 알아서 적응합니다. 프로그래밍 방식 접근이 필요하지만 직접 개발은 원치 않는 분들을 위해 Thunderbit는 Extract API도 제공합니다. AI 기반 필드 감지와 셀렉터 유지보수 없이 구조화된 데이터를 API로 추출할 수 있습니다.

Amazon 데이터에 대해 더 깊이 알고 싶다면 Amazon 상품과 리뷰를 스크래핑하는 방법Amazon 판매 데이터 추출 및 분석 가이드도 참고해 보세요.

Python으로 대규모 Amazon 리뷰 스크래핑할 때 유용한 팁

여러 ASIN을 대상으로 리뷰를 스크래핑한다면, 아래 습관들이 시행착오를 꽤 줄여 줍니다.

  • ASIN 단위로 배치 처리하고, 페이지 사이뿐 아니라 상품 사이에도 지연을 넣으세요. 저는 ASIN 사이에 10~15초 정도 쉬게 합니다.
  • 중복 제거를 강하게 하세요. 여러 별점 필터와 정렬 조합을 합치면 겹치는 리뷰가 생깁니다. (title, author, date) 튜플을 중복 제거 키로 쓰면 좋습니다.
  • 실패 로그를 남기세요. 어떤 ASIN + 페이지 + 필터 조합이 실패했는지 기록해 두면 전체를 다시 긁지 않아도 재시도할 수 있습니다.
  • 큰 프로젝트는 데이터베이스에 저장하세요. CSV 파일을 계속 키우는 것보다 SQLite 데이터베이스가 훨씬 확장성이 좋습니다.
import sqlite3

conn = sqlite3.connect("reviews.db")
df.to_sql("reviews", conn, if_exists="append", index=False)
  • 정기 스크래핑을 예약하세요. 지속적인 모니터링이 필요하다면 cron job을 설정하거나 Thunderbit의 Scheduled Scraper 기능을 쓰세요. URL과 일정을 정해 두면 서버 없이 나머지를 자동으로 처리합니다.

다른 방법도 궁금하다면 최고의 자동 웹 스크래핑 도구웹사이트 데이터를 Excel로 스크래핑하는 방법 글도 참고해 보세요.

법적·윤리적 고려사항에 대한 짧은 안내

Amazon의 이용 약관은 “robot, spider, scraper 또는 기타 자동화 수단을 사용해 Amazon Services에 접근하는 행위”를 명시적으로 금지합니다. 다만 최근 미국 판례는 공개 데이터 스크래퍼에 좀 더 우호적인 편입니다. Meta Platforms v. Bright Data(2024년 1월) 사건에서 연방법원은 공개적으로 접근 가능한 데이터를 스크래핑하는 것이, 스크래퍼가 로그인한 “사용자”가 아닐 경우 서비스 약관 위반이 아니라고 판단했습니다.

중요한 차이는 로그인 뒤를 긁느냐입니다(이 튜토리얼이 다루는 부분). Amazon 계정을 만들 때 이미 ToS에 동의했기 때문에, 로그인 뒤 스크래핑은 계약법 문제로 들어갑니다. 공개적으로 보이는 featured reviews를 스크래핑하는 것이 로그인 벽 뒤를 긁는 것보다 법적 위험이 낮습니다.

실무적으로는, 스크래핑한 데이터를 상업적으로 재배포하지 말 것, 공개적으로 표시된 범위를 넘어 개인 사용자 데이터를 수집하지 말 것, robots.txt를 존중할 것, 대규모 또는 상업적 사용 시 법률 자문을 구할 것 등이 기본입니다. 이 내용은 법률 자문이 아닙니다. 법적 쟁점에 대해 더 알고 싶다면 웹 스크래핑의 법적 의미 개요를 참고하세요.

결론: Python으로 Amazon 리뷰를 스크래핑하거나, 아예 코드를 건너뛰세요

이 가이드에서 다룬 내용을 짧게 정리하면 다음과 같습니다.

  • 로그인 벽은 실제로 존재하지만, 쿠키 기반 인증으로 해결할 수 있습니다. 브라우저에서 쿠키 7개를 복사해 requests.Session()에 넣으면 됩니다
  • 며칠마다 깨지는 CSS 클래스 대신 data-hook 셀렉터를 사용하세요
  • 별점 필터와 정렬 조합을 함께 써서 10페이지 제한을 넘고, 제품당 500개 이상의 리뷰에 접근하세요
  • TextBlob으로 빠르게 감성 분석을 하거나, 운영 정확도가 필요하면 Hugging Face Transformers를 사용하세요
  • 봇 방어도 계속 대응해야 합니다. 속도 제한, User-Agent 회전, 지수 백오프, 그리고 규모가 커지면 Residential proxy가 필요합니다

Python은 완전한 제어를 제공하고, 내부 동작을 이해하기에도 가장 좋은 방법입니다. 하지만 목적이 “운영용 데이터 파이프라인을 만들겠다”가 아니라 “금요일까지 경쟁사 리뷰를 스프레드시트로 받아야 한다”라면, 커스텀 스크래퍼를 계속 유지하는 수고가 그만한 값어치를 못 할 수도 있습니다.

Thunderbit는 인증, 셀렉터, 페이지네이션, 내보내기를 클릭 몇 번으로 처리합니다. 무료 플랜을 써서 워크플로에 맞는지 확인해 보세요. Amazon이 봇 방어를 계속 강화할수록, 실시간으로 적응하는 AI 기반 도구는 점점 선택이 아니라 필수가 될 것입니다.

스크래핑 워크플로 영상 가이드는 Thunderbit YouTube 채널에서도 확인할 수 있습니다.

FAQ

1. 로그인하지 않고 Amazon 리뷰를 스크래핑할 수 있나요?

가능은 하지만, 상품 상세 페이지(/dp/{ASIN}/)에 보이는 약 8개의 “featured reviews” 정도만 가능합니다. 정렬, 필터, 페이지네이션이 있는 전체 리뷰 페이지는 2024년 말부터 인증이 필요합니다. 대부분의 비즈니스 용도에서는 로그인 벽을 처리해야 합니다.

2. Amazon 리뷰를 스크래핑하는 것은 합법인가요?

Amazon 이용 약관은 자동 스크래핑을 금지합니다. 다만 최근 미국 판례(Meta v. Bright Data, 2024; hiQ v. LinkedIn)는 공개 접근 가능한 데이터 스크래핑을 지지하는 방향입니다. 로그인 뒤를 긁는 것은 Amazon ToS에 동의한 상태이므로 법적 위험이 더 큽니다. 상업적 사용은 법률 자문을 받는 게 좋습니다.

3. 상품당 Amazon 리뷰를 얼마나 많이 가져올 수 있나요?

Amazon은 정렬 옵션과 별점 필터 조합마다 리뷰 페이지를 10페이지로 제한합니다. 5개 별점 필터 × 2개 정렬 조합을 모두 사용하면 상품당 최대 100페이지, 즉 약 1,000개 리뷰까지 접근할 수 있습니다. 키워드 필터를 쓰면 이론상 더 많아지지만, 중복도 크게 늘어납니다.

4. Amazon 리뷰 스크래핑에 가장 좋은 Python 라이브러리는 무엇인가요?

정적 HTML 파싱에는 requests + BeautifulSoup 조합이 가장 흔하고 안정적입니다. JavaScript 렌더링이 필요한 경우에는 Selenium이 유용합니다. 로그인 벽과 페이지네이션을 자동으로 처리하는 노코드 대안으로는 Thunderbit를 써 보세요.

5. Amazon 스크래핑 시 차단을 피하려면 어떻게 해야 하나요?

10개 이상의 실제 브라우저 문자열에서 User-Agent를 바꾸고, 요청마다 2~5초의 무작위 지연을 넣고, 503/429 오류에는 지수 백오프를 적용하고, 대규모 작업에는 Residential proxy를 쓰세요(데이터센터 IP는 사전에 차단되는 경우가 많습니다). 쿠키도 요청 간 일관되게 유지해야 합니다. 유지보수 없는 방식으로 가려면 Thunderbit가 브라우저 세션을 통해 봇 방어를 자동으로 처리합니다.

더 알아보기

Fawad Khan
Fawad Khan
파와드는 글을 쓰며 생계를 이어가고, 솔직히 꽤 좋아해요. 그는 문구 한 줄이 사람들 기억에 남게 만드는 요소와, 반대로 그냥 스크롤해 지나치게 만드는 요소를 오랜 시간 연구해 왔어요. 마케팅에 대해 물어보면 몇 시간이고 이야기할 거예요. 카르보나라에 대해 물어보면 더 오래 이야기할 거고요.
목차
Thunderbit · AI 웹 데이터 에이전트

1클릭 안에서 어떤 페이지든 데이터 추출

25만 명 이상의 사용자가 신뢰
무료 플랜 제공
웹페이지에서 스프레드시트까지
필요한 내용만 설명하세요 — Thunderbit의 AI 에이전트가 수집하고 Excel, Google Sheets, Airtable, Notion으로 내보냅니다. 시작은 무료입니다.
Chrome Store Rating
PRODUCT HUNT#1 Product of the Week