IT/쇼핑몰

쇼핑몰 크롤링 가이드: Playwright와 PyQt를 활용한 웹 스크래핑

higold 2024. 8. 3. 00:18

파이썬 Playwright와 PyQt를 활용한 웹 스크래핑

안녕하세요! 이번 포스트에서는 Python을 사용하여 무** 쇼핑몰을 크롤링하는 방법에 대해 알아보겠습니다. Playwright를 사용하여 동적 웹페이지를 크롤링하고, PyQt를 이용해 사용자 친화적인 GUI를 만드는 과정을 단계별로 설명하겠습니다.

목차

  1. 환경 설정
  2. 기본 크롤링 스크립트 작성
  3. GUI 애플리케이션 만들기
  4. 한글 저장 문제 해결
  5. 주의사항 및 팁

1. 환경 설정

크롤링 프로젝트를 시작하기 전에 필요한 라이브러리를 설치해야 합니다. 다음 명령어를 사용하여 필요한 패키지를 설치하세요:

pip install playwright PyQt5
playwright install chromium

2. 기본 크롤링 스크립트 작성

먼저, Playwright를 사용하여 무** 쇼핑몰을 크롤링하는 기본 스크립트를 작성해 보겠습니다.

from playwright.sync_api import sync_playwright
import csv
import time

def crawl_musinsa(keyword):
    with sync_playwright() as p:
        browser = p.chromium.launch(headless=True)
        page = browser.new_page()

        url = f"https://www.musinsa.com/search/musinsa/integration?q={keyword}&type=keyword"
        page.goto(url)

        page.wait_for_selector('.sc-1yenj15-0')

        # 페이지 스크롤
        for _ in range(3):
            page.evaluate("window.scrollTo(0, document.body.scrollHeight)")
            time.sleep(2)

        items = page.query_selector_all('.sc-1yenj15-0')

        results = []
        for item in items:
            # 이미지 URL 추출
            img = item.query_selector('.sc-1yenj15-8')
            img_url = img.get_attribute('src') or img.get_attribute('data-original') or 'N/A'

            # 다른 정보 추출 (브랜드, 상품명, 가격 등)
            brand = item.query_selector('.sc-1yenj15-11').inner_text()
            name = item.query_selector('.sc-1yenj15-12').inner_text()
            price = item.query_selector('.sc-1dubb4w-5').inner_text()

            results.append({
                'image_url': img_url,
                'brand': brand,
                'name': name,
                'price': price,
            })

        browser.close()
        return results

# 결과를 CSV 파일로 저장
def save_to_csv(results, filename):
    with open(filename, 'w', newline='', encoding='utf-8') as f:
        writer = csv.DictWriter(f, fieldnames=['image_url', 'brand', 'name', 'price'])
        writer.writeheader()
        writer.writerows(results)

# 메인 실행 부분
if __name__ == "__main__":
    keyword = input("검색할 키워드를 입력하세요: ")
    results = crawl_musinsa(keyword)
    save_to_csv(results, f'musinsa_{keyword}_results.csv')
    print(f"{len(results)}개의 상품 정보를 크롤링하여 저장했습니다.")

이 스크립트는 사용자가 입력한 키워드로 무** 쇼핑몰을 검색하고, 검색 결과의 상품 정보를 크롤링합니다.

3. GUI 애플리케이션 만들기

이제 PyQt를 사용하여 크롤링 스크립트를 제어할 수 있는 GUI 애플리케이션을 만들어 보겠습니다.

import sys
from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QHBoxLayout, QLineEdit, QPushButton, QTextEdit, QProgressBar, QFileDialog
from PyQt5.QtCore import QThread, pyqtSignal

class CrawlerThread(QThread):
    update_progress = pyqtSignal(int)
    update_status = pyqtSignal(str)
    finished = pyqtSignal(list)

    def __init__(self, keyword):
        QThread.__init__(self)
        self.keyword = keyword

    def run(self):
        results = crawl_musinsa(self.keyword)
        self.finished.emit(results)

class CrawlerGUI(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        layout = QVBoxLayout()

        input_layout = QHBoxLayout()
        self.keyword_input = QLineEdit()
        self.crawl_button = QPushButton('크롤링 시작')
        input_layout.addWidget(self.keyword_input)
        input_layout.addWidget(self.crawl_button)

        self.progress_bar = QProgressBar()
        self.status_text = QTextEdit()
        self.status_text.setReadOnly(True)

        layout.addLayout(input_layout)
        layout.addWidget(self.progress_bar)
        layout.addWidget(self.status_text)

        self.setLayout(layout)
        self.setWindowTitle('무신사 크롤러')
        self.setGeometry(300, 300, 400, 300)

        self.crawl_button.clicked.connect(self.start_crawling)

    def start_crawling(self):
        keyword = self.keyword_input.text()
        if not keyword:
            self.status_text.setText("키워드를 입력해주세요.")
            return

        self.crawler_thread = CrawlerThread(keyword)
        self.crawler_thread.update_progress.connect(self.update_progress)
        self.crawler_thread.update_status.connect(self.update_status)
        self.crawler_thread.finished.connect(self.crawling_finished)
        self.crawler_thread.start()

        self.crawl_button.setEnabled(False)
        self.progress_bar.setValue(0)
        self.status_text.clear()

    def update_progress(self, value):
        self.progress_bar.setValue(value)

    def update_status(self, status):
        self.status_text.append(status)

    def crawling_finished(self, results):
        self.crawl_button.setEnabled(True)
        self.status_text.append(f"크롤링 완료! {len(results)}개의 상품 정보를 가져왔습니다.")

        file_path, _ = QFileDialog.getSaveFileName(self, "결과 저장", "", "CSV Files (*.csv)")
        if file_path:
            save_to_csv(results, file_path)
            self.status_text.append(f"결과가 {file_path}에 저장되었습니다.")

if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = CrawlerGUI()
    ex.show()
    sys.exit(app.exec_())

이 GUI 애플리케이션은 사용자가 키워드를 입력하고 크롤링을 시작할 수 있는 인터페이스를 제공합니다. 크롤링 진행 상황을 실시간으로 보여주고, 결과를 CSV 파일로 저장할 수 있습니다.

4. 한글 저장 문제 해결

CSV 파일에 한글이 깨져서 저장되는 문제가 발생할 수 있습니다. 이를 해결하기 위해 save_to_csv 함수를 다음과 같이 수정합니다:

import codecs

def save_to_csv(results, filename):
    with codecs.open(filename, 'w', encoding='utf-8-sig') as f:
        writer = csv.DictWriter(f, fieldnames=['image_url', 'brand', 'name', 'price'])
        writer.writeheader()
        writer.writerows(results)

이렇게 하면 UTF-8 인코딩과 함께 BOM(Byte Order Mark)을 추가하여 Microsoft Excel에서도 한글이 올바르게 표시됩니다.

5. 주의사항 및 팁

  1. 웹 크롤링 시 해당 웹사이트의 이용약관을 반드시 확인하고 준수해야 합니다.
  2. 과도한 요청은 서버에 부담을 줄 수 있으므로 적절한 간격을 두고 크롤링해야 합니다.
  3. 웹사이트의 구조가 변경되면 크롤러가 제대로 작동하지 않을 수 있으므로 주기적으로 코드를 점검해야 합니다.
  4. 크롤링한 데이터는 개인적인 용도로만 사용하고, 상업적 목적으로 사용하지 않도록 주의해야 합니다.
  5. 에러 처리와 예외 상황에 대한 대비를 충분히 해두는 것이 좋습니다.

이상으로 무** 쇼핑몰 크롤링 가이드를 마치겠습니다. 이 글이 여러분의 웹 크롤링 프로젝트에 도움이 되었기를 바랍니다. 궁금한 점이나 추가 설명이 필요한 부분이 있다면 댓글로 남겨주세요. 감사합니다!

반응형