TRENDSHIFT 딥다이브 · 2026-06-27

NanmiCoder/MediaCrawler 딥다이브
— JS 역공학 없이 7개 중국 SNS를 한 방에 긁는 Playwright 크롤러

소셜미디어 크롤러 레포 중 오랫동안 중국 GitHub 상위권에 자리한 프로젝트다. 핵심 아이디어는 단순하고 영리하다 — 로그인한 브라우저 세션을 그대로 재사용하면 API 서명 로직을 해독하지 않아도 된다. 소홍서(小红书/Xiaohongshu), 더우인(抖音/Douyin), 콰이서우(快手/Kuaishou), 비리비리(B站/Bilibili), 웨이보(微博/Weibo), 바이두 티에바(贴吧/Tieba), 즈후(知乎/Zhihu) — 7개 플랫폼 크롤러를 동일한 추상 인터페이스로 묶었다. (저장소: NanmiCoder/MediaCrawler · Python 3.11+ · Playwright · 비상업 학습 라이선스 · ★25k+ · TrendShift 상위 레포)

⚠️ 중요 주의: 이 문서는 '브라우저 자동화·비동기 Python 아키텍처'를 학습하는 목적으로 작성된 공부자료입니다. 크롤러 실행은 대상 플랫폼 이용약관·robots.txt·개인정보보호법을 위반할 수 있습니다. 상업적 이용은 라이선스상 명시적으로 금지됩니다.
목차
  1. 프로젝트 한줄 요약
  2. 왜 주목받는가
  3. 기술 스택 전체 지도
  4. 아키텍처 심화 분석
  5. 디렉토리 구조 해부
  6. 학습 포인트 (기술별)
  7. 시스템 요구사항 · 설치
  8. 직접 해볼 수 있는 실습 과제
  9. 관련 기술 심화 학습 로드맵
  10. 핵심 키워드 사전
  11. 참고 링크

1프로젝트 한줄 요약

이 레포가 무엇을 하는 물건인가.

핵심 메시지

"중국 SNS 7개를 긁고 싶은데 API 서명 해독이 너무 어렵다면 — 그냥 브라우저를 통째로 조종하면 된다"

MediaCrawler의 핵심은 JS 역공학(reverse engineering)을 하지 않는다는 선택이다. 플랫폼이 아무리 복잡한 서명 알고리즘을 숨겨도, 로그인된 브라우저가 그 서명을 대신 만들어 준다. Playwright로 실제 Chrome을 제어해 로그인하고, 그 세션 쿠키·토큰을 저장해두면 이후 API 요청에서 서명이 자동으로 붙는다.

이 원리 하나로 소홍서·더우인·콰이서우·비리비리·웨이보·티에바·즈후 7개 플랫폼 크롤러를 동일한 Python 추상 클래스 위에 얹었다.

용어
크롤러 (Web Crawler / Spider)
웹사이트를 자동으로 방문하여 데이터를 수집하는 프로그램. 사람이 브라우저로 하는 행동(클릭, 스크롤, 로그인)을 코드로 흉내 낸다. 규모·목적·방법에 따라 법적 허용 범위가 크게 달라진다.
용어
Playwright
Microsoft가 만든 브라우저 자동화 라이브러리. Chromium(Chrome/Edge), Firefox, WebKit(Safari) 등 실제 브라우저를 Python 코드로 제어한다. 로그인·클릭·스크롤·네트워크 가로채기 모두 가능. Selenium보다 빠르고, 비동기(async/await) 방식을 지원한다.
용어
로그인 상태 유지 (Login Context Persistence)
한 번 사람이 직접 로그인하면, 그 세션 정보(쿠키, localStorage 등)를 디스크에 저장한다. 이후 실행 시 저장된 상태를 불러와 "이미 로그인된 브라우저"처럼 행동한다. API 서명이나 토큰을 별도로 해독할 필요가 없다.

2왜 주목받는가

트렌딩 이유 · JS 역공학 대신 브라우저를 통째로 빌리는 영리함.

중국 SNS 플랫폼들은 API 요청에 복잡한 암호화 서명을 붙인다. 소홍서의 X-S 헤더, 더우인의 _signature 파라미터 등이 대표적이다. 이를 분석(역공학)하려면 JavaScript 난독화 해제, 알고리즘 재구현이 필요하고, 플랫폼이 업데이트할 때마다 다시 해야 한다. MediaCrawler는 이 문제를 우회한다 — 브라우저가 서명을 만들어 주니까 코드가 만들 필요가 없다.

함정 · 위험
JS 역공학 크롤러의 한계

서명 알고리즘을 직접 재구현하면, 플랫폼이 알고리즘을 바꾸는 순간 크롤러가 무용지물이 된다. 유지보수 비용이 매우 높고, 법적으로도 기술적 보호조치 우회에 해당할 수 있어 더 위험하다.

또한 API 서명 해독 자체가 매우 어렵다 — 소홍서 하나만 해도 보안팀이 수시로 업데이트한다.

해결 · 장점
MediaCrawler의 접근: 브라우저를 빌린다

Playwright로 실제 Chrome을 열고, 사용자가 한 번 QR코드로 로그인하면 세션을 저장한다. 이후 크롤러가 실행될 때 이 세션을 그대로 재사용한다. 브라우저 내부에서 JavaScript 표현식으로 서명값을 뽑아 쓰면, 플랫폼 업데이트와 무관하게 서명이 자동으로 생성된다.

결과적으로 코드 유지보수 부담이 크게 줄고, 기술 진입장벽도 낮아진다. 이 점이 ★25k를 넘게 받은 핵심 이유다.

또 다른 주목 이유는 통일된 아키텍처다. 7개 플랫폼이 모두 AbstractCrawler, AbstractLogin, AbstractStore라는 동일한 ABC(Abstract Base Class) 인터페이스를 구현한다. 새 플랫폼을 추가할 때 인터페이스만 보고 작성하면 된다. 저장 방식도 CSV·JSON·JSONL·MySQL·SQLite·MongoDB·Excel 7가지를 팩토리 패턴으로 지원한다.

비교 항목JS 역공학 크롤러MediaCrawler (Playwright 방식)
기술 난이도매우 높음 (암호화 분석)중간 (Python + 브라우저 자동화)
유지보수플랫폼 업데이트마다 재작업브라우저가 서명을 처리하므로 안정적
탐지 위험비정상 요청 패턴 감지 쉬움실제 브라우저 핑거프린트 사용
속도빠름 (HTTP 직접 요청)느림 (브라우저 기동 오버헤드)
법적 위험기술적 보호조치 우회 가능성동일하게 이용약관 위반 가능성 있음

3기술 스택 전체 지도

백엔드·브라우저 자동화·저장소·인프라 각 레이어 상세.

핵심 언어 · 런타임

구성 요소버전/설명역할
Python3.11+메인 런타임. asyncio 기반 비동기 처리
uv최신초고속 Python 패키지 관리자 (pip 대체). pyproject.toml 기반
Node.jsLTSplaywright install 시 브라우저 바이너리 관리에 필요

브라우저 자동화

구성 요소버전역할
Playwright1.45.0브라우저 제어 핵심. BrowserContext, Page, CDP 연결 모두 담당
stealth.min.js내장 (libs/)크롤러 감지 방지용 JS 삽입 스크립트. navigator.webdriver 숨김
CDP (Chrome DevTools Protocol)내장로컬 설치된 Chrome/Edge를 직접 제어. 더 강력한 반탐지 능력

HTTP · 네트워크

구성 요소버전역할
httpx0.28.1비동기 HTTP 클라이언트. 각 플랫폼 API 직접 호출에 사용
requests2.32.3동기 HTTP. 일부 유틸리티 용도
tenacity8.2.2재시도(retry) 데코레이터. 네트워크 실패 시 자동 재시도

저장소 (Storage) — 팩토리 패턴으로 7가지 동적 선택

옵션라이브러리특징
CSV내장 csv가장 간단. 엑셀로 바로 열 수 있음
JSON / JSONL내장 json + aiofilesJSONL은 줄 단위 JSON, 대용량에 적합
MySQL / PostgreSQLaiomysql 0.2.0 / asyncpg비동기 RDB. SQLAlchemy + Alembic 마이그레이션
SQLiteaiosqlite 0.21.0로컬 파일 DB. 별도 서버 불필요
MongoDBmotor 3.3.0비동기 NoSQL. 비정형 데이터에 유리
Excelopenpyxl 3.1.2.xlsx 직접 생성. 비동기 flush 방식

데이터 처리 · 분석

라이브러리역할
pandas 2.2.3데이터 조작 및 분석
jieba 0.42.1중국어 형태소 분석 (댓글 분석 시)
wordcloud 1.9.3댓글 키워드 워드클라우드 이미지 생성
matplotlib 3.9.0차트·시각화
Pillow 12.1.0이미지 처리
opencv-python이미지 처리 고급 기능
parsel 1.9.1CSS/XPath 기반 HTML 파싱 (Scrapy의 파싱 라이브러리)

프록시 · IP 풀

구성 요소설명
ProxyIpPoolIP 프록시 풀 관리 클래스. 유효성 검증 포함
쾌다이리 (kuaidaili)유료 중국 IP 프록시 서비스 어댑터 내장
완두 HTTP (wandouhttp)또 다른 유료 프록시 서비스 어댑터
Static Proxy사용자 지정 고정 프록시 URL 지원

플랫폼 어댑터 (media_platform/)

플랫폼코드명주요 특징
소홍서 (Xiaohongshu)xhsplaywright_sign.py로 JS 표현식 서명 추출. rednote.com 해외판 지원
더우인 (Douyin)dy틱톡 중국판. 강력한 반봇 시스템
콰이서우 (Kuaishou)ks短视频 2위 플랫폼
비리비리 (Bilibili)bili동영상·댓글·크리에이터 홈 지원
웨이보 (Weibo)wb중국판 트위터. 이미지·동영상 저장 지원
바이두 티에바 (Tieba)tieba바이두 포럼 커뮤니티
즈후 (Zhihu)zhihu중국판 Quora. 질문·답변 수집

4아키텍처 심화 분석

브라우저 → CDP → API 가로채기 → 파서 → 저장 흐름 + 핵심 설계 패턴.

시스템 구조도

┌─────────────────────────────────────────────────────────────────┐ │ main.py (진입점) │ │ CrawlerFactory.create_crawler(platform) → AbstractCrawler │ └────────────────────┬────────────────────────────────────────────┘ │ ┌──────────▼───────────┐ │ XiaoHongShuCrawler │ (각 플랫폼별로 동일 구조) │ DouYinCrawler │ │ BilibiliCrawler ... │ └──────────┬───────────┘ │ async start() ┌──────────▼──────────────────────────────────┐ │ Playwright 런타임 │ │ │ │ ┌──────────────────────────────────────┐ │ │ │ 모드 A: 일반 모드 │ │ │ │ playwright.chromium.launch() │ │ │ │ + stealth.min.js 삽입 │ │ │ │ (감지 방지용 JS 덮어쓰기) │ │ │ └──────────────────────────────────────┘ │ │ │ │ ┌──────────────────────────────────────┐ │ │ │ 모드 B: CDP 모드 (기본값) │ │ │ │ 사용자 로컬 Chrome/Edge 찾기 │ │ │ │ --remote-debugging-port=9222 실행 │ │ │ │ playwright.connect_over_cdp() │ │ │ │ (실제 브라우저 = 최강 반탐지) │ │ │ └──────────────────────────────────────┘ │ └──────────┬──────────────────────────────────┘ │ ┌──────────▼───────────────────────────────────┐ │ 로그인 처리 (AbstractLogin) │ │ │ │ ① 저장된 세션 확인 (USER_DATA_DIR) │ │ → 세션 유효? 바로 크롤 시작 │ │ → 세션 만료? 아래로 │ │ ② 로그인 방식 선택 (LOGIN_TYPE) │ │ qrcode: QR 이미지 터미널 표시 → 앱 스캔 │ │ phone: SMS 인증 수신 대기 │ │ cookie: 수동 쿠키 문자열 입력 │ │ ③ 로그인 완료 → browser_context 저장 │ └──────────┬───────────────────────────────────┘ │ ┌──────────▼────────────────────────────────────┐ │ API 클라이언트 (AbstractApiClient) │ │ 예: XiaoHongShuClient (httpx 기반) │ │ │ │ pong() 체크 → 세션 유효 확인 │ │ update_cookies(browser_context) → 쿠키 동기화 │ │ │ │ 서명 생성 핵심: │ │ browser_context.pages[0].evaluate( │ │ "() => window._webmsxyw('/api/...')" │ │ ) → JS 내부 서명 함수를 브라우저가 직접 실행 │ └──────────┬────────────────────────────────────┘ │ HTTP 요청 (서명 자동 포함) ┌──────────▼──────────────────────────────────┐ │ 파서 · 추출기 (extractor.py) │ │ parsel / Pydantic 모델 검증 │ │ 게시글·댓글·크리에이터 데이터 구조화 │ └──────────┬──────────────────────────────────┘ │ ┌──────────▼──────────────────────────────────┐ │ 저장소 (AbstractStore) │ │ StoreFactory.create_store() │ │ CSV | JSON | JSONL | MySQL | SQLite │ │ PostgreSQL | MongoDB | Excel │ └─────────────────────────────────────────────┘

핵심 설계 패턴 3가지

1. 추상 클래스 + 팩토리 패턴 (Strategy + Factory)

모든 플랫폼 크롤러는 AbstractCrawler를 상속받아 start(), search(), launch_browser()를 반드시 구현해야 한다. CrawlerFactory가 플랫폼 문자열(예: "xhs")을 받아 해당 클래스 인스턴스를 반환한다. 저장소도 XhsStoreFactory가 동일한 패턴으로 7가지 백엔드 중 하나를 선택한다.

# CrawlerFactory 구조 (main.py)
class CrawlerFactory:
    CRAWLERS: dict[str, Type[AbstractCrawler]] = {
        "xhs": XiaoHongShuCrawler,
        "dy": DouYinCrawler,
        "ks": KuaishouCrawler,
        "bili": BilibiliCrawler,
        "wb": WeiboCrawler,
        "tieba": TieBaCrawler,
        "zhihu": ZhihuCrawler,
    }
    @staticmethod
    def create_crawler(platform: str) -> AbstractCrawler:
        crawler_class = CrawlerFactory.CRAWLERS.get(platform)
        return crawler_class()

2. 브라우저 컨텍스트를 통한 서명 주입

플랫폼의 JS 서명 함수는 역공학하지 않는다. 대신 Playwright의 page.evaluate()로 브라우저 내 JS 환경에서 직접 서명 함수를 호출한다. 소홍서를 예로 들면 브라우저 안에서 실행되는 window._webmsxyw 같은 내부 함수를 그대로 불러 서명값을 뽑아낸다.

3. 비동기 세마포어 기반 동시성 제어

asyncio의 Semaphore로 동시 요청 수를 MAX_CONCURRENCY_NUM으로 제한한다. 크롤러가 플랫폼 서버에 과부하를 주지 않도록 CRAWLER_MAX_SLEEP_SEC 기반 랜덤 슬립도 삽입된다. tenacity@retry 데코레이터로 네트워크 오류를 투명하게 재시도한다.

5디렉토리 구조 해부

각 폴더가 어떤 역할을 맡는가.

MediaCrawler/ ├── main.py ← 진입점. CrawlerFactory, cleanup, wordcloud 후처리 ├── config/ │ ├── base_config.py ← 플랫폼·크롤링·저장 전역 설정 (PLATFORM, KEYWORDS, SAVE_DATA_OPTION 등) │ ├── db_config.py ← DB 연결 문자열 (MySQL, PostgreSQL, MongoDB, SQLite) │ ├── xhs_config.py ← 소홍서 전용 설정 (XHS_INTERNATIONAL 등) │ ├── dy_config.py ← 더우인 전용 설정 │ └── ... ← 나머지 플랫폼별 config │ ├── base/ │ └── base_crawler.py ← AbstractCrawler, AbstractLogin, AbstractStore, │ AbstractApiClient — 모든 인터페이스 정의 │ ├── media_platform/ ← 플랫폼별 크롤러 구현체 │ ├── xhs/ │ │ ├── core.py ← XiaoHongShuCrawler (start/search/login 흐름) │ │ ├── client.py ← XiaoHongShuClient (httpx 기반 API 호출) │ │ ├── login.py ← QR코드/휴대폰/쿠키 로그인 구현 │ │ ├── playwright_sign.py ← page.evaluate()로 브라우저 서명 추출 │ │ ├── extractor.py ← 게시글·댓글·크리에이터 데이터 파싱 │ │ └── field.py ← Enum: 검색 정렬 타입 등 │ ├── douyin/ │ ├── kuaishou/ │ ├── bilibili/ │ ├── weibo/ │ ├── tieba/ │ └── zhihu/ ← 위와 동일한 구조 반복 │ ├── store/ ← 저장 구현체 │ ├── excel_store_base.py ← ExcelStoreBase (비동기 flush 관리) │ ├── xhs/ │ │ ├── _store_impl.py ← XhsCsvStoreImplement, XhsJsonlStoreImplement 등 │ │ └── xhs_store_media.py ← 이미지·동영상 파일 저장 │ └── ... ← 나머지 플랫폼별 store │ ├── database/ │ ├── db.py ← DB 초기화·종료 (SQLAlchemy async engine) │ ├── models.py ← ORM 모델 (게시글, 댓글, 크리에이터 테이블) │ └── mongodb_store_base.py ← MongoDB 기반 저장 추상화 │ ├── proxy/ │ ├── proxy_ip_pool.py ← ProxyIpPool: IP 로드·검증·순환 │ ├── proxy_mixin.py ← 크롤러에 프록시 기능을 섞어주는 Mixin │ └── providers/ ← kuaidaili, wandouhttp 어댑터 │ ├── tools/ │ ├── cdp_browser.py ← CDPBrowserManager: 로컬 Chrome 감지·실행·연결 │ ├── async_file_writer.py ← AsyncFileWriter: 워드클라우드 생성 │ ├── utils.py ← 로거, User-Agent, 프록시 포맷 변환 등 │ └── app_runner.py ← asyncio 이벤트 루프 + SIGINT 핸들러 │ ├── model/ │ └── m_xiaohongshu.py ← Pydantic 모델: NoteUrlInfo, CreatorUrlInfo │ ├── cache/ ← 캐시 관련 유틸 ├── cmd_arg/ ← typer 기반 CLI 인수 파싱 (--init-db 등) ├── libs/ │ └── stealth.min.js ← 크롤러 감지 방지 JS ├── docs/ │ ├── hit_stopwords.txt ← 워드클라우드 불용어 목록 │ └── STZHONGS.TTF ← 중국어 폰트 ├── pyproject.toml ← uv/pip 의존성 선언 ├── requirements.txt ← 구형 pip용 의존성 └── .env.example ← 환경변수 예시 (DB 연결, 쿠키 등)
구조 이해 비유

base/base_crawler.py는 "식당 가맹 계약서" — 모든 지점(플랫폼)이 반드시 제공해야 할 메뉴(메서드)를 규정한다.

media_platform/xhs/는 "소홍서 지점" — 실제 재료(API 엔드포인트, 서명 방식)를 써서 계약서의 메뉴를 만드는 방법을 구현한다.

store/는 "음식 포장 방식" — 같은 음식을 CSV 봉투·JSON 상자·DB 냉장고 중 어디에 넣을지 고른다.

6학습 포인트

브라우저 자동화 · 비동기 Python · 크롤링 윤리에서 배울 것.

1. Playwright 브라우저 자동화 심화

이 레포는 Playwright의 고급 기능을 실전으로 배울 수 있는 좋은 예시다. 단순한 클릭/입력을 넘어 BrowserContext 저장과 복원, page.evaluate()로 JS 함수 직접 호출, CDP 프로토콜 연결, init_script로 감지 방지 JS 삽입까지 다룬다.

base_crawler.pylaunch_browser_with_cdp()tools/cdp_browser.pyCDPBrowserManager를 함께 보면 로컬 Chrome 프로세스를 찾아 실행하고 CDP 포트로 연결하는 전 과정을 이해할 수 있다.

2. Python 비동기 프로그래밍 (asyncio)

이 레포 전체가 async/await로 작성되어 있다. 배울 수 있는 패턴:

패턴위치설명
asyncio.Semaphore각 플랫폼 core.py동시 요청 수 제한
asyncio.gather()batch 요청 처리여러 코루틴 동시 실행
aiofilesstore/ 저장파일 I/O 비동기화
aiomysql / aiosqlitedatabase/DB 쿼리 비동기화
tenacity @retryAPI 클라이언트실패 시 자동 재시도

3. 디자인 패턴: ABC + Factory + Mixin

base/base_crawler.py의 ABC 설계를 보면 인터페이스 분리, 의존성 역전 원칙(DIP)을 실제로 어떻게 적용하는지 볼 수 있다. proxy/proxy_mixin.py의 Mixin 패턴도 Python 다중 상속을 활용한 기능 합성의 좋은 예다.

4. 크롤링 윤리와 법적 한계

반드시 알아야 할 것
크롤러는 도구일 뿐, 사용 방식이 위법이 된다

이 레포의 LICENSE는 "NON-COMMERCIAL LEARNING LICENSE" — 상업적 이용 명시적 금지다. 코드 자체를 학습하는 것과 실제 플랫폼에서 데이터를 수집하는 것은 별개의 법적 판단을 요한다.

실제 실행 전 반드시 확인할 사항: ① 대상 플랫폼의 robots.txt와 서비스 이용약관, ② 개인정보보호법(국내 PIPA, 유럽 GDPR), ③ 컴퓨터 자원 무단 접근 관련 형법 조항. 중국에서는 크롤러 관련 기소 사례가 다수 존재한다 (레포 내 링크 참고).

5. 실습 아이디어

실제 플랫폼 크롤링 대신 안전하게 배우는 방법: 공개 API가 있는 서비스(Hacker News API, Reddit Public API, Wikipedia API)를 대상으로 같은 추상 클래스 구조를 직접 구현해보는 것이 좋다. 서명 로직이 없으므로 아키텍처 학습에 집중할 수 있다.

7시스템 요구사항 · 설치

요구사항 · uv / pip 설치 · playwright install 명령.

항목최소 사양권장 / 비고
OSmacOS / Linux / WindowsLinux에서 CDP 모드 사용 시 Xvfb 필요할 수 있음
Python3.11 이상.python-version 파일에 명시
Node.jsLTS (18+)Playwright 브라우저 설치 시 필요
RAM4 GB브라우저 + Python + DB 동시 실행 시 8 GB 권장
Chrome/Edge최신CDP 모드 사용 시 로컬 설치 필수
인터넷필수대상 플랫폼 접근 가능한 네트워크

방법 A: uv 사용 (권장)

# 1. uv 설치 (없는 경우)
curl -LsSf https://astral.sh/uv/install.sh | sh

# 2. 레포 클론
git clone https://github.com/NanmiCoder/MediaCrawler.git
cd MediaCrawler

# 3. 가상환경 생성 + 의존성 설치 (uv가 자동으로 Python 3.11 관리)
uv sync

# 4. Playwright 브라우저 바이너리 설치
uv run playwright install chromium

# 5. 환경변수 설정
cp .env.example .env
# .env 파일에 DB 연결, 쿠키 등 필요 항목 채우기

방법 B: pip 사용

# Python 3.11+ 가상환경 생성
python -m venv venv
source venv/bin/activate  # Windows: venv\Scripts\activate

pip install -r requirements.txt
playwright install chromium

기본 실행

# config/__init__.py 또는 .env에서 설정 후:
# PLATFORM=xhs, KEYWORDS=파이썬, CRAWLER_TYPE=search

uv run python main.py
# 처음 실행 시 QR코드가 터미널에 표시됨 → 소홍서 앱으로 스캔
# 이후 세션이 저장되어 재로그인 불필요

DB 초기화 (MySQL/PostgreSQL 사용 시)

# SAVE_DATA_OPTION=db 또는 postgres인 경우
uv run python main.py --init-db mysql
# 또는
uv run python main.py --init-db sqlite

8직접 해볼 수 있는 실습 과제

난이도별 3~5개 실습 — 실제 플랫폼 크롤링보다 구조 이해에 집중.

LV.1 — 입문

추상 클래스 구조 그려보기 난이도: ★☆☆☆☆

base/base_crawler.py를 읽고, AbstractCrawler·AbstractLogin·AbstractStore·AbstractApiClient의 메서드 목록을 표로 정리한다. 그리고 media_platform/xhs/core.py에서 각 메서드가 어떻게 구현되었는지 대응시켜 본다.

목표: ABC 인터페이스와 구현체 관계 이해. 코드 실행 없이 읽기만 해도 충분.
LV.2 — 기초

Playwright로 네이버 로그인 상태 저장·재사용 난이도: ★★☆☆☆

MediaCrawler의 핵심 원리를 네이버에 적용해 본다. Playwright Python 라이브러리로 네이버에 수동 로그인한 뒤 browser_context.storage_state(path="naver_state.json")로 저장한다. 다음 실행 시 browser.new_context(storage_state="naver_state.json")로 세션을 복원하고 로그인 없이 마이페이지에 접근해본다.

목표: 로그인 상태 지속(persistence) 원리 직접 체험. 실제 서비스 이용약관 확인 후 본인 계정으로만.
LV.3 — 중급

공개 API 대상 추상 크롤러 직접 구현 난이도: ★★★☆☆

MediaCrawler의 AbstractCrawler를 상속하여 Hacker News API (공개, 인증 불필요, https://hacker-news.firebaseio.com/v0/) 크롤러를 구현한다. start(), search()를 구현하고, 저장 방식은 AbstractStore를 상속한 JSON 구현체를 만든다. 결과를 JSONL 파일로 저장한다.

목표: 팩토리 패턴·ABC·비동기 httpx 실습. 공개 API라 법적 문제 없음.
LV.4 — 고급

워드클라우드 파이프라인 로컬 테스트 난이도: ★★★★☆

tools/async_file_writer.py의 워드클라우드 생성 로직을 분리해서 테스트 코드를 작성한다. 직접 만든 가짜 댓글 JSONL 파일(100개 줄)을 입력으로 주고, jieba 형태소 분석 → 불용어 제거 → wordcloud 이미지 생성까지 독립적으로 실행한다. 한국어 형태소 분석기 konlpy로 교체해 한국어 댓글 워드클라우드를 만들어 본다.

목표: jieba·wordcloud 라이브러리 이해, 데이터 파이프라인 독립 테스트 방법.
LV.5 — 심화

새 플랫폼 어댑터 추가하기 (Reddit Public API) 난이도: ★★★★★

media_platform/reddit/ 폴더를 만들고 AbstractCrawler·AbstractLogin·AbstractApiClient·AbstractStore 4개를 모두 구현한다. Reddit의 public JSON API(https://www.reddit.com/r/python.json)를 대상으로 한다. CrawlerFactory"reddit": RedditCrawler를 등록하고 config/reddit_config.py를 추가한다.

목표: MediaCrawler 아키텍처 전체 이해. 신규 플랫폼 추가 시 수정이 필요한 파일 목록 파악.

9관련 기술 심화 학습 로드맵

이 레포를 기반으로 확장할 수 있는 주차별 학습 경로.

주차주제핵심 학습 내용실습
1주 Python 비동기 기초 asyncio 이벤트 루프, async/await, coroutine vs thread 차이, asyncio.gather() asyncio로 동시에 5개 URL 다운로드 코드 작성
2주 Playwright 기초 브라우저 실행, 페이지 이동, 클릭·입력, 스크린샷, wait_for_selector() 네이버 검색어 입력 후 결과 첫 페이지 제목 10개 추출
3주 Playwright 고급 BrowserContext 저장/복원, page.evaluate() JS 실행, CDP 연결, stealth 스크립트 로그인 상태 저장 후 재사용 실습 (본인 계정)
4주 HTTP 클라이언트 (httpx) 비동기 GET/POST, 헤더 조작, 쿠키 관리, 프록시 설정, 세션 재사용 공개 REST API 10개 동시 호출 + 응답 파싱
5주 Python OOP 설계 패턴 ABC 추상 클래스, 팩토리 패턴, Mixin, Pydantic 모델 검증 MediaCrawler의 AbstractCrawler를 보고 독자적인 데이터 수집 시스템 설계
6주 데이터 저장 (다중 백엔드) SQLAlchemy async, Alembic 마이그레이션, aiosqlite, motor(MongoDB) 같은 데이터를 SQLite / JSON / CSV 세 가지로 동시 저장하는 스토어 구현
7주 데이터 처리 · 시각화 pandas 데이터 가공, jieba/konlpy 형태소 분석, wordcloud, matplotlib 수집한 텍스트 데이터로 키워드 트렌드 차트 생성
8주 윤리·법률·보안 robots.txt 파싱, 이용약관 검토, rate limiting 구현, IP 프록시의 법적 문제 robots.txt를 읽고 크롤 허용 경로 자동 필터링 로직 작성

10핵심 키워드 사전

이 레포를 이해하는 데 필요한 핵심 개념 정리.

용어설명
Playwright Microsoft의 브라우저 자동화 라이브러리. Python/JS/Java/C# 지원. asyncio 완전 호환. Selenium보다 빠르고 안정적.
CDP (Chrome DevTools Protocol) Chrome/Edge 브라우저를 외부 프로그램이 제어할 수 있게 하는 프로토콜. --remote-debugging-port로 활성화. Playwright가 이를 통해 브라우저와 통신한다.
BrowserContext Playwright의 "독립된 브라우저 세션". 쿠키·캐시·로컬스토리지가 격리된다. storage_state로 저장/복원 가능.
page.evaluate() Playwright에서 브라우저 내 JavaScript를 직접 실행하는 메서드. 이 레포에서는 플랫폼 내부 서명 함수를 여기서 호출한다.
stealth.min.js 크롤러 탐지 방지 JS 스크립트. navigator.webdriver 값 숨김, Chrome 헤드리스 판별 변수 위장 등을 수행.
asyncio.Semaphore 동시 실행 가능한 코루틴 수를 제한하는 동기화 도구. 서버 과부하 방지에 사용.
tenacity @retry 함수 실패 시 자동 재시도 데코레이터. 재시도 횟수·대기 시간·예외 조건을 선언적으로 설정.
Abstract Base Class (ABC) Python의 추상 클래스. @abstractmethod로 표시된 메서드는 자식 클래스에서 반드시 구현해야 함. 인터페이스 역할.
Factory Pattern 객체 생성을 담당하는 클래스(Factory)가 어떤 클래스의 인스턴스를 생성할지 결정하는 패턴. CrawlerFactory, XhsStoreFactory가 예시.
IP 프록시 풀 (Proxy Pool) 여러 IP 주소를 번갈아 사용하여 IP 차단을 회피하는 기법. 유효성 검증 + 순환 로직 포함.
JSONL (JSON Lines) 한 줄에 JSON 객체 하나. 대용량 데이터 스트리밍 저장에 유리. 마지막 줄만 추가하므로 메모리 효율적.
jieba Python 중국어 형태소 분석 라이브러리. 공백이 없는 중국어 문장을 단어 단위로 분리.
robots.txt 웹사이트 운영자가 크롤러에게 접근 허용/금지 경로를 명시하는 파일. 법적 강제력은 없지만 준수가 관행이자 안전책.
NON-COMMERCIAL LICENSE 이 레포의 라이선스. 학습·연구 목적으로만 사용 가능하며 상업적 이용 명시 금지. MIT와 달리 사용 범위가 제한된다.

11참고 링크 · 법적·윤리적 주의

출처 · 정리 기준일 2026-06-27 · 솔직한 caveat.

법적·윤리 주의 — 반드시 읽기
이 레포는 학습용이다 — 실제 운영은 본인 책임

① 이용약관(ToS) 위반: 소홍서·더우인 등 모든 대상 플랫폼은 자동화 데이터 수집을 이용약관으로 금지하고 있다. 이를 어기면 계정 영구 정지 및 민사 손해배상 대상이 될 수 있다.

② robots.txt: 각 플랫폼의 /robots.txt를 확인하고 Disallow 경로는 접근하지 않는 것이 기본 예절이자 법적 리스크 감소 방법이다.

③ 개인정보보호: 수집한 데이터에 사용자 이름·프로필·연락처 등 개인정보가 포함되면 국내 개인정보보호법(PIPA), 유럽 GDPR 적용 대상이 될 수 있다. 제3자 공유·상업적 이용은 더욱 위험하다.

④ 상업적 이용 금지: 레포의 NON-COMMERCIAL LEARNING LICENSE는 영리 목적 사용을 명시적으로 금지한다. 수익 창출 서비스에 사용하면 저작권 침해다.

⑤ 중국 크롤러 법적 사례: 중국에서는 크롤러 사용으로 인한 형사 기소가 다수 발생했다. 레포 내 링크 참고: github.com/HiddenStrawberry/Crawler_Illegal_Cases_In_China