5단계
5단계 — 외부 API · 크롤러 윤리
25 분
5단계 — 외부 API · 크롤러 윤리
외부 사이트의 데이터를 가져올 때 지켜야 할 예의 와 기술 이 있어요. 안 지키면 차단되거나, 법적 문제가 생겨요.
크롤러 5계명
robots.txt를 먼저 본다 — 사이트 루트의/robots.txt가 크롤 가능 영역 을 알려줍니다- 요청 간격을 둔다 — 1초당 1회 이하 (rate limit)
- User-Agent 를 명시한다 — 어떤 봇인지 밝힘
- 캐시한다 — 같은 데이터를 두 번 요청하지 않음
- 공식 API 를 우선 시도 — RSS/Atom/Open API 가 있으면 그쪽
http_client 패턴
# utils/http_client.py
import time
import httpx
class RateLimitedClient:
def __init__(self, base_url: str, requests_per_second: float = 1.0):
self.client = httpx.Client(
base_url=base_url,
headers={"User-Agent": "codingstairs-crawler/1.0 (https://codingstairs.duckdns.org)"},
timeout=10.0,
)
self.min_interval = 1.0 / requests_per_second
self.last_request_at = 0.0
def get(self, path: str, **kwargs):
elapsed = time.time() - self.last_request_at
if elapsed < self.min_interval:
time.sleep(self.min_interval - elapsed)
self.last_request_at = time.time()
return self.client.get(path, **kwargs)
이 한 클래스를 거치면 자동으로 rate limit + User-Agent 가 적용돼요.
robots.txt 파싱
from urllib.robotparser import RobotFileParser
rp = RobotFileParser()
rp.set_url("https://example.com/robots.txt")
rp.read()
if not rp.can_fetch("codingstairs-crawler/1.0", "https://example.com/some-page"):
raise PermissionError("robots.txt 에서 차단된 경로")
기본은 허락받지 않은 곳은 가지 않음.
캐싱은 DB 또는 Redis
def get_with_cache(url: str, ttl_seconds: int = 3600):
with get_conn() as conn, conn.cursor() as cur:
cur.execute(
"SELECT body, fetched_at FROM http_cache WHERE url = %s",
(url,),
)
row = cur.fetchone()
if row and (datetime.now(tz=UTC) - row[1]).total_seconds() < ttl_seconds:
return row[0]
body = client.get(url).text
with get_conn() as conn, conn.cursor() as cur:
cur.execute("""
INSERT INTO http_cache (url, body, fetched_at)
VALUES (%s, %s, NOW())
ON CONFLICT (url) DO UPDATE SET body = EXCLUDED.body, fetched_at = NOW()
""", (url, body))
return body
Playwright — JavaScript 가 필요한 페이지
정적 HTML 만으론 안 되는 사이트는 Playwright 같은 진짜 브라우저 가 필요. 단, 비용이 100배 비싸므로 최후의 수단.
직접 해 보기
공개 API (예: https://jsonplaceholder.typicode.com) 의 게시물 목록을 1초 간격으로 5번 가져오는 스크립트를 만들어 보세요. RateLimitedClient 가 정확히 1초 간격을 지키는지 확인.
더 깊이
- 크롤러 윤리 노트
- Playwright 크롤러 노트 — 외부데이터 SSOT
다음 단계
6단계에서는 가져온 데이터를 변환·저장 하는 ETL 파이프라인을 만들어요.