Amazon 스크래핑 튜토리얼을 따라 해봤는데 CAPTCHAs, 503 오류, 혹은 완전히 비어 있는 결과만 마주쳤다면 — 당신은 이미 많은 사람들과 같은 상황입니다. 인터넷에 떠도는 Python 기반 Amazon 스크래핑 가이드의 상당수는 2022년이나 2023년에 작성된 것으로, Amazon이 이미 막아버린 셀렉터와 방식에 의존하고 있습니다.
저는 Thunderbit에서 수년간 데이터 추출 도구를 만들어 왔고, 현장에서 분명히 말씀드릴 수 있는 점이 하나 있습니다. Amazon은 안정적으로 스크래핑하기 가장 까다로운 사이트 중 하나입니다. HTML 구조가 계속 바뀌고, 6중 anti-bot 방어 체계를 운영하며, A/B 테스트를 통해 사용자마다 다른 페이지 레이아웃을 보여주기도 합니다. 이 가이드에서는 2025년에도 실제로 작동하는 Python Amazon 스크래퍼를 소개합니다. 검증된 CSS 셀렉터, 여러 겹의 차단 회피 전략, 그리고 대부분의 튜토리얼이 아예 다루지 않는 스케줄링과 내보내기 방법까지 함께 설명하겠습니다. 그리고 Python을 직접 다루지 않고도 데이터를 바로 얻고 싶은 분들을 위해, 로 같은 작업을 클릭 몇 번만에 처리하는 방법도 보여드리겠습니다.
Amazon 상품 스크래핑이란?
Amazon 상품 스크래핑은 Amazon의 상품 상세 페이지와 검색 결과 페이지에서 상품명, 가격, 평점, 리뷰 수, 이미지, 재고 상태 등 공개 데이터를 프로그램으로 추출하는 작업입니다. 수백 개의 상품 정보를 손으로 하나씩 복사하는 대신, 스크래퍼가 각 페이지를 방문해 HTML을 읽고, 원하는 정보를 CSV, Excel, 데이터베이스 같은 구조화된 형식으로 가져옵니다.
아침 커피를 다 마시는 동안 천 개의 상품 페이지를 대신 확인해 주는, 지치지 않는 인턴을 고용한다고 생각하면 됩니다. 다만 이 인턴은 오타도 없고 점심시간도 필요 없습니다.
왜 Python으로 Amazon 상품을 스크래핑할까요?
Amazon은 30개 이상의 카테고리에 걸쳐 약 을 보유하고 있고, 약 이 이 생태계를 움직이고 있습니다. 이제 전체 GMV의 69%는 서드파티 셀러가 차지합니다. 이 방대한 카탈로그의 일부만 수동으로 추적하는 것도 사실상 불가능합니다. 그래서 많은 팀이 Amazon을 스크래핑합니다.
| 활용 사례 | 도움이 되는 사람 | 추출하는 데이터 |
|---|---|---|
| 가격 모니터링 및 재가격 조정 | 이커머스 운영팀, 마켓플레이스 셀러 | 가격, 재고 여부, 셀러 정보 |
| 경쟁사 분석 | 제품 매니저, 브랜드 팀 | 상품 기능, 평점, 리뷰 수 |
| 시장 조사 | 분석가, 신제품 팀 | 카테고리 트렌드, 가격 분포 |
| 리드 생성 | 영업팀 | 셀러 이름, 브랜드 정보, 연락처 |
| 제휴 마케팅 | 콘텐츠 제작자, 딜 사이트 | 가격, 할인 정보, 상품 상세 |
| 재고 추적 | 공급망, 구매팀 | 재고 상태, 배송 예상 |
가격 변동 규모만 봐도 자동화는 필수입니다. Amazon은 하루에 가격을 바꾸고, 평균 상품의 가격도 약 10분마다 갱신됩니다. 반면 Best Buy나 Walmart 같은 경쟁사는 한 달에 약 5만 회 정도만 가격을 변경합니다. 사람이 이 속도를 따라가는 건 불가능합니다.

Python을 쓰면 스크래핑 과정을 완전히 통제할 수 있습니다. 무엇을 추출할지, 오류를 어떻게 처리할지, 데이터를 어디에 저장할지 직접 정할 수 있죠. 다만 그만큼 유지보수, 차단 회피, 그리고 Amazon의 잦은 HTML 변경 대응도 전부 사용자의 몫입니다.
Amazon에서 무엇을 스크래핑할 수 있고, 무엇은 피해야 할까요?
공개된 상품 페이지에서는 보통 다음 정보를 추출할 수 있습니다.
- 상품명(이름, 브랜드)
- 가격(현재가, 정가, 할인 가격)
- 평점(별점 평균)
- 리뷰 수
- 상품 이미지(메인 이미지 URL)
- 재고 / 판매 여부
- ASIN(Amazon Standard Identification Number)
- 상품 설명 및 핵심 포인트
- 셀러 정보
- 상품 옵션(사이즈, 색상 등)
반면 다음은 피해야 합니다.
- 로그인 벽 뒤의 데이터: 확장 리뷰 페이지, 개인 계정 정보, 주문 내역
- 개인 정보: 구매자 이름, 주소, 결제 정보
- 재배포용 저작권 콘텐츠: 상품 설명과 이미지는 분석용으로는 괜찮지만, 자신의 콘텐츠처럼 다시 배포하면 안 됩니다
Amazon의 는 GPTBot, Scrapy, ClaudeBot을 포함한 50개 이상의 봇을 차단하고 있으며, 계정, 장바구니, 위시리스트 같은 경로도 금지합니다. 상품 상세 페이지 자체는 명시적으로 금지되어 있지 않지만, Amazon 서비스 약관은 자동화된 접근을 금지합니다. 법원은 일반적으로 약관 위반(민사 문제)과 CFAA에 따른 형사 위반을 구분해 왔습니다. 이 부분은 가이드 마지막에서 다시 설명하겠습니다.
필요한 도구와 라이브러리
이 튜토리얼에서 사용할 Python 스택은 다음과 같습니다.
| 라이브러리 | 용도 | 사용 이유 |
|---|---|---|
requests | HTTP 요청 | 간단하고 널리 지원됨 |
beautifulsoup4 | HTML 파싱 | CSS 셀렉터 기반 추출이 쉬움 |
lxml | 빠른 HTML 파서 | BeautifulSoup의 파서 백엔드로 사용 |
curl_cffi | TLS 지문 위장 | Amazon 탐지를 우회하는 데 핵심 |
pandas | 데이터 정리 및 내보내기 | DataFrame, CSV/Excel 출력 |
선택 사항(JavaScript 렌더링 콘텐츠용):
selenium또는playwright— 헤드리스 브라우저 자동화
Python 환경 설정하기
터미널을 열고 아래 명령을 실행하세요.
1mkdir amazon-scraper && cd amazon-scraper
2python -m venv venv
3source venv/bin/activate # Windows: venv\Scripts\activate
4pip install requests beautifulsoup4 lxml curl_cffi pandas
설치가 잘 되었는지 확인합니다.
1import requests, bs4, curl_cffi, pandas
2print("All good!")
오류 없이 "All good!"가 출력되면 준비 완료입니다.

대부분의 Amazon 스크래핑 튜토리얼이 실패하는 이유와, 이 글이 다른 점
대부분의 가이드가 건너뛰는 부분이 바로 이 내용이고, 아마도 여러분이 지금 이 글을 보고 있는 이유이기도 합니다.
Amazon은 HTML 구조, 클래스 이름, 요소 ID를 자주 바꿉니다. 스크래핑 업계에서는 DOM 변경과 지문(fingerprint) 변화 때문에 고 보고합니다. 가장 유명한 희생양은? 2018~2023년 수백 개의 튜토리얼에 등장했던 #priceblock_ourprice입니다. 이 ID는 이제 Amazon 상품 페이지에서 더 이상 존재하지 않습니다.
무엇이 깨졌고, 지금은 무엇이 작동하는지 간단히 비교해 보겠습니다.
| 데이터 항목 | 깨진 셀렉터(2024년 이전) | 2025년 작동 셀렉터 |
|---|---|---|
| 가격 | #priceblock_ourprice | div#corePriceDisplay_desktop_feature_div span.a-price .a-offscreen |
| 제목 | #productTitle | span#productTitle (여전히 작동) |
| 평점 | span.a-icon-alt (때때로 문맥 오류) | #acrPopover span.a-icon-alt |
| 리뷰 수 | #acrCustomerReviewCount | span#acrCustomerReviewText |
| 재고 여부 | #availability span | div#availability span.a-size-medium |
이 가이드의 모든 코드 예시는 2025년 실사용 Amazon 페이지에서 테스트했습니다. 2022년식 복붙 코드가 아니라, 실제로 동작하는 CSS 셀렉터와 예상 결과를 함께 보여드리겠습니다.
시작하기 전에
- 난이도: 중급 (기본 Python 지식 필요)
- 소요 시간: 전체 튜토리얼 약 30~45분, 기본 스크래퍼는 약 10분
- 준비물: Python 3.9+, Chrome 브라우저(Amazon 페이지 확인용), 터미널, 그리고 노코드 방식과 비교해 보고 싶다면
1단계: Amazon에 첫 요청 보내기
브라우저에서 아무 Amazon 상품 페이지나 열고 URL을 복사합니다. 먼저 단순한 requests.get()부터 시작해 보겠습니다.
1import requests
2url = "https://www.amazon.com/dp/B0DGNFM9YJ"
3response = requests.get(url)
4print(response.status_code)
5print(response.text[:500])
이 코드를 실행하면 거의 확실하게 503 상태 코드가 나오거나, "To discuss automated access to Amazon data please contact…" 같은 문구가 포함된 페이지가 표시될 것입니다. 이것은 Amazon의 WAF(Web Application Firewall)가 Python 스크립트를 감지한 결과입니다. 적절한 헤더 없이 실행한 requests.get()의 Amazon 대상 성공률은 약 수준입니다.
출력은 대개 503과 차단 페이지 HTML일 것입니다. 정상입니다. 다음 단계에서 해결하겠습니다.
2단계: 사용자 정의 헤더와 TLS 지문 위장 설정하기
이제는 User-Agent만 추가해서는 부족합니다. Amazon은 HTTP 헤더와 TLS 지문을 함께 비교합니다. Chrome 120이라고 주장하면서 TLS 핸드셰이크에서는 Python requests의 흔적이 보이면, 바로 됩니다.
2025년 기준 가장 신뢰할 만한 방법은 브라우저 위장을 지원하는 curl_cffi를 사용하는 것입니다.
1from curl_cffi import requests as cfreq
2headers = {
3 "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
4 "Accept-Language": "en-US,en;q=0.9",
5 "Accept-Encoding": "gzip, deflate, br",
6 "Referer": "https://www.google.com/",
7 "DNT": "1",
8 "Connection": "keep-alive",
9 "Upgrade-Insecure-Requests": "1",
10}
11url = "https://www.amazon.com/dp/B0DGNFM9YJ"
12response = cfreq.get(url, headers=headers, impersonate="chrome124")
13print(response.status_code)
14print(len(response.text))
curl_cffi로 Chrome 124를 위장하면 성공률은 약 까지 올라갑니다. 일반 requests 대비 47배 개선된 수준입니다. 이제는 200 상태 코드와 훨씬 긴 HTML 응답(10만 자 이상)을 볼 수 있어야 합니다.
그래도 503이 나오면 impersonate 값을 바꿔서("chrome131" 등) 다시 시도하거나, 잠시 기다린 뒤 재시도하세요.
3단계: HTML 파싱 후 상품 데이터 추출하기
이제 전체 HTML이 확보되었으니, 검증된 2025년 셀렉터를 사용해 데이터를 추출해 보겠습니다.
1from bs4 import BeautifulSoup
2soup = BeautifulSoup(response.text, "lxml")
3# 상품 제목
4title_el = soup.select_one("span#productTitle")
5title = title_el.get_text(strip=True) if title_el else None
6# 가격
7price_el = soup.select_one(
8 "div#corePriceDisplay_desktop_feature_div span.a-price .a-offscreen"
9)
10if not price_el:
11 price_el = soup.select_one("span.priceToPay .a-offscreen")
12if not price_el:
13 price_el = soup.select_one(".apexPriceToPay .a-offscreen")
14price = price_el.get_text(strip=True) if price_el else None
15# 평점
16rating_el = soup.select_one("#acrPopover span.a-icon-alt")
17rating = rating_el.get_text(strip=True) if rating_el else None
18# 리뷰 수
19reviews_el = soup.select_one("span#acrCustomerReviewText")
20reviews = reviews_el.get_text(strip=True) if reviews_el else None
21# 재고 상태
22avail_el = soup.select_one("div#availability span")
23availability = avail_el.get_text(strip=True) if avail_el else None
24# 메인 이미지 URL
25img_el = soup.select_one("#landingImage")
26image_url = img_el.get("src") if img_el else None
27print(f"Title: {title}")
28print(f"Price: {price}")
29print(f"Rating: {rating}")
30print(f"Reviews: {reviews}")
31print(f"Availability: {availability}")
32print(f"Image: {image_url}")
예상 출력 예시:
1Title: Apple AirPods Pro (2nd Generation) with USB-C
2Price: $189.99
3Rating: 4.7 out of 5 stars
4Reviews: 98,432 ratings
5Availability: In Stock
6Image: https://m.media-amazon.com/images/I/61SUj2...
가격 추출에 여러 개의 대체 셀렉터를 둔 이유는 Amazon이 상품 유형, 할인 여부, A/B 테스트 버전에 따라 서로 다른 컨테이너를 사용하기 때문입니다. 각 추출을 조건문으로 감싸면 셀렉터가 맞지 않아도 스크래퍼가 멈추지 않습니다.
4단계: 검색 결과에서 여러 상품 스크래핑하기
실제 데이터셋을 만들려면 Amazon 검색 결과 페이지에서 시작해 ASIN을 수집한 뒤, 각 상품 상세 페이지를 스크래핑해야 합니다.
1import time
2import random
3def get_search_asins(keyword, max_pages=1):
4 """Amazon 검색 결과에서 ASIN을 수집합니다."""
5 asins = []
6 for page in range(1, max_pages + 1):
7 search_url = f"https://www.amazon.com/s?k={keyword}&page={page}"
8 resp = cfreq.get(search_url, headers=headers, impersonate="chrome124")
9 if resp.status_code != 200:
10 print(f"Search page {page} returned {resp.status_code}")
11 break
12 search_soup = BeautifulSoup(resp.text, "lxml")
13 results = search_soup.select('div[data-component-type="s-search-result"]')
14 for r in results:
15 asin = r.get("data-asin")
16 if asin:
17 asins.append(asin)
18 print(f"Page {page}: found {len(results)} products")
19 time.sleep(random.uniform(2, 5)) # 예의 있는 지연
20 return asins
21asins = get_search_asins("wireless+earbuds", max_pages=2)
22print(f"Collected {len(asins)} ASINs")
각 ASIN은 https://www.amazon.com/dp/{ASIN} 형태의 깔끔한 상품 URL로 연결됩니다. 세션별 파라미터가 붙을 수 있는 검색 결과 전체 URL보다 훨씬 안정적입니다.
5단계: 페이지네이션 처리와 대량 스크래핑
이제 검색 수집과 상세 페이지 스크래핑을 하나의 파이프라인으로 묶어 보겠습니다.
1import pandas as pd
2def scrape_product(asin):
3 """단일 Amazon 상품 상세 페이지를 스크래핑합니다."""
4 url = f"https://www.amazon.com/dp/{asin}"
5 try:
6 resp = cfreq.get(url, headers=headers, impersonate="chrome124")
7 if resp.status_code != 200:
8 return None
9 soup = BeautifulSoup(resp.text, "lxml")
10 title_el = soup.select_one("span#productTitle")
11 price_el = (
12 soup.select_one("div#corePriceDisplay_desktop_feature_div span.a-price .a-offscreen")
13 or soup.select_one("span.priceToPay .a-offscreen")
14 or soup.select_one(".apexPriceToPay .a-offscreen")
15 )
16 rating_el = soup.select_one("#acrPopover span.a-icon-alt")
17 reviews_el = soup.select_one("span#acrCustomerReviewText")
18 avail_el = soup.select_one("div#availability span")
19 img_el = soup.select_one("#landingImage")
20 return {
21 "asin": asin,
22 "title": title_el.get_text(strip=True) if title_el else None,
23 "price": price_el.get_text(strip=True) if price_el else None,
24 "rating": rating_el.get_text(strip=True) if rating_el else None,
25 "reviews": reviews_el.get_text(strip=True) if reviews_el else None,
26 "availability": avail_el.get_text(strip=True) if avail_el else None,
27 "image_url": img_el.get("src") if img_el else None,
28 "url": url,
29 }
30 except Exception as e:
31 print(f"Error scraping {asin}: {e}")
32 return None
33# 수집한 ASIN 전체 스크래핑
34products = []
35for i, asin in enumerate(asins):
36 print(f"Scraping {i+1}/{len(asins)}: {asin}")
37 product = scrape_product(asin)
38 if product:
39 products.append(product)
40 time.sleep(random.uniform(2, 5)) # 요청 사이 무작위 지연
41df = pd.DataFrame(products)
42print(f"\nScraped {len(df)} products successfully")
43print(df.head())
2~5초 사이의 무작위 지연은 매우 중요합니다. 매번 정확히 3초처럼 일정한 간격은 Amazon의 행동 분석에서 수상하게 보일 수 있습니다. 무작위 간격은 사람의 브라우징 패턴을 더 잘 흉내 냅니다.
6단계: 스크래핑한 Amazon 데이터를 CSV로 저장하기
1df.to_csv("amazon_products.csv", index=False, encoding="utf-8-sig")
2print("Saved to amazon_products.csv")
이제 ASIN, 제목, 가격, 평점, 리뷰, 재고, 이미지 URL, 상품 URL이 들어 있는 깔끔한 CSV를 갖게 됩니다. 대부분의 튜토리얼은 여기서 끝나지만, 실제 업무 흐름을 만든다면 CSV는 시작일 뿐입니다.
차단 회피 심화: 스크래퍼를 오래 살리는 방법
Python으로 Amazon 상품을 스크래핑하려는 사람들에게 가장 큰 문제 1위는 입니다. Amazon의 6중 방어 체계에는 IP 평판 분석, TLS 지문 채집, 브라우저 환경 검사, 행동 생체 인식, CAPTCHA, ML 기반 이상 탐지가 포함됩니다. 아래에서는 각 요소에 대응하는 계층형 전략을 소개합니다.
User-Agent와 전체 헤더를 순환하기
고정된 단일 User-Agent는 금방 표시됩니다. 최신 브라우저 문자열을 여러 개 두고 번갈아 사용하세요.
1import random
2USER_AGENTS = [
3 "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36",
4 "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36",
5 "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:121.0) Gecko/20100101 Firefox/121.0",
6 "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Safari/605.1.15",
7]
8def get_headers():
9 return {
10 "User-Agent": random.choice(USER_AGENTS),
11 "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
12 "Accept-Language": "en-US,en;q=0.9",
13 "Accept-Encoding": "gzip, deflate, br",
14 "Referer": "https://www.google.com/",
15 "DNT": "1",
16 "Connection": "keep-alive",
17 }
한 가지 놓치기 쉬운 점은 Accept-Language가 IP의 지리적 위치와 일치해야 한다는 것입니다. 독일 IP에서 Accept-Language: en-US를 보내면 위험 신호로 보일 수 있습니다.
curl_cffi로 TLS 지문 위장하기
이미 2단계에서 다뤘지만, 이 방법의 효과는 다시 강조할 가치가 있습니다. 이 단일 기법이 성공률을 가장 크게 끌어올립니다. 일반 Python requests의 Amazon 성공률은 약 2%입니다. curl_cffi 위장을 사용하면 약 94%까지 올라갑니다. 작동하는 스크래퍼와 고장 난 스크래퍼의 차이입니다.
1from curl_cffi import requests as cfreq
2# 위장 대상 브라우저도 번갈아 사용
3BROWSERS = ["chrome120", "chrome124", "chrome131"]
4response = cfreq.get(
5 url,
6 headers=get_headers(),
7 impersonate=random.choice(BROWSERS),
8)
프록시 순환하기
몇 개의 페이지 이상을 스크래핑하려면 프록시 순환이 필요합니다. Amazon은 IP 주소를 추적하며, 요청이 너무 많은 단일 IP를 차단합니다.
1PROXIES = [
2 "http://user:pass@proxy1.example.com:8080",
3 "http://user:pass@proxy2.example.com:8080",
4 "http://user:pass@proxy3.example.com:8080",
5]
6proxy = random.choice(PROXIES)
7response = cfreq.get(
8 url,
9 headers=get_headers(),
10 impersonate="chrome124",
11 proxies={"http": proxy, "https": proxy},
12)
데이터센터 프록시보다 주거용 프록시가 더 효과적입니다. Amazon은 데이터센터 IP 대역을 선제적으로 차단하는 편이기 때문입니다. 다만 비용은 더 비쌉니다. 작은 프로젝트라면 부터 시작해 필요에 따라 확장할 수 있습니다.
속도 제한과 지수 백오프
경쟁사 글에서는 거의 다루지 않지만, 매우 중요합니다. 503이나 CAPTCHA 응답을 받았을 때 즉시 다시 시도하지 마세요. 그건 영구 차단으로 가는 지름길입니다.
1import time
2import random
3def fetch_with_backoff(url, max_retries=3):
4 """실패 시 지수 백오프로 URL을 가져옵니다."""
5 for attempt in range(max_retries):
6 response = cfreq.get(
7 url,
8 headers=get_headers(),
9 impersonate=random.choice(BROWSERS),
10 )
11 if response.status_code == 200:
12 return response
13 # 지터가 포함된 지수 백오프
14 wait = min(2 ** attempt + random.uniform(0, 1), 30)
15 print(f"Attempt {attempt+1} failed ({response.status_code}). Waiting {wait:.1f}s...")
16 time.sleep(wait)
17 return None # 재시도 종료
wait = min(2^attempt + jitter, max_delay) 공식은 지연 시간이 2초, 4초, 8초...처럼 늘어나되, 너무 길어지지는 않도록 합니다. 무작위 지터는 재시도 패턴이 고정적으로 보이지 않게 해 줍니다.
JavaScript 렌더링 콘텐츠를 위한 Selenium 또는 Playwright 대체 수단
일부 Amazon 페이지, 특히 동적 가격 위젯이나 옵션 선택기가 있는 페이지는 JavaScript 렌더링이 필요합니다. curl_cffi가 불완전한 HTML을 돌려줄 때는 헤드리스 브라우저가 대안입니다.
1from playwright.sync_api import sync_playwright
2def scrape_with_browser(url):
3 with sync_playwright() as p:
4 browser = p.chromium.launch(headless=True)
5 page = browser.new_page()
6 page.goto(url, wait_until="domcontentloaded")
7 page.wait_for_timeout(3000) # JS 렌더링 대기
8 html = page.content()
9 browser.close()
10 return html
이 방식은 더 느립니다. 페이지당 3~5초가 걸리며, curl_cffi는 1초도 안 걸릴 수 있습니다. 필요할 때만 사용하세요.
제 경험상 curl_cffi만으로도 90% 이상의 Amazon 상품 페이지는 브라우저 없이 처리할 수 있습니다.
차단 회피 요약
| 기법 | 난이도 | 효과 | 대부분의 튜토리얼에서 다루는가? |
|---|---|---|---|
| 맞춤 User-Agent | 쉬움 | 낮음(Amazon이 패턴을 감지함) | 예 |
| 전체 헤더 순환 | 쉬움 | 중간 | 드묾 |
| TLS 위장(curl_cffi) | 중간 | 높음(~94% 성공률) | 거의 없음 |
| 프록시 순환 | 중간 | 높음 | 아주 짧게 언급하거나 아예 없음 |
| 속도 제한 + 지수 백오프 | 쉬움 | 중간 | 아님 |
| Selenium/Playwright 대체 | 중간 | 높음(JS 콘텐츠용) | 언급만 하고 시연은 안 함 |
CSV를 넘어: Google Sheets, Airtable 등으로 내보내기
제가 검토한 모든 튜토리얼은 CSV 내보내기에서 멈춥니다. 하지만 실제 비즈니스 워크플로우에서는 Google Sheets, 데이터베이스, Airtable, Notion 같은 도구로 데이터가 들어가야 합니다.
gspread로 Google Sheets에 내보내기
먼저 Google 서비스 계정을 한 번만 설정합니다.
- → APIs & Services → Credentials로 이동
- 서비스 계정을 만들고 JSON 키 파일 다운로드
~/.config/gspread/service_account.json에 저장- 대상 스프레드시트를 JSON 파일의
client_email과 공유
그다음:
1import gspread
2from gspread_dataframe import set_with_dataframe
3gc = gspread.service_account()
4sh = gc.open("Amazon Scrape Data")
5worksheet = sh.sheet1
6set_with_dataframe(worksheet, df)
7print("Data exported to Google Sheets!")
이 코드는 DataFrame 전체를 Google Sheet에 바로 씁니다. 실시간 공유가 가능하고, 대시보드용으로도 바로 사용할 수 있습니다.
로컬 분석용 SQLite 저장
더 큰 데이터셋이나 이력 추적에는 SQLite가 적합합니다. 서버 설정 없이 단일 파일만 있으면 됩니다.
1import sqlite3
2conn = sqlite3.connect("amazon_products.db")
3df.to_sql("products", conn, if_exists="append", index=False)
4print(f"Stored {len(df)} products in SQLite")
5# 나중에 조회:
6historical = pd.read_sql_query(
7 "SELECT * FROM products WHERE price IS NOT NULL ORDER BY rowid DESC LIMIT 100",
8 conn,
9)
노코드 대안
Python 내보내기 스크립트를 직접 관리하고 싶지 않다면, 는 Google Sheets, Airtable, Notion, Excel, CSV, JSON으로 무료 내보내기를 제공합니다. Airtable과 Notion에서 바로 렌더링되는 이미지 필드도 포함됩니다. gspread 설정도, API 자격 증명도, 코드도 필요 없습니다. 기존 도구로 데이터를 흘려보내야 하는 팀이라면 시간을 크게 절약할 수 있습니다.
자동 Amazon 스크래핑 예약하기 — 빠진 한 장
가격 모니터링과 재고 추적은 한 번 실행하는 작업이 아니라 반복 실행이 필요합니다. 그런데 경쟁사 글 중 예약 실행을 다루는 곳은 거의 없었습니다. Python 스크래퍼를 자동화하는 방법을 소개하겠습니다.
Cron 작업(Linux/macOS)
crontab을 엽니다.
1crontab -e
매일 오전 6시에 스크래퍼를 실행하는 줄을 추가합니다.
10 6 * * * cd /path/to/amazon-scraper && /path/to/venv/bin/python scraper.py >> ~/scraper.log 2>&1
또는 6시간마다 실행:
10 */6 * * * cd /path/to/amazon-scraper && /path/to/venv/bin/python scraper.py >> ~/scraper.log 2>&1
Windows 작업 스케줄러
run_scraper.bat 파일을 만듭니다.
1@echo off
2cd /d "C:\path\to\amazon-scraper"
3call venv\Scripts\activate
4python scraper.py
5deactivate
그다음 작업 스케줄러를 열어 기본 작업 만들기 → 트리거(Daily, Hourly 등) 설정 → 작업: "Start a program" 선택 → run_scraper.bat 파일 지정.
GitHub Actions(무료 플랜)
인프라 없이 클라우드에서 예약 실행하려면:
1name: Amazon Scraper
2on:
3 schedule:
4 - cron: "0 6 * * *" # UTC 기준 매일 오전 6시
5 workflow_dispatch: # 수동 실행
6jobs:
7 scrape:
8 runs-on: ubuntu-latest
9 steps:
10 - uses: actions/checkout@v3
11 - name: Set up Python
12 uses: actions/setup-python@v4
13 with:
14 python-version: "3.11"
15 - name: Install dependencies
16 run: pip install -r requirements.txt
17 - name: Run scraper
18 run: python scraper.py
19 - name: Commit results
20 run: |
21 git config user.name 'GitHub Actions'
22 git config user.email 'actions@github.com'
23 git add data/
24 git diff --staged --quiet || git commit -m "Update scraped data"
25 git push
프록시 자격 증명은 GitHub Secrets에 저장하면 무료 자동 스크래핑 파이프라인이 완성됩니다.
노코드 대안: Thunderbit의 Scheduled Scraper
cron 문법이나 클라우드 인프라를 관리하고 싶지 않은 팀이라면 Thunderbit의 내장 를 사용할 수 있습니다. "매일 오전 8시" 또는 "매주 월요일"처럼 자연어로 일정을 설명하고, Amazon URL을 추가한 뒤 "Schedule"을 누르면 됩니다. 터미널도, YAML 파일도, 배포 파이프라인도 필요 없습니다. 지속적인 가격/재고 모니터링이 필요한 이커머스 팀에 특히 유용합니다.
Python 직접 구현 vs. 스크래퍼 API vs. 노코드: 어떤 방법을 써야 할까요?
포럼에서 정말 자주 보이는 질문인데, 상위 랭킹 글들 중 구조적으로 답해 주는 곳은 거의 없습니다. 솔직하게 정리해 보겠습니다.
| 기준 | Python + BS4/curl_cffi | 스크래퍼 API (ScraperAPI, Oxylabs) | 노코드(Thunderbit) |
|---|---|---|---|
| 설정 시간 | 30–60분 | 10–20분 | 약 2분 |
| 코딩 필요 여부 | 예(Python) | 예(API 호출) | 없음 |
| 차단 방어 내장 | 아니요(DIY) | 예 | 예 |
| JS 렌더링 처리 | Selenium/Playwright 사용 시 가능 | 제공사별 상이 | 예(Browser 또는 Cloud 모드) |
| 예약 실행 | 직접 구현(cron/클라우드) | 일부 제공 | 내장 |
| 비용 | 무료(+ 프록시 비용) | 월 $30–100+ | 무료 플랜 제공 |
| 유지보수 | 높음(셀렉터가 자주 깨짐) | 낮음 | 없음(AI가 적응) |
| 적합한 대상 | 완전한 제어를 원하는 개발자 | 대규모 안정성이 필요한 팀 | 빠른 작업이 필요한 비개발자, 비즈니스 사용자 |
배우고 싶고, 모든 세부를 커스터마이즈하고 싶으며, 지속적인 유지보수가 괜찮다면 Python이 좋은 선택입니다. 스크래퍼 API는 차단 방어를 대신 처리해 주지만 그래도 코드는 필요합니다. 반면 Thunderbit은 영업, 이커머스 운영, 또는 단순히 데이터만 필요한 사람에게 가장 빠른 경로입니다. 셀렉터도, 코드도, Amazon HTML이 바뀔 때마다 손댈 유지보수도 없습니다.
Thunderbit이 Amazon 상품을 2번 클릭으로 스크래핑하는 방법
물론 제가 만든 제품이라 편향이 있을 수 있습니다. 하지만 실제 워크플로우는 정말 이렇습니다.
- 설치
- Amazon 검색 결과나 상품 페이지로 이동
- "AI Suggest Fields" 클릭(또는 즉시 사용 가능한 Amazon 스크래퍼 템플릿 사용)
- "Scrape" 클릭
Thunderbit의 AI는 페이지를 읽고, 데이터 구조를 파악한 다음, 모든 정보를 깔끔한 표로 추출합니다. Excel, Google Sheets, Airtable, Notion으로 무료 내보내기도 가능합니다. 진짜 장점은 다음 주에 Amazon이 HTML을 바꿔도(그리고 실제로 바꿀 텐데), Thunderbit의 AI는 자동으로 적응한다는 점입니다. 깨진 스크립트도, 셀렉터 업데이트도 없습니다.
상품 목록에 상세 페이지 데이터를 보강할 때는 Thunderbit의 Subpage Scraping 기능이 링크를 따라 상품 페이지로 자동 이동해 이미지, 설명, 옵션 같은 추가 필드를 가져옵니다. Python으로 구현하려면 꽤 많은 추가 코드가 필요한 작업입니다.
Python Amazon 스크래퍼를 장기적으로 안정적으로 유지하는 팁
Python 방식으로 간다면 유지보수 부담을 줄이는 방법은 다음과 같습니다.
- 셀렉터를 정기적으로 확인하세요. Amazon은 자주 바꿉니다. 이 글을 북마크해 두세요. 셀렉터 표는 변화에 맞춰 업데이트하겠습니다.
- 성공률을 모니터링하세요. 200 응답과 503/CAPTCHA 응답의 비율을 추적하세요. 성공률이 80% 아래로 떨어지면 알림(간단한 이메일만으로도 충분)을 설정하세요.
- 원본 HTML을 저장하세요. 파싱된 데이터와 함께 전체 HTML 응답을 보관하세요. 셀렉터가 바뀌어도 다시 스크래핑하지 않고 재파싱할 수 있습니다.
- 프록시와 User-Agent를 자주 순환하세요. 고정 지문은 대량 실행 시 몇 시간 안에 표시됩니다.
- 지수 백오프를 사용하세요. 차단 직후에는 절대 즉시 재시도하지 마세요.
- Docker로 컨테이너화하세요. 배포와 이식성을 위해 스크래퍼를 Docker 컨테이너로 감싸세요.
- 데이터 검증을 추가하세요. 가격이 숫자인지, 평점이 1~5 범위인지, 제목이 비어 있지 않은지 확인하세요. 한 팀은 검증 계층을 추가한 뒤 고 보고했습니다.
또는 이 모든 것이 너무 번거롭게 느껴진다면, Thunderbit 같은 노코드 도구가 더 적합한지 고려해 보세요. 더 빠른 길을 선택하는 데 부끄러울 건 없습니다. 저도 스크래퍼를 수없이 디버깅해 본 입장에서 말하지만, 때로는 가장 좋은 코드는 아예 쓰지 않아도 되는 코드입니다.
Amazon 스크래핑 시 법적·윤리적 고려 사항
Amazon 스크래핑 이야기를 할 때마다 빠지지 않는 부분이니, 법적 환경을 간단히 짚고 가겠습니다.
- 공개 데이터 스크래핑은 미국에서 일반적으로 합법입니다. 획기적인 판결(2022)은 공개 데이터 접근이 CFAA를 위반하지 않는다고 정리했습니다. 최근의 (2024)와 (2024)도 이 원칙을 강화했습니다.
- Amazon의 약관은 자동 접근을 금지합니다. 이는 형사 문제가 아니라 민사 문제(계약 위반)입니다. 법원은 일반적으로 이 둘을 구분합니다.
- **Amazon v. Perplexity(2025)**는 Amazon 페이지의 AI 스크래핑과 관련된 진행 중인 사건입니다. 2026년 3월 예비 금지명령이 내려졌습니다. 주목할 만합니다.
- 공개 페이지에만 한정하세요. 로그인 보호 콘텐츠, 개인 정보, 인증 뒤의 정보는 스크래핑하지 마세요.
- 속도 제한을 지키세요. Amazon 서버를 과도하게 두드리지 마세요. 요청 간 2~5초 지연은 합리적입니다.
- 데이터를 책임 있게 사용하세요. 분석 목적의 스크래핑과 저작권 콘텐츠 재배포는 다릅니다.
- 대규모 상업적 사용이라면 법률 자문을 받으세요. 특히 EU에서는 GDPR이 개인정보에 적용됩니다.
더 자세한 내용은 가이드를 참고하세요.
마무리
이제 여러분은 2025년에 검증된 셀렉터, "User-Agent만 바꾸면 된다" 수준을 훨씬 넘어서는 다층 차단 회피 전략, 지속적인 모니터링을 위한 실용적인 예약 방법, 그리고 Google Sheets나 데이터베이스, 팀에서 쓰는 각종 도구로 데이터를 보내는 내보내기 방법까지 갖춘 Python Amazon 스크래퍼를 갖게 되었습니다.
핵심 요약:
- Python + curl_cffi + BeautifulSoup 조합은 TLS 위장과 함께 쓸 때 완전한 제어권과 약 94%의 성공률을 제공합니다
- 차단 회피는 여러 층이 필요합니다: 헤더 순환, TLS 위장, 프록시 순환, 속도 제한, 지수 백오프
- 스케줄링을 통해 일회성 스크립트를 지속적인 모니터링 파이프라인으로 바꿀 수 있습니다(cron, GitHub Actions, 또는 Thunderbit 내장 스케줄러)
- CSV를 넘어서는 내보내기 — Google Sheets, SQLite, Airtable, Notion — 에서 실제 비즈니스 가치가 나옵니다
- Thunderbit은 셀렉터 디버깅보다 데이터 분석에 시간을 쓰고 싶은 비개발자에게 2번 클릭으로 가능한 대안을 제공합니다
이 코드를 직접 써 보고 싶다면, 이 가이드의 모든 예시는 그대로 복사해 실행할 수 있습니다. 코딩을 아예 건너뛰고 싶다면, 으로 Amazon에서 노코드 방식을 바로 테스트해 볼 수 있습니다.
더 알고 싶다면 , , 가이드를 참고하세요. 에서 단계별 안내 영상도 볼 수 있습니다.
행운을 빕니다 — 그리고 다음 Amazon 업데이트 때까지 셀렉터가 무사하길 바랍니다.
자주 묻는 질문
1. 왜 내 Python Amazon 스크래퍼는 몇 번 요청 후 차단되나요?
Amazon은 IP 평판 분석, TLS 지문(JA3/JA4), 브라우저 환경 감지, 행동 생체 인식, CAPTCHA, ML 기반 이상 탐지를 포함한 6중 방어 체계를 사용합니다. 단순히 User-Agent만 넣은 requests 스크립트의 성공률은 약 정도입니다. 안정적으로 접근하려면 TLS 위장(curl_cffi), 전체 헤더 순환, 프록시 순환, 무작위 지터가 포함된 속도 제한이 필요합니다.
2. 2025년에 Amazon 상품 스크래핑에 가장 좋은 Python 라이브러리는 무엇인가요?
가장 큰 개선 효과를 주는 것은 TLS 위장 HTTP 요청용 curl_cffi입니다. 여기에 HTML 파싱용 BeautifulSoup4와 lxml, 데이터 정리 및 내보내기용 pandas, JavaScript 렌더링 콘텐츠를 위한 대체 수단으로 Selenium 또는 Playwright를 함께 쓰면 됩니다. Python은 스크래핑 개발자의 가 사용하는 언어입니다.
3. Amazon 상품 데이터를 스크래핑하는 것은 합법인가요?
미국에서는 공개 데이터 스크래핑이 일반적으로 합법이며, hiQ v. LinkedIn 및 Meta v. Bright Data 같은 판례가 이를 뒷받침합니다. 다만 Amazon의 서비스 약관은 자동 접근을 금지합니다. 법원은 일반적으로 약관 위반(민사)과 형사 위반을 구분합니다. 로그인 보호 콘텐츠는 피하고, 속도 제한을 지키며, 대규모 상업적 사용 전에는 반드시 법률 자문을 받으세요.
4. 코드를 전혀 쓰지 않고 Amazon을 스크래핑할 수 있나요?
가능합니다. 같은 도구를 쓰면 Chrome 확장 프로그램으로 Amazon 상품을 2번 클릭만에 스크래핑할 수 있습니다. AI 기반 필드 감지가 데이터를 자동으로 구조화하며, Excel, Google Sheets, Airtable, Notion으로 무료 내보내기도 가능합니다. Amazon의 HTML이 바뀌어도 Thunderbit의 AI는 수동 업데이트 없이 적응합니다.
5. Amazon은 HTML 셀렉터를 얼마나 자주 바꾸며, 스크래퍼는 어떻게 최신 상태로 유지하나요?
자주, 그리고 예고 없이 바뀝니다. 스크래핑 업계에서는 DOM 변경 때문에 의 크롤러가 매주 수정이 필요하다고 보고합니다. 앞서 가려면 스크래퍼 성공률을 모니터링하고, 원본 HTML을 저장해 재파싱할 수 있게 하며, 실제 페이지에서 셀렉터를 정기적으로 확인해야 합니다. 또는 Thunderbit 같은 AI 도구를 쓰면 자동 적응이 가능해 유지보수 부담을 없앨 수 있습니다.
더 알아보기