Etsy 스크래핑 방법: 2026 가이드

Etsy의 고급 봇 차단 전략으로 인해 스크래핑이 어렵습니다. Python을 활용해 이러한 장애물을 우회하고 가치 있는 전자상거래 데이터를 추출하는 방법을 알아보세요.
3 분 읽기
How to Scrape Etsy blog image

Etsy는 스크래핑하기 매우 까다로운 사이트로 악명 높습니다. 다양한 차단 전략을 사용하며 웹상에서 가장 정교한 봇 차단 시스템을 보유하고 있습니다. 상세한 헤더 분석부터 끝없이 이어지는 CAPTCHA까지, Etsy는 전 세계 웹 스크래퍼들의 골칫거리입니다. 이러한 장애물을 극복할 수 있다면 Etsy는 상대적으로 스크래핑하기 쉬운 사이트가 됩니다.

Etsy를 스크래핑할 수 있다면, 인터넷이 제공하는 가장 큰 마켓플레이스 중 하나에서 풍부한 소규모 비즈니스 데이터에 접근할 수 있습니다. 오늘 따라오시면, 곧 전문가처럼 Etsy를 스크래핑할 수 있게 될 것입니다. 우리는 Etsy에서 다음과 같은 모든 페이지 유형을 스크래핑하는 방법을 배울 것입니다.

  • 검색 결과
  • 제품 페이지
  • 상점 페이지

시작하기

이 튜토리얼에서는Python Requests와 BeautifulSoup을 주요 도구로 사용할 것입니다. 아래 명령어로 설치할 수 있습니다. Requests는 HTTP 요청을 수행하고 Etsy 서버와 통신하는 기능을 제공합니다. BeautifulSoup은 Python을 사용해 웹 페이지를 파싱할 수 있는 힘을 줍니다. 웹 스크래핑을 위한 BeautifulSoup 사용법 가이드를 먼저 읽어보시길 권장합니다.

Requests 설치

pip install requests

BeautifulSoup 설치

pip install beautifulsoup4

Etsy에서 스크래핑할 내용

Etsy 페이지를 검사하면 중첩된 요소들의 복잡한 구조에 얽힐 수 있습니다. 어디를 살펴봐야 하는지 알면 이 문제를 쉽게 극복할 수 있습니다. Etsy 페이지는 브라우저에서 페이지를 렌더링하기 위해 JSON 데이터를 사용합니다. JSON을 찾을 수 있다면, 문서의 HTML을 깊이 파고들지 않고도 페이지 구축에 사용된 모든 데이터를 찾을 수 있습니다.

검색 결과

Etsy의 검색 페이지에는 JSON 객체 배열이 포함되어 있습니다. 아래 이미지를 보면, 이 모든 데이터는 type="application/ld+json" 속성을 가진 script 요소 안에 들어 있습니다. 자세히 살펴보면, 이 JSON 데이터에는 itemListElement라는 배열이 포함되어 있습니다. 이 배열을 추출할 수 있다면, 페이지 구축에 사용된 모든 데이터를 얻을 수 있습니다.

Inspecting Etsy's search results

제품 정보

제품 페이지도 크게 다르지 않습니다. 아래 이미지를 다시 한번 보시면, type="application/ld+json"을 가진 스크립트 태그가 있습니다. 이 태그에는 제품 페이지 생성에 사용된 모든 정보가 포함되어 있습니다.

Schema example of a product on Etsy

쇼핑몰

아마도 짐작하셨겠지만, 저희 상점 페이지도 동일한 방식으로 구축됩니다. 페이지에서 type="application/ld+json" 을 가진 첫 번째 스크립트 객체를 찾으면 데이터를 확보할 수 있습니다.

Inspecting a shop on Etsy

파이썬으로 Etsy 스크래핑하는 방법

이제 구축에 필요한 모든 구성 요소를 살펴보겠습니다. 앞서 언급했듯이, Etsy는 사이트 접근을 차단하기 위해 다양한 전략을 사용합니다. 우리는 이러한 차단에 대응하기 위한 만능 도구로 Web Unlocker를 사용합니다. 이 도구는 프록시 연결을 관리해 줄 뿐만 아니라, 발생하는 모든 CAPTCHA도 해결해 줍니다. 프록시 없이 시도해 보셔도 좋지만, 초기 테스트에서 Web Unlocker 없이는 Etsy의 차단 시스템을 통과할 수 없었습니다.

웹 언락커 인스턴스를 확보한 후 간단한 딕셔너리를 생성하여 프록시 연결을 설정할 수 있습니다. 데이터 전송 중 암호화를 보장하기 위해 브라이트 데이터의 SSL 인증서를 사용합니다. 아래 코드에서는 SSL 인증서 경로를 지정한 후 사용자 이름, 존 이름, 비밀번호를 사용해 프록시 URL을 생성합니다. 당사 프록시는 모든 요청을 Bright Data의 프록시 서비스 중 하나로 전달하는 맞춤형 URL을 구성하여 구축됩니다.

path_to_cert = "bright-data-cert.crt"

proxies = {
    'http': 'http://brd-customer-<YOUR-USERNAME>-zone-<YOUR-ZONE-NAME>:<YOUR-PASSWORD>@brd.superproxy.io:33335',
    'https': 'http://brd-customer-<YOUR-USERNAME>-zone-<YOUR-ZONE-NAME>:<YOUR-PASSWORD>@brd.superproxy.io:33335'
}

검색 결과

검색 결과를 추출하기 위해 프록시를 사용하여 요청을 보냅니다. 그런 다음 BeautifulSoup을 사용하여 수신된 HTML 문서를 파싱합니다. 스크립트 태그 내부의 데이터를 찾아 JSON 객체로 로드합니다. 그런 다음 JSON에서 itemListElement 필드를 반환합니다.

def etsy_search(keyword):
    encoded_keyword = urlencode({"q": keyword})
    url = f"https://www.etsy.com/search?{encoded_keyword}"
    
    response = requests.get(url, proxies=proxies, verify=path_to_cert)
    soup = BeautifulSoup(response.text, "html.parser")
    script = soup.find("script", attrs={"type": "application/ld+json"})
    full_json = json.loads(script.text)
    return full_json["itemListElement"]

제품 정보

제품 정보 추출 방식은 기본적으로 동일합니다. 유일한 차이점은 itemListElement가 없다는 점입니다. 이번에는 listing_id를 사용해 URL을 생성하고 전체 JSON 객체를 추출합니다.

def etsy_product(listing_id):
    url = f"https://www.etsy.com/listing/{listing_id}/"

    response = requests.get(url, proxies=proxies, verify=path_to_cert)
    soup = BeautifulSoup(response.text, "html.parser")
    script = soup.find("script", attrs={"type": "application/ld+json"})
    return json.loads(script.text)

상점

상점을 추출할 때는 제품 추출과 동일한 방식을 따릅니다. shop_name을 사용하여 URL을 구성합니다. 응답을 받은 후 JSON을 찾아 JSON으로 로드하고 추출된 페이지 데이터를 반환합니다.

def etsy_shop(shop_name):
    url = f"https://www.etsy.com/shop/{shop_name}"

    response = requests.get(url, proxies=proxies, verify=path_to_cert)
    soup = BeautifulSoup(response.text, "html.parser")
    script = soup.find("script", attrs={"type": "application/ld+json"})
    return json.loads(script.text)

데이터 저장

데이터를 추출하자마자 깔끔하게 구조화된 JSON 형태가 됩니다. Python의 기본 파일 처리 기능과 json.dumps()를 사용해 출력을 파일에 기록할 수 있습니다. indent=4를 지정해 사람이 파일을 볼 때 깔끔하고 읽기 쉽게 작성합니다.

with open("products.json", "w") as file:
    json.dump(products, file, indent=4)

모든 것 통합하기

이제 각 부분을 구성하는 방법을 알았으니 모두 합쳐 보겠습니다. 아래 코드는 방금 작성한 함수를 사용해 원하는 데이터를 JSON 형식으로 반환합니다. 그런 다음 각 객체를 개별 JSON 파일에 각각 기록합니다.

import requests
import json
from bs4 import BeautifulSoup
from urllib.parse import urlencode

# 프록시 및 인증서 설정 (고정된 자격 증명)
path_to_cert = "bright-data-cert.crt"
proxies = {
    'http': 'http://brd-customer-<YOUR-USERNAME>-zone-<YOUR-ZONE-NAME>:<YOUR-PASSWORD>@brd.superproxy.io:22225',
    'https': 'http://brd-customer-<YOUR-USERNAME>-zone-<YOUR-ZONE-NAME>:<YOUR-PASSWORD>@brd.superproxy.io:22225'
}

def fetch_etsy_data(url):
    """Etsy 페이지에서 JSON-LD 데이터를 가져와 파싱합니다."""
    try:
        response = requests.get(url, proxies=proxies, verify=path_to_cert)
        response.raise_for_status()
    except requests.exceptions.RequestException as e:
        print(f"요청 실패: {e}")
        return None

    soup = BeautifulSoup(response.text, "html.parser")
    script = soup.find("script", attrs={"type": "application/ld+json"})
    
    if not script:
        print("페이지에서 JSON-LD 스크립트를 찾을 수 없습니다.")
        return None

    try:
        return json.loads(script.text)
    except json.JSONDecodeError as e:
        print(f"JSON 파싱 오류: {e}")
        return None

def etsy_search(keyword):
    """지정된 키워드로 Etsy 검색을 수행하고 결과를 반환합니다."""
    encoded_keyword = urlencode({"q": keyword})
    url = f"https://www.etsy.com/search?{encoded_keyword}"
    data = fetch_etsy_data(url)
    return data.get("itemListElement", []) if data else None

def etsy_product(listing_id):
    """Etsy 리스팅에서 상품 상세 정보를 가져옵니다."""
    url = f"https://www.etsy.com/listing/{listing_id}/"
    return fetch_etsy_data(url)

def etsy_shop(shop_name):
    """Etsy 상점 페이지에서 상점 상세 정보를 가져옵니다."""
    url = f"https://www.etsy.com/shop/{shop_name}"
    return fetch_etsy_data(url)

def save_to_json(data, filename):
    """오류 처리와 함께 데이터를 JSON 파일에 저장합니다."""
    try:
        with open(filename, "w", encoding="utf-8") as file:
            json.dump(data, file, indent=4, ensure_ascii=False, default=str)
        print(f"데이터가 {filename}에 성공적으로 저장되었습니다.")
    except (IOError, TypeError) as e:
        print(f"{filename}에 데이터 저장 중 오류 발생: {e}")

if __name__ == "__main__":
    # 상품 검색
    products = etsy_search("coffee mug")
    if products:
        save_to_json(products, "products.json")

    # 특정 상품
    item_info = etsy_product(1156396477)
    if item_info:
        save_to_json(item_info, "item.json")

    # Etsy shop
    shop = etsy_shop("QuiverCreekCeramic")
    if shop:
        save_to_json(shop, "shop.json")

아래는 products.json의 샘플 데이터입니다.

   {
        "@context": "https://schema.org",
        "@type": "Product",
        "image": "https://i.etsystatic.com/34923795/r/il/8f3bba/5855230678/il_fullxfull.5855230678_n9el.jpg",
        "name": "사진이 들어간 맞춤 커피 머그, 개인화 사진 커피 컵, 그/그녀를 위한 기념일 머그 선물, 남녀 모두에게 맞춤 로고-텍스트 머그",
        "url": "https://www.etsy.com/listing/1193808036/custom-coffee-mug-with-photo",
        "brand": {
            "@type": "Brand",
            "name": "TheGiftBucks"
        },
        "offers": {
            "@type": "Offer",
            "price": "14.99",
            "priceCurrency": "USD"
        },
        "position": 1
    },

데이터셋 사용 고려하기

당사의 데이터셋은 웹 스크래핑에 대한 훌륭한 대안을 제공합니다. 즉시 사용 가능한 Etsy 데이터셋 또는 당사의 다른 전자상거래 데이터셋 중 하나를 구매하여 스크래핑 과정을 완전히 제거할 수 있습니다! 계정을 생성한 후 당사의 데이터셋 마켓플레이스로 이동하세요.

Bright Data's dataset marketplace

“Etsy”를 입력하고 Etsy 데이터 세트를 클릭하세요.

Choosing the Etsy dataset

그러면 수백만 건의 Etsy 데이터 레코드를 손쉽게 이용할 수 있습니다. 샘플 데이터를 다운로드하여 실제 작업 환경을 미리 확인해 볼 수도 있습니다.

A sample of Etsy's dataset records

결론

이 튜토리얼에서는 Etsy 스크래핑을 상세히 살펴보았습니다. 프록시 통합에 대한 집중 강좌를 받았으며, Web Unlocker를 활용해 가장 강력한 봇 차단 기능도 우회하는 방법을 익혔습니다. 데이터 추출 방법과 저장 방법도 알게 되었으며, 스크래핑 작업을 완전히 대체하는 당사의 사전 제작 데이터셋도 경험해 보셨습니다. 어떤 방식으로 데이터를 확보하든 당사가 지원합니다.

지금 가입하여 무료 체험을 시작하세요.