AI 시대에는 웹 데이터에 효율적으로 접근하고 처리하는 것이 중요합니다. Crawl4AI는 대규모 언어 모델(LLM), AI 에이전트 및 최신 데이터 파이프라인을 사용하는 개발자를 위해 세심하게 설계된 강력한 오픈 소스 웹 크롤러 및 스크래퍼로 등장했습니다. 이 튜토리얼은 설치부터 고급 크롤링 기술까지 Crawl4AI에 대한 심층적인 내용을 다룹니다.
최대한의 생산성으로 개발자 팀이 함께 작업할 수 있는 통합된 올인원 플랫폼을 원하십니까?
Apidog는 귀하의 모든 요구를 충족하며 Postman을 훨씬 더 저렴한 가격으로 대체합니다!
프로젝트에 Crawl4AI를 선택해야 하는 이유
Crawl4AI는 단순한 표준 웹 스크래퍼 이상입니다. LLM 친화적으로 처음부터 설계되었습니다. 이는 다음 사항에 중점을 둡니다.
- 깔끔한 마크다운 생성: 상용구 및 노이즈를 제거하여 검색 증강 생성(RAG) 시스템 및 모델 미세 조정에 최적화된 구조가 잘 잡히고 간결한 마크다운을 생성합니다.
- 구조화된 데이터 추출: 전통적인 방법(CSS 선택자, XPath)을 사용하거나 LLM을 활용하여 더 복잡하고 의미론적인 추출 작업을 수행하여 특정 데이터 포인트를 JSON과 같은 형식으로 추출할 수 있습니다.
- 고성능: Python의
asyncio
라이브러리와 강력한 Playwright 브라우저 자동화 프레임워크를 활용하여 빠르고 비동기적인 크롤링을 수행합니다. - 고급 브라우저 제어: JavaScript 실행, 동적 콘텐츠 처리, 세션 관리(쿠키, 로컬 스토리지), 프록시 사용, 다양한 사용자 환경 시뮬레이션(사용자 에이전트, 지리적 위치)을 포함하여 브라우저 인스턴스에 대한 세부적인 제어를 제공합니다.
- 오픈 소스 및 유연성: 외부 API 키 또는 유료 서비스에 의존하지 않는 완전한 오픈 소스(Apache 2.0, 출처 표기)입니다. Docker 또는 직접적인 pip 설치를 통해 배포 유연성을 제공합니다.
Crawl4AI는 데이터 접근성을 민주화하여 개발자가 웹 데이터를 빠르고 효율적으로 수집하고 형성할 수 있도록 지원하는 것을 목표로 합니다.
Crawl4AI 설치 및 설정
Crawl4AI를 실행하는 것은 간단하며, pip
및 Docker
옵션을 모두 제공합니다.
방법 1: Pip 설치 (라이브러리 사용에 권장)
패키지 설치: 터미널을 열고 다음을 실행합니다.
# 최신 안정 버전 설치
pip install -U crawl4ai
# 또는, 최신 프리릴리스 설치 (최첨단 기능용)
# pip install crawl4ai --pre
설치 후 설정 실행: 이 중요한 단계는 필요한 Playwright 브라우저 바이너리(기본값은 Chromium)를 설치합니다.
crawl4ai-setup
확인: 진단 도구를 사용하여 설정을 확인합니다.
crawl4ai-doctor
문제 해결: crawl4ai-setup
에서 문제가 발생하는 경우, 브라우저 종속성을 수동으로 설치합니다.
python -m playwright install --with-deps chromium
방법 2: Docker 배포 (API 서비스에 적합)
이미지 가져오기: 공식 Docker 이미지를 가져옵니다 (최신 태그는 GitHub에서 확인하세요).
# 예시 태그, 필요한 경우 교체
docker pull unclecode/crawl4ai:latest
컨테이너 실행: Crawl4AI 서비스를 시작하고 API를 노출합니다 (기본 포트 11235).
docker run -d -p 11235:11235 --name crawl4ai --shm-size=1g unclecode/crawl4ai:latest
이는 FastAPI 백엔드로 Crawl4AI를 실행하며, HTTP를 통해 크롤링 요청을 받을 준비가 됩니다. http://localhost:11235/playground
에서 대화형 API 플레이그라운드에 접근할 수 있습니다.
Crawl4AI로 첫 번째 크롤링을 실행하는 방법
Crawl4AI는 AsyncWebCrawler
를 사용하여 기본적인 크롤링을 매우 간단하게 만듭니다.
import asyncio
from crawl4ai import AsyncWebCrawler, BrowserConfig, CrawlerRunConfig, CacheMode
async def run_basic_crawl():
# --- 기본 예제 ---
print("--- 기본 크롤링 실행 중 ---")
# 'async with'를 사용하여 자동 브라우저 시작 및 종료
async with AsyncWebCrawler() as crawler:
# arun() 메서드는 단일 URL에 대한 크롤링을 수행합니다.
# CrawlResult 객체를 반환합니다.
result = await crawler.arun(url="https://example.com")
if result and result.success:
# 생성된 마크다운 접근 (일반적으로 'fit_markdown')
print("크롤링 성공!")
# result.markdown은 원본 및 필터링된 마크다운을 모두 제공합니다.
print(f"적합 마크다운 (처음 300자): {result.markdown.fit_markdown[:300]}...")
else:
print(f"크롤링 실패: {result.error_message}")
# --- 기본 구성 예제 ---
print("\n--- 기본 구성으로 크롤링 실행 중 ---")
# 브라우저 동작 구성 (예: 디버깅을 위해 headful로 실행)
browser_conf = BrowserConfig(headless=True) # 브라우저 창을 보려면 False로 설정
# 실행별 설정 구성 (예: 캐시 우회)
# CacheMode.ENABLED (기본값), CacheMode.DISABLED, CacheMode.BYPASS
run_conf = CrawlerRunConfig(cache_mode=CacheMode.BYPASS)
async with AsyncWebCrawler(config=browser_conf) as crawler:
result = await crawler.arun(
url="https://crawl4ai.com/", # 공식 사이트 크롤링
config=run_conf # 실행 구성 적용
)
if result and result.success:
print("크롤링 성공!")
print(f"적합 마크다운 단어 수: {result.markdown.word_count}")
print(f"크롤링된 URL: {result.url}")
else:
print(f"크롤링 실패: {result.error_message}")
if __name__ == "__main__":
asyncio.run(run_basic_crawl())
주요 Crawl4AI 개념:
AsyncWebCrawler
: 크롤링을 시작하는 메인 클래스입니다.async with
를 사용하면 브라우저가 제대로 관리됩니다.arun(url, config=None)
: 단일 URL을 크롤링하는 핵심 비동기 메서드입니다.BrowserConfig
: 브라우저 수준 설정(headless, 사용자 에이전트, 프록시)을 제어합니다.AsyncWebCrawler
초기화 중에 전달됩니다.CrawlerRunConfig
: 특정 크롤링 작업에 대한 설정(캐싱, 추출 전략, 타임아웃, JavaScript 실행)을 제어합니다.arun
메서드에 전달됩니다.CacheMode
: Crawl4AI가 캐시와 상호 작용하는 방식을 결정합니다(ENABLED
,DISABLED
,BYPASS
).BYPASS
는 개발 중 최신 데이터를 확보하는 데 유용합니다.
Crawl4AI CrawlResult
객체는 어떻게 작동하나요?
모든 성공적인 arun
또는 arun_many
호출은 하나 이상의 CrawlResult
객체를 반환하며, 이는 크롤링 중에 수집된 모든 정보를 캡슐화합니다.
CrawlResult
객체는 다음과 같은 다양한 속성을 포함합니다.
url
: 크롤링된 최종 URL (리다이렉트 후).success
: 크롤링 성공 여부를 나타내는 부울 값.error_message
:success
가False
인 경우 오류 세부 정보 포함.status_code
: 응답의 HTTP 상태 코드.markdown
: 마크다운 버전(raw_markdown
,fit_markdown
,word_count
)을 포함하는 객체.html
: 페이지의 원본 HTML 콘텐츠.text
: 페이지에서 추출된 일반 텍스트 콘텐츠.extracted_content
: 구성된 추출 전략의 결과(예: JSON 문자열)를 저장합니다.links
: 페이지에서 발견된 링크 목록(internal
,external
).media
: 추출된 미디어(이미지, 테이블 등)에 대한 정보.metadata
: 페이지 메타데이터(제목, 설명 등).cookies
: 크롤링 후 브라우저 쿠키.screenshot_path
: 스크린샷이 찍힌 경우 경로.network_log_path
: 네트워크 HAR 파일이 캡처된 경우 경로.console_log_path
: 콘솔 로그 파일이 캡처된 경우 경로.
이 객체를 검사하는 것은 Crawl4AI 크롤링에서 필요한 특정 데이터에 접근하는 핵심입니다.
Crawl4AI로 AI 지원 마크다운을 생성하는 방법
Crawl4AI의 핵심 강점은 LLM에 적합한 깔끔한 마크다운을 생성하는 능력입니다.
result.markdown
속성은 다음을 포함합니다.
result.markdown.raw_markdown
: 페이지의 주요 콘텐츠 영역을 마크다운으로 직접, 필터링되지 않은 변환 결과.result.markdown.fit_markdown
: 마크다운의 필터링된 버전. Crawl4AI가 일반적인 웹 클러터(메뉴, 광고, 푸터, 사이드바)를 제거하기 위해 휴리스틱 필터(예:PruningContentFilter
또는BM25ContentFilter
)를 적용하므로 LLM에 가장 유용한 경우가 많습니다.result.markdown.word_count
:fit_markdown
의 단어 수.
Crawl4AI에서 필터링 프로세스를 사용자 정의할 수 있습니다.
import asyncio
from crawl4ai import AsyncWebCrawler, CrawlerRunConfig, CacheMode
# 사용자 정의를 위한 특정 전략 가져오기
from crawl4ai.content_filter_strategy import PruningContentFilter
from crawl4ai.markdown_generation_strategy import DefaultMarkdownGenerator
async def run_custom_markdown_crawl():
print("\n--- 사용자 정의 마크다운 필터링으로 크롤링 실행 중 ---")
# 특정 콘텐츠 필터로 마크다운 생성기 구성
# PruningContentFilter는 단어 수 임계값을 기반으로 요소를 제거합니다.
markdown_generator_with_filter = DefaultMarkdownGenerator(
content_filter=PruningContentFilter(
threshold=0.48, # 엄격성을 위해 임계값 조정 (0 ~ 1)
threshold_type="fixed" # 'fixed' 또는 'relative'
)
)
# 실행 구성에 이 생성기 적용
run_conf = CrawlerRunConfig(
cache_mode=CacheMode.BYPASS,
markdown_generator=markdown_generator_with_filter
)
async with AsyncWebCrawler() as crawler:
result = await crawler.arun(
url="https://www.nbcnews.com/business", # 뉴스 사이트는 종종 클러터가 많습니다.
config=run_conf
)
if result and result.success:
print("크롤링 성공!")
print(f"원본 마크다운 길이: {len(result.markdown.raw_markdown)}")
print(f"적합 마크다운 길이: {len(result.markdown.fit_markdown)}") # 보통 더 짧습니다.
# raw_markdown과 fit_markdown을 비교하여 필터의 효과를 확인하세요.
else:
print(f"크롤링 실패: {result.error_message}")
if __name__ == "__main__":
asyncio.run(run_custom_markdown_crawl())
markdown_generator
내에서 content_filter
를 조정함으로써 Crawl4AI가 fit_markdown
을 생성하기 전에 콘텐츠를 얼마나 적극적으로 정리할지 제어할 수 있습니다.
Crawl4AI 딥 크롤링 사용 방법
Crawl4AI는 단일 페이지에만 국한되지 않습니다. 링크를 따라 웹사이트를 탐색하는 딥 크롤링을 수행할 수 있습니다.
adeep_crawl
메서드 (또는 crwl
CLI의 --deep-crawl
플래그)를 사용합니다.
import asyncio
from crawl4ai import AsyncWebCrawler, CrawlerRunConfig, CacheMode
async def run_deep_crawl():
print("\n--- 딥 크롤링 실행 중 ---")
# 구성은 평소와 같이 전역적으로 또는 실행별로 적용할 수 있습니다.
run_conf = CrawlerRunConfig(cache_mode=CacheMode.ENABLED)
async with AsyncWebCrawler() as crawler:
# adeep_crawl은 비동기 제너레이터를 반환하며, 페이지가 완료될 때마다 결과를 생성합니다.
crawl_generator = await crawler.adeep_crawl(
start_url="https://docs.crawl4ai.com/", # 시작 지점
strategy="bfs", # 'bfs' (너비 우선), 'dfs' (깊이 우선), 'bestfirst'
max_depth=2, # 따라갈 링크 깊이 제한
max_pages=10, # 크롤링할 총 페이지 수 제한
config=run_conf
)
# 결과가 들어오는 대로 처리
pages_crawled = 0
async for result in crawl_generator:
if result.success:
print(f"[OK] 크롤링됨: {result.url} (깊이: {result.depth}, 적합 마크다운 길이: {len(result.markdown.fit_markdown)})")
pages_crawled += 1
else:
print(f"[FAIL] URL: {result.url}, 오류: {result.error_message}")
print(f"\n딥 크롤링 완료. 성공적으로 크롤링된 총 페이지 수: {pages_crawled}")
if __name__ == "__main__":
asyncio.run(run_deep_crawl())
Crawl4AI 딥 크롤링 매개변수:
start_url
: 크롤링을 시작할 초기 URL.strategy
: 링크를 발견하고 우선 순위를 지정하는 방법(bfs
,dfs
,bestfirst
).max_depth
:start_url
로부터의 최대 링크 거리.max_pages
: 이 작업에서 크롤링할 최대 총 페이지 수.include_patterns
,exclude_patterns
: 따라갈 URL을 필터링하는 데 정규식 패턴을 사용합니다.
Crawl4AI로 동적 콘텐츠 및 상호 작용을 처리하는 방법
최신 웹사이트는 콘텐츠를 로드하기 위해 JavaScript에 크게 의존합니다. Crawl4AI는 Playwright의 기능을 통해 이를 처리합니다.
CrawlerRunConfig
를 사용하여 임의의 JavaScript를 실행하거나 특정 조건을 기다릴 수 있습니다.
import asyncio
import json
from crawl4ai import AsyncWebCrawler, BrowserConfig, CrawlerRunConfig, CacheMode
from crawl4ai.extraction_strategy import JsonCssExtractionStrategy # 예시
async def crawl_dynamic_page():
print("\n--- JS 상호 작용으로 동적 페이지 크롤링 중 ---")
# CSS 추출을 위한 예시 스키마 (대상 사이트에 맞게 조정)
schema = { "items": { "selector": "div.product-item", "type": "list", "fields": { "title": "h2", "price": ".price" } } }
css_extractor = JsonCssExtractionStrategy(schema)
# 페이지에서 실행할 JavaScript (예: '더 보기' 버튼 클릭)
# 참고: 선택자는 대상 웹사이트와 일치해야 합니다.
js_to_run = """
(async () => {
const loadMoreButton = document.querySelector('button#load-more');
if (loadMoreButton) {
console.log('더 보기 버튼 클릭 중...');
loadMoreButton.click();
// 클릭 후 콘텐츠 로드를 위해 잠시 대기
await new Promise(resolve => setTimeout(resolve, 2000));
console.log('클릭 후 대기 완료.');
} else {
console.log('더 보기 버튼을 찾을 수 없습니다.');
}
})();
"""
run_conf = CrawlerRunConfig(
cache_mode=CacheMode.BYPASS,
js_code=[js_to_run], # 실행할 JS 스니펫 목록
wait_for_timeout=3000, # 초기 로드 및 JS 실행 후 3초 대기
# wait_for_selector="div.newly-loaded-content", # 또는 특정 요소 대기
extraction_strategy=css_extractor, # JS 실행 후 데이터 추출
output_formats=['markdown', 'extracted_content']
)
# BrowserConfig에서 JS가 활성화되어 있는지 확인합니다 (기본적으로 활성화됨).
browser_conf = BrowserConfig(headless=True, java_script_enabled=True)
async with AsyncWebCrawler(config=browser_conf) as crawler:
result = await crawler.arun(
url="URL_OF_DYNAMIC_PAGE_HERE", # 실제 URL로 교체하세요
config=run_conf
)
if result and result.success:
print("동적 페이지 크롤링 성공!")
print(f"적합 마크다운 길이: {len(result.markdown.fit_markdown)}")
if result.extracted_content:
try:
extracted_data = json.loads(result.extracted_content)
print(f"추출된 콘텐츠 미리보기: {json.dumps(extracted_data, indent=2)[:500]}...")
except json.JSONDecodeError:
print(f"추출된 콘텐츠 (JSON 아님): {result.extracted_content[:500]}...")
else:
print(f"크롤링 실패: {result.error_message}")
if __name__ == "__main__":
# 테스트를 위해 동적으로 콘텐츠를 로드하는 실제 URL로 교체하고 위 줄의 주석을 해제하세요.
# asyncio.run(crawl_dynamic_page())
print("'URL_OF_DYNAMIC_PAGE_HERE'를 실제 URL로 교체하고 위 줄의 주석을 해제하여 동적 예제를 실행하세요.")
CrawlerRunConfig
의 주요 Crawl4AI 상호 작용 매개변수:
js_code
: 페이지 컨텍스트에서 실행할 JavaScript 문자열 목록.wait_for_timeout
: 페이지 로드 후 및 JS 실행 후 대기할 밀리초.wait_for_selector
: 페이지 로드/상호 작용 완료로 간주하기 전에 기다릴 CSS 선택자.page_interaction_hooks
: 복잡한 상호 작용을 위한 더 고급 훅.
Crawl4AI 결론
Crawl4AI는 웹 크롤링 및 스크래핑을 위한 포괄적이고 Pythonic하며 AI 중심적인 솔루션을 제공합니다. 깔끔한 마크다운 생성, 유연한 구조화된 데이터 추출(CSS 및 LLM 기반), 동적 콘텐츠의 강력한 처리, 효율적인 비동기 작업에 중점을 두어 RAG, LLM 미세 조정 또는 웹에서 구조화된 정보가 필요한 모든 프로젝트에 탁월한 선택입니다. 명확한 API, 구성 옵션(BrowserConfig
, CrawlerRunConfig
), 상세한 CrawlResult
객체를 활용하여 개발자는 정교하고 효율적인 데이터 수집 워크플로우를 구축할 수 있습니다.
최대한의 생산성으로 개발자 팀이 함께 작업할 수 있는 통합된 올인원 플랫폼을 원하십니까?
Apidog는 귀하의 모든 요구를 충족하며 Postman을 훨씬 더 저렴한 가격으로 대체합니다!