교보문고 전자책 웹사이트에서 전자책 데이터를 수집하는 스크래퍼 를 만들었다.playwright + ray 기반으로 작동해서 빠르고 대용량 스크래핑에 유리하다.🐳 스크래퍼 컨테이너 → 📄 책 데이터 → 🐳 DB 컨테이너n개의 actor가 병렬실행을 위해 준비 (cpu core)여러 책 리스트 page urls 를 n개의 actor 에게 지속적으로 공급seogo-scraper 프로젝트의 README.md 와 동일합니다.
Seogo-Scrpaer는 대규모 전자도서관 데이터를 효율적으로 수집하기 위해 설계된 분산 웹스크래퍼 입니다. 단일 프로세스의 성능 한계를 극복하기 위해 Ray 아키텍처를 도입하였으며, Docker 환경에서 실행 가능합니다.
이 프로젝트는 Docker 환경 위에서 Ray 프레임워크를 활용한 분산 처리 아키텍처를 따릅니다. Playwright를 사용한 다수의 스크래퍼 워커(Scraper Workers)가 병렬로 데이터를 수집하며, 수집된 데이터는 DbActor를 통해 MySQL 데이터베이스에 비동기적으로 저장됩니다.
scraper) : Python 애플리케이션과 Ray 런타임이 구동되는 핵심 컨테이너입니다.db): MySQL 8.0이 구동되며, 영구 데이터 저장을 담당합니다.seogo): 두 컨테이너는 격리된 Docker Bridge 네트워크를 통해 통신을 수행합니다.Task Distribution (Main Process → Workers)
src/main.py가 실행되면 Ray 클러스터를 초기화하고, 설정된 개수(ACTOR_NUMS)만큼의 ScraperWorker를 생성합니다.External Scraping (Workers ↔ Internet)
ScraperWorker는 독립된 Playwright 브라우저 인스턴스를 가집니다.BookData 객체로 변환합니다.Data Aggregation (Workers → DbActor)
DbActor에게 전달(Remote Call)합니다.Persistence (DbActor ↔ MySQL)
DbActor는 aiomysql 커넥션 풀을 사용하여 데이터를 INSERT 또는 UPDATE 합니다.db:3306)를 통해 이루어집니다.| Component | Type | Role & Responsibility |
|---|---|---|
| ScraperWorker | Ray Actor |
Headless Browser(Chromium)를 관리하며 실제 웹 페이지를 탐색 및 파싱합니다. |
| DbActor | Ray Actor |
DB 커넥션 풀을 관리하는 싱글톤 액터입니다. 다수의 워커로부터 저장 요청을 받아 처리합니다. |
| Ray Runtime | Framework |
프로세스 간 통신(IPC) 및 작업 스케줄링을 담당하여 멀티코어 리소스를 극대화합니다. |
| MySQL | Database |
수집된 도서, 저자, 출판사 정보를 관계형 데이터로 저장합니다. |
multiprocessing 사용 시 브라우저 프로세스의 생성/종료 오버헤드가 크고 좀비 프로세스 관리가 어려움.Ray Actor 를 도입하여 브라우저 인스턴스를 미리 띄워두고, 작업(Task)만 할당하는 방식으로 처리 속도를 개선.DbActor 를 운용하여 모든 쓰기 요청을 큐 형태로 받아 비동기(aiomysql)로 처리, 데이터 무결성을 보장.BasePageScraper 추상 클래스로 분리.Worker Actor 코드는 수정하지 않고, 로직 클래스만 갈아끼우는 방식으로 교보문고 외 타 사이트 확장이 용이.| Category | Technology |
|---|---|
| Language | Python 3.10 |
| Distributed | Ray (Actor Model) |
| Browser Automation | Playwright (Async) |
| Database | MySQL 8.0, aiomysql |
| Infrastructure | Docker, Docker Compose |
.
├── Makefile # 실행 명령 관리
├── docker-compose.yml # 컨테이너 오케스트레이션
├── src
│ ├── main.py # Entry Point (Ray Init)
│ ├── core # 프레임워크 코어
│ │ ├── actors # Ray Actor (Worker, DB)
│ │ ├── base # 추상화된 스크래퍼 인터페이스
│ │ └── browser # Playwright 설정 (Stealth 모드)
│ └── providers # 사이트별 구현체 (교보, 알라딘 등)
└── db # DB 스키마 및 초기화
.env 파일 생성하기MYSQL_ROOT_PASSWORD=rootpassword
MYSQL_DATABASE=mydatabase
MYSQL_USER=user
MYSQL_PASSWORD=password
DB_HOST=db
DB_PORT=3306
DB_NAME=mydatabase
DB_USER=user
DB_PASSWORD=password
프로젝트의 루트 디렉토리는 환경 설정을 위해 .env 파일을 사용합니다. .env 파일에는 컨테이너들이 서로 통신하고 데이터베이스를 초기화하는 데 필요한 다양한 정보가 적혀있으며, 보안 상 .env 파일이 레포지토리에는 존재하지 않습니다. 임시 방편으로 루트 디렉토리에 .env 파일을 새로 생성하고 위 내용을 복사하여 붙어넣어 주세요.
# src/core/utils/constants.py
ACTOR_NUMS = 4 # 👈 이 부분
시스템의 동시 처리 능력을 조정하려면 Ray Actor의 개수를 변경해야 합니다. 본인 로컬 머신의 cpu core 갯수 보다 좀 적게 설정하세요.
# docker-compose.yml
services:
db:
# ... (생략)
ports:
- "3306:3306" # 👈 이 부분 (ex. "3307:3306")
이 스크래퍼는 DB 컨테이너를 띄워 통신합니다. 이때 3306 포트를 사용하기 때문에, 로컬 3306 포트가 이미 사용 중인 경우 docker-compose.yml 에서 외부 포트 매핑을 변경할 수 있습니다. 앞의 숫자만 로컬 포트로 변경하고, 콜론 뒤의 컨테이너 내부 포트(3306)는 그대로 유지해야 합니다.
Docker가 설치된 환경에서 단 한 줄의 명령어로 전체 시스템을 실행할 수 있습니다. 실행 전 주의사항을 다시한번 사용하세요!
.env 파일 확인하기# 1. 시스템 실행 (DB & Scraper 컨테이너 구동)
make up
# 2. 스크래핑 시작
make scrape
# 3. 로그 확인 👈 스크래핑 과정을 볼 수 있습니다.
make logs
# 4. 종료 및 정리
make clean
git init 및 .gitignore 파일 생성 (Python의 __pycache__, .venv 등 포함)README.md 기본 파일 생성requirements.txt 파일 생성 (ray, playwright/selenium 등)docker-compose 와 make 를 통해 가상 환경에서 스크래핑, 저장이 잘 되는지 확인전자책~소속도서관 의 관계에 집중하면 되는 것 아닐까?Ray 를 공부하고, 적극적으로 프로젝트에 사용했다.부분 스크래핑, 중지, 재실행 등)전자도서관-전자책 검색인데, 이 DB에서 테마 정보가 의미가 있을까?원하는 도서관, 회사 상호작용 또는 오류 트래킹 등)