웹 크롤링의 실전: 11번가 상품 정보 자동 수집 시스템 구축하기

들어가며

웹 크롤링은 온라인 데이터 수집의 핵심 기술로, 마케팅, 가격 비교, 시장 분석 등 다양한 분야에서 활용되고 있습니다. 특히 이커머스 시장에서는 경쟁사 상품 정보 모니터링, 가격 동향 파악 등을 위해 자동화된 크롤링 시스템이 필수적입니다. 이번 포스팅에서는 국내 대표 이커머스 플랫폼인 11번가의 상품 정보를 자동으로 수집하는 Python 기반 크롤링 시스템을 구축하는 과정을 공유하고자 합니다.

웹 크롤링의 도전 과제

웹 크롤링에서 가장 큰 도전 중 하나는 웹사이트 구조가 지속적으로 변경된다는 점입니다. 특히 대형 이커머스 플랫폼은 UI/UX 개선, 보안 강화, 마케팅 전략 등의 이유로 주기적으로 웹사이트 구조를 업데이트합니다. 이러한 변화는 기존 크롤러가 정상 작동하지 않게 만드는 주요 원인이 됩니다.

다음으로는 데이터 저장 및 관리의 문제입니다. 크롤링한 데이터를 효율적으로 저장하고, 이미지 등의 바이너리 데이터를 함께 관리하는 것은 간단한 작업이 아닙니다. 특히 대량의 데이터를 다룰 때는 파일 시스템 권한, 저장 공간, 데이터 중복 문제 등 다양한 이슈가 발생할 수 있습니다.

크롤링 시스템 아키텍처 설계

효과적인 크롤링 시스템은 모듈화된 아키텍처를 갖추는 것이 중요합니다. 저희가 구축한 시스템은 다음과 같은 구조로 설계되었습니다:

  1. 유틸리티 모듈(utils.py): 파일 시스템 관리, 네트워크 요청, 데이터 저장 등 기본 기능
  2. 파서 모듈(product_parser.py): HTML 요소에서 상품 정보 추출 로직
  3. 크롤러 모듈(crawler.py): 웹페이지 탐색 및 데이터 수집 프로세스
  4. 메인 모듈(main.py): 사용자 인터페이스 및 실행 진입점

이러한 모듈화 접근 방식은 코드 유지보수를 용이하게 만들고, 웹사이트 구조 변화에 빠르게 대응할 수 있게 해줍니다.

Playwright를 활용한 동적 콘텐츠 처리

현대 웹사이트는 JavaScript를 활용한 동적 콘텐츠가 많아, 단순 HTTP 요청으로는 모든 정보를 수집하기 어렵습니다. 이러한 환경에서는 브라우저 자동화 도구가 필수적입니다. 우리 시스템은 Microsoft의 Playwright를 채택했습니다.

# 브라우저 설정
browser = p.chromium.launch(
    headless=False,
    args=[
        "--disable-blink-features=AutomationControlled",
        "--no-sandbox",
        "--disable-web-security",
    ]
)

# 자동화 감지 방지 스크립트
context.add_init_script('''
Object.defineProperty(navigator, 'webdriver', {
    get: () => false,
});
''')

Playwright는 Chrome, Firefox, Safari 등 다양한 브라우저를 지원하며, 자동화 감지 우회, 스크린샷 캡처, 네트워크 요청 모니터링 등 고급 기능을 제공합니다.

HTML 구조 분석과 선택자 전략

웹 크롤링의 핵심은 HTML 구조를 정확히 이해하고, 원하는 정보를 추출하기 위한 적절한 선택자(selector)를 설계하는 것입니다. 11번가와 같은 복잡한 이커머스 사이트에서는 다양한 선택자 전략이 필요합니다:

  1. 다중 선택자 접근 방식: 여러 선택자를 우선순위에 따라 시도하여 필요한 요소 추출
  2. JavaScript DOM 검사: 자바스크립트로 DOM 요소를 직접 확인
  3. 예외 처리와 대체 경로: 예상한 선택자가 실패할 경우 대체 방법 구현
# DOM 요소 탐색 전에 JS로 확인해보기
js_check = page.evaluate('''() => {
    const selectors = [
        '.search_list .item',
        '.search_list li',
        '.prd_item',
        '.product_item',
        'li.c-search-item',
        '.l_search_content li',
        'div[class*="product"] li'
    ];
    
    const result = {};
    for (const selector of selectors) {
        const elements = document.querySelectorAll(selector);
        result[selector] = elements.length;
    }
    return result;
}''')

print("JS DOM 요소 확인 결과:")
for selector, count in js_check.items():
    print(f"- {selector}: {count}개 요소 발견")

이 접근 방식은 웹사이트 구조가 변경되더라도 크롤러가 적응할 수 있는 유연성을 제공합니다.

강건한 이미지 다운로드 시스템

이커머스 크롤링에서 상품 이미지는 매우 중요한 데이터입니다. 하지만 이미지 다운로드는 네트워크 지연, 서버 오류, 잘못된 URL 등 다양한 이유로 실패할 수 있습니다. 우리의 시스템은 다음과 같은 방식으로 이 문제를 해결합니다:

  1. URL 유효성 검증: 다운로드 전 URL 형식 확인
  2. 재시도 메커니즘: 실패 시 여러 번 재시도하는 로직
  3. 콘텐츠 타입 확인: 응답이 실제 이미지인지 확인
  4. 대체 경로 저장: 기본 경로에 저장 실패 시 대체 경로 사용
# 이미지 다운로드 시도
download_success, saved_path = download_image(img_url, image_filepath, max_retries=3)
if download_success and saved_path:
    if is_debug:
        print(f"이미지 다운로드 성공: {saved_path}")
    actual_image_path = saved_path  # 실제 저장된 경로로 업데이트
else:
    print(f"이미지 다운로드 실패: {img_url}")
    actual_image_path = None

디버깅 및 로깅 전략

효과적인 크롤링 시스템은 강력한 디버깅 및 로깅 기능을 갖추어야 합니다. 우리 시스템에는 다음과 같은 디버깅 기능이 포함되어 있습니다:

  1. 페이지 스크린샷: 각 단계에서 브라우저 상태 캡처
  2. HTML 소스 저장: 전체 페이지 및 개별 상품 HTML 저장
  3. 상세 로깅: 각 과정의 성공/실패 상태 기록
  4. DOM 구조 분석: 페이지 로드 후 DOM 구조 정보 추출
# 페이지 스크린샷 저장
screenshot_path = os.path.join(folders['debug'], f'11st_page_{page_num}.png')
page.screenshot(path=screenshot_path)
print(f"스크린샷 저장됨: {screenshot_path}")

# HTML 소스 저장 (디버깅용)
source_path = os.path.join(folders['debug'], f'11st_page_{page_num}_source.html')
with open(source_path, 'w', encoding='utf-8') as f:
    f.write(page.content())
print(f"HTML 소스 저장됨: {source_path}")

이러한 디버깅 정보는 크롤러가 실패했을 때 원인 분석과 문제 해결에 큰 도움이 됩니다.

시스템 적응성 향상을 위한 기법

웹사이트 변화에 유연하게 대응하기 위해 우리 시스템은 다음과 같은 적응 기법을 사용합니다:

  1. 다양한 URL 형식 시도: 사이트의 URL 구조 변화에 대응
  2. 다층적 선택자 전략: 광범위한 선택자부터 구체적 선택자까지 시도
  3. JS 기반 DOM 검사: 페이지 구조를 실시간으로 분석
  4. 정규식 패턴 매칭: 데이터 추출에 유연한 패턴 사용
# 11번가 PC 버전 URL 사용
page_url = f'https://search.11st.co.kr/pc/total-search?kwd={quote(keyword)}'
if page_num > 1:
    page_url += f'&pageNo={page_num}'

크롤링 윤리와 법적 고려사항

웹 크롤링을 구현할 때는 항상 윤리적, 법적 측면을 고려해야 합니다:

  1. robots.txt 준수: 웹사이트의 크롤링 정책 확인
  2. 요청 속도 제한: 서버에 과도한 부하를 주지 않도록 제어
  3. 개인정보 보호: 개인식별정보 수집 제한
  4. 저작권 존중: 수집한 데이터의 사용 범위 제한

우리 시스템은 요청 간 무작위 시간 간격을 두어 서버 부하를 최소화하고 있습니다:

# 다음 페이지 처리 전 대기
wait_time = random.uniform(8, 12)
print(f"다음 페이지로 넘어가기 전 {wait_time:.1f}초 대기 중...")
time.sleep(wait_time)

결론 및 향후 과제

이 포스팅에서는 11번가 상품 정보를 자동으로 수집하는 크롤링 시스템의 구축 과정을 살펴보았습니다. 모듈화된 아키텍처, 강건한 선택자 전략, 효과적인 디버깅 시스템이 성공적인 웹 크롤링의 핵심 요소임을 확인했습니다.

향후 개선 방향으로는:

  1. 분산 크롤링 시스템: 여러 IP에서 동시에 크롤링하여 효율성 향상
  2. 머신러닝 기반 선택자 자동 생성: 웹사이트 변화에 자동 적응
  3. 데이터베이스 통합: JSON 대신 관계형 또는 NoSQL DB 활용
  4. 실시간 모니터링 대시보드: 크롤링 성능 및 결과 실시간 확인

웹 크롤링은 기술적 도전과 함께 지속적인 개선이 필요한 분야입니다. 특히 이커머스와 같이 변화가 빠른 도메인에서는 코드의 유연성과 적응성이 무엇보다 중요합니다. 이 포스팅이 여러분의 웹 크롤링 프로젝트에 도움이 되길 바랍니다.


코멘트

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다