Amazon Sponsored Ad Placement Scraper가 96% 성공률을 달성하는 방법

발행: (2025년 12월 26일 오전 10:35 GMT+9)
13 min read
원문: Dev.to

Source: Dev.to

(번역할 텍스트를 제공해 주시면 한국어로 번역해 드리겠습니다.)

🚨 문제: 불완전한 데이터가 잘못된 의사결정을 초래한다

작년, 경쟁사의 광고 전략을 분석하던 중 우리 팀은 흥미로운 현상을 발견했습니다. 동일한 키워드 “wireless earbuds” 를 서로 다른 도구로 스크래핑했을 때, 스폰서드 프로덕트 광고 수가 크게 달라졌으며—때로는 두 배 차이가 났습니다.

처음엔 타이밍 문제라고 생각했습니다. 하지만 실제 상황은 더 우려스러웠습니다: 우리는 Amazon이 “의심스러운 방문자”에게 보여주도록 선택한 단순화된 버전만을 보고 있었던 것입니다.

이 사실을 알게 되면서 Amazon의 안티‑스크래핑 메커니즘을 파헤치는 긴 여정에 들어섰고, 10여 개가 넘는 솔루션을 테스트하며 상당한 프록시‑IP 예산을 소모했습니다. 오늘은 이러한 고생 끝에 얻은 인사이트를 공유하여 여러분이 같은 함정에 빠지지 않도록 돕고자 합니다.

Source:

💰 왜 Amazon은 SP 광고 데이터를 이렇게 철저히 보호할까

솔직히 말하자면: Sponsored Products 광고는 Amazon의 돈 프린터다. 광고 클릭 하나하나가 실제 매출로 이어지기 때문에, Amazon은 이 데이터를 다섯 가지 정교한 장벽을 통해 거의 집착하듯 보호한다.

🔒 장벽 #1 – IP 평판 점수 시스템

  • Amazon은 방대한 IP 평판 데이터베이스를 운영한다.
  • 데이터센터 IP, 알려진 프록시 서버, 그리고 자주 회전하는 동적 IP는 고위험으로 표시된다.
  • 일반 사용자 행동과 일치하지 않는 요청 패턴(예: 초당 여러 카테고리 검색 페이지에 접근)으로 나타나는 경우, 주거용 프록시 IP도 다운그레이드 처리를 유발할 수 있다.

시스템이 완전히 차단하는 것이 아니라, 광고 노출을 선택적으로 감소시키거나 낮은 입찰가의 광고만 표시한다.

🎭 장벽 #2 – JavaScript 동적 렌더링 함정

  • SP 광고는 클라이언트‑사이드 JavaScript를 통해 삽입되므로, 단순 HTTP 요청만으로는 전체 내용을 캡처할 수 없다.
  • Amazon 프런트엔드 코드에는 다양한 탐지 메커니즘이 포함되어 있다:
검사 항목감지 내용
✅ Window 객체 완전성누락되거나 변조된 속성
✅ WebGL 지문 검증가짜 또는 누락된 GPU 정보
navigator.webdriver 탐지자동화 플래그
✅ Canvas 지문헤드리스 브라우저 서명

이상 징후가 감지되면 광고 노출 렌더링 로직이 조용히 건너뛰어진다. 스크랩한 페이지는 정상처럼 보이지만 가장 핵심적인 데이터가 누락된다.

🌍 장벽 #3 – 지리적 위치 및 ZIP‑코드 매칭

  • 동일 키워드라도 ZIP 코드에 따라 완전히 다른 광고가 표시될 수 있다(판매자가 특정 지역을 타깃팅하기 때문).
  • 요청 IP의 지리적 위치가 선언된 ZIP‑코드 파라미터와 일치하지 않거나 명백한 국경 간 프록시를 사용할 경우, Amazon은 해당 요청을 의심스러워 하며 광고 내용을 제한한다.

🕵️ 장벽 #4 – 요청 빈도 및 세션 연속성

  • 실제 사용자는 검색 결과 페이지에 머무르고, 스크롤하고, 클릭한다; 스크래퍼는 기계적인 규칙성을 보이는 경우가 많다.
  • Amazon의 행동 분석 엔진은 각 세션의 경로를 추적해 비정상적인 패턴이 발견되면 광고 노출 전략을 강화한다.

누적 효과: 동일 IP 또는 디바이스 지문에서 여러 의심 행동이 겹치면 평판 점수가 지속적으로 하락하고, 결국 블랙리스트에 올려진다.

🎲 장벽 #5 – 광고 배치 블랙‑박스 알고리즘

첫 네 장벽을 모두 우회하더라도, SP 광고 자체는 실시간 입찰 블랙‑박스 시스템이다. 광고 수량, 위치, 구체적인 제품은 복잡하고 독점적인 알고리즘에 의해 동적으로 결정된다.

🛠️ Solution Matrix – From Small to Large Scale

규모일일 요청 수기술성공률월 비용핵심 포인트
소규모10,000전문 API 서비스90‑96 %+$3,500+• 안티 스크래핑 메커니즘을 우회하기 위해 대규모 자원을 투입
• 플랫폼 알고리즘 변경을 지속적으로 추적
• 구조화된 데이터 출력
• 성공적인 요청을 기준으로 청구.

📊 실제 테스트 데이터 비교

100개의 키워드와 5개의 ZIP 코드를 대상으로 14 일간 테스트

솔루션평균 성공률고경쟁 성공률비용 / 1K
자체 구축 Selenium68 %52 %$45
ScraperAPI43 %38 %$60+
Bright Data79 %74 %$120
Pangolin Scrape API96.3 %92 %$35

🏆 왜 Pangolin이 최고의 성능을 발휘할까요?

  • Optimized IP network – specifically for Amazon; each IP undergoes long‑term “account nurturing.”
  • Dynamic fingerprint generation – unique but reasonable browser fingerprints for every request.
  • Intelligent request scheduling – algorithms adjust strategies based on real‑time feedback.

💻 코드 예제 – 빠른 시작

옵션 1: 기본 Puppeteer (소규모 테스트)

const puppeteer = require('puppeteer-extra');
const StealthPlugin = require('puppeteer-extra-plugin-stealth');
puppeteer.use(StealthPlugin());

async function scrapeSponsoredAds(keyword, zipCode) {
    const browser = await puppeteer.launch({
        headless: true,
        args: [
            '--no-sandbox',
            '--disable-blink-features=AutomationControlled'
        ]
    });

    const page = await browser.newPage();

    // Set realistic viewport & user‑agent
    await page.setViewport({ width: 1280, height: 800 });
    await page.setUserAgent(
        'Mozilla/5.0 (Windows NT 10.0; Win64; x64) ' +
        'AppleWebKit/537.36 (KHTML, like Gecko) ' +
        'Chrome/124.0.0.0 Safari/537.36'
    );

    // Optional: add extra headers to mimic a real browser
    await page.setExtraHTTPHeaders({
        'Accept-Language': 'en-US,en;q=0.9',
        'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8'
    });

    // Build Amazon search URL with ZIP code parameter
    const url = `https://www.amazon.com/s?k=${encodeURIComponent(keyword)}&ref=nb_sb_noss_2&zipCode=${zipCode}`;
    await page.goto(url, { waitUntil: 'networkidle2', timeout: 60000 });

    // Wait for SP ad container to load (adjust selector if needed)
    await page.waitForSelector('[data-component-type="sponsored-product"]', { timeout: 15000 });

    // Extract ad data
    const ads = await page.evaluate(() => {
        const nodes = document.querySelectorAll('[data-component-type="sponsored-product"]');
        return Array.from(nodes).map(node => ({
            title: node.querySelector('h2')?.innerText.trim(),
            asin: node.getAttribute('data-asin'),
            price: node.querySelector('.a-price-whole')?.innerText.trim(),
            rating: node.querySelector('.a-icon-alt')?.innerText.trim(),
            url: node.querySelector('a')?.href
        }));
    });

    await browser.close();
    return ads;
}

// Example usage
scrapeSponsoredAds('wireless earbuds', '10001')
    .then(ads => console.log(JSON.stringify(ads, null, 2)))
    .catch(err => console.error('Scrape error:', err));

옵션 2: Pangolin Scrape API 사용 (모든 규모)

# Bash – simple curl request
curl -X POST https://api.pangolin-scrape.com/v1/amazon/sp \
     -H "Authorization: Bearer YOUR_API_KEY" \
     -H "Content-Type: application/json" \
     -d '{
           "keyword": "wireless earbuds",
           "zip_code": "10001",
           "locale": "en_US"
         }'
# Python – wrapper library example
import requests

API_KEY = "YOUR_API_KEY"
endpoint = "https://api.pangolin-scrape.com/v1/amazon/sp"

payload = {
    "keyword": "wireless earbuds",
    "zip_code": "10001",
    "locale": "en_US"
}

headers = {
    "Authorization": f"Bearer {API_KEY}",
    "Content-Type": "application/json"
}

response = requests.post(endpoint, json=payload, headers=headers)
if response.ok:
    ads = response.json()
    print(ads)
else:
    print("Error:", response.status_code, response.text)

📌 Takeaways

  1. 스크래퍼를 제한하고 있는 장벽을 식별하세요 – 먼저 IP 평판을 확인하고, 그 다음 JS 렌더링, 지리 매칭, 요청 빈도, 마지막으로 입찰 알고리즘 순으로 진행합니다.
  2. 규모에 맞는 솔루션을 선택하세요 – 소규모 프로젝트는 잘 튜닝된 Selenium 설정만으로도 충분하고, 중규모는 헤드리스 브라우저 팜이 필요하며, 대규모는 Amazon의 변동에 지속적으로 대응하는 전용 API가 최적입니다.
  3. 동적 지문 생성 및 현실적인 세션 행동에 투자하세요 – 정적 지문은 한계가 있으며, 트래픽이 실제 쇼핑객을 얼마나 잘 흉내 내느냐에 따라 성공률이 높아집니다.

스크래핑을 즐기세요 (책임감 있게)!

Amazon Sponsored Ad Placement Scraper

아래는 Amazon에서 Sponsored Product (SP) 광고 배치 데이터를 수집할 때 사용할 수 있는 두 가지 접근 방식입니다.

Option 1 – Headless Browser (Puppeteer)

const puppeteer = require('puppeteer');

async function getSponsoredAds(keyword, zipCode = '10001') {
    const browser = await puppeteer.launch({ headless: true });
    const page = await browser.newPage();

    // Set a realistic user‑agent and location cookie
    await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36');
    await page.setCookie({
        name: 'zip',
        value: zipCode,
        domain: '.amazon.com'
    });

    // Build the search URL and navigate to it
    const searchUrl = `https://www.amazon.com/s?k=${encodeURIComponent(keyword)}`;
    await page.goto(searchUrl, { waitUntil: 'networkidle2' });

    // Simulate human behavior
    await page.evaluate(() => {
        window.scrollBy(0, Math.random() * 500 + 300);
    });
    await new Promise(r => setTimeout(r, 2000 + Math.random() * 3000));

    // Extract sponsored ads from the results page
    const sponsoredAds = await page.evaluate(() => {
        const ads = [];
        document
            .querySelectorAll('[data-component-type="s-search-result"]')
            .forEach((el, i) => {
                const badge = el.querySelector('.s-label-popover-default');
                if (badge?.textContent.includes('Sponsored')) {
                    ads.push({
                        position: i + 1,
                        asin: el.getAttribute('data-asin'),
                        title: el.querySelector('h2')?.textContent.trim()
                    });
                }
            });
        return ads;
    });

    await browser.close();
    return sponsoredAds;
}

// Example usage
// (async () => {
//     const ads = await getSponsoredAds('bluetooth speaker', '90001');
//     console.log(ads);
// })();

Option 2 – Pangolin API (Production‑Ready)

const axios = require('axios');

class PangolinSPAdScraper {
    constructor(apiKey) {
        this.apiKey = apiKey;
        this.baseUrl = 'https://api.pangolinfo.com/scrape';
    }

    async getSponsoredAds(keyword, options = {}) {
        const response = await axios.post(this.baseUrl, {
            api_key: this.apiKey,
            type: 'search',
            amazon_domain: 'amazon.com',
            keyword: keyword,
            zip_code: options.zipCode || '10001',
            output_format: 'json'
        });

        return response.data.search_results
            .filter(item => item.is_sponsored)
            .map(item => ({
                position: item.position,
                asin: item.asin,
                title: item.title,
                price: item.price,
                adType: item.sponsored_type
            }));
    }
}

// Usage
const scraper = new PangolinSPAdScraper('YOUR_API_KEY');
scraper.getSponsoredAds('bluetooth speaker', { zipCode: '90001' })
    .then(ads => console.log(`Found ${ads.length} ad placements`))
    .catch(err => console.error('Error:', err));

🎯 나의 권장 사항

규모권장 접근법
소규모Selenium/Puppeteer를 사용해 데이터를 파악해 보세요.
중규모탄탄한 개발팀이 있다면 작은 클러스터를 구축하고, 그렇지 않다면 바로 API를 사용하세요.
대규모전문 API를 사용하세요—절감되는 시간이 비용보다 훨씬 큽니다.

핵심 원칙: 항상 실제 데이터를 통해 스크래핑 효과를 검증하세요. “일부 데이터를 스크랩할 수 있다”에 만족하지 말고, “모든 관련 데이터를 캡처했는가?”를 물어보세요.

🏁 Bottom Line

아마존의 데이터 기반 마켓플레이스에서 SP‑ad 데이터의 정확성은 비즈니스 의사결정에 직접적인 영향을 미칩니다. 광고 배치를 50 %만 수집하는 스크래퍼는 키워드 경쟁이 낮다고 오해하게 만들어 입찰이나 재고 선택을 잘못하게 할 수 있습니다.

신뢰할 수 있는 Sponsored Ad Placement Scraper를 구축하는 기술 장벽이 높기 때문에, 대부분의 팀은 핵심 제품 로직에 자원을 할당하고 데이터 수집을 신뢰할 수 있는 서비스에 아웃소싱하는 것이 유리합니다.

🔗 리소스

  • Pangolin 웹사이트:
  • API 문서:
  • 개발자 콘솔:
Back to Blog

관련 글

더 보기 »