웹 크롤링
ActiCrawl의 강력한 크롤링 엔진으로 현대적인 JavaScript 중심 사이트, 동적 콘텐츠, 복잡한 네비게이션 패턴을 효과적으로 크롤링하는 방법을 알아보세요.
웹 크롤링 이해하기
웹 크롤링은 웹사이트를 체계적으로 탐색하고 데이터를 추출하는 프로세스입니다. ActiCrawl은 다음을 수행할 수 있는 정교한 크롤링 엔진을 제공합니다:
- 여러 페이지를 자동으로 탐색
- JavaScript 렌더링 콘텐츠 처리
- 링크 따라가기 및 새 페이지 발견
- robots.txt 및 크롤링 지연 준수
- 세션 및 인증 관리
단일 페이지 스크래핑
단일 페이지를 스크래핑하려면 기본 스크래핑 엔드포인트를 사용하세요:
javascript
const result = await client.scrape({
url: 'https://example.com/page',
format: 'markdown'
});
다중 페이지 크롤링
링크 따라가기
도메인 내의 링크를 자동으로 따라가며 크롤링:
javascript
const crawler = await client.crawl({
startUrl: 'https://example.com',
followLinks: true,
maxPages: 100,
linkSelector: 'a[href]', // 따라갈 링크의 CSS 선택자
sameDomain: true, // 같은 도메인의 링크만 따라가기
format: 'json'
});
// 크롤링된 페이지 처리
crawler.on('page', (page) => {
console.log(`크롤링됨: ${page.url}`);
console.log(`${page.links.length}개의 링크 발견`);
});
crawler.on('complete', (results) => {
console.log(`${results.length}개 페이지 크롤링 완료`);
});
URL 패턴
특정 URL 패턴 정의하여 크롤링:
python
from acticrawl import ActiCrawl
client = ActiCrawl(api_key='YOUR_API_KEY')
crawler = client.create_crawler({
'start_url': 'https://example.com/products',
'url_patterns': [
r'^https://example\.com/products/[\w-]+$', # 제품 페이지
r'^https://example\.com/category/[\w-]+$' # 카테고리 페이지
],
'max_pages': 500
})
results = crawler.run()
사이트맵 크롤링
사이트맵을 사용하여 효율적으로 크롤링:
ruby
crawler = client.crawl_sitemap(
sitemap_url: 'https://example.com/sitemap.xml',
filter: ->(url) { url.include?('/blog/') }, # 블로그 포스트만 크롤링
concurrency: 5,
format: 'markdown'
)
crawler.each do |page|
puts "제목: #{page['metadata']['title']}"
puts "콘텐츠: #{page['content']}"
end
고급 크롤링 전략
깊이 우선 vs 너비 우선
사이트 구조에 따라 크롤링 전략 선택:
javascript
// 너비 우선 (기본값) - 각 레벨의 모든 페이지 발견에 적합
const bfsCrawler = await client.crawl({
startUrl: 'https://example.com',
strategy: 'breadth-first',
maxDepth: 3
});
// 깊이 우선 - 특정 경로를 깊게 따라가기에 적합
const dfsCrawler = await client.crawl({
startUrl: 'https://example.com',
strategy: 'depth-first',
maxDepth: 10
});
페이지네이션 처리
페이지네이션된 콘텐츠 자동 처리:
python
crawler = client.create_crawler({
'start_url': 'https://example.com/listings?page=1',
'pagination': {
'type': 'query_param',
'param': 'page',
'max_pages': 50,
'increment': 1
}
})
# 또는 다음 버튼 클릭으로
crawler = client.create_crawler({
'start_url': 'https://example.com/results',
'pagination': {
'type': 'click',
'selector': 'button.next-page',
'wait_after_click': 2000,
'max_clicks': 20
}
})
무한 스크롤
무한 스크롤 페이지 처리:
javascript
const result = await client.scrape({
url: 'https://example.com/feed',
infinite_scroll: {
enabled: true,
max_scrolls: 10,
scroll_delay: 1000, // 스크롤 간 1초 대기
element_count_selector: '.feed-item', // 새 항목이 없으면 중지
timeout: 30000
}
});
세션 관리
로그인 상태 유지
인증된 영역 크롤링:
javascript
// 먼저 로그인
const session = await client.createSession({
loginUrl: 'https://example.com/login',
credentials: {
username: 'user@example.com',
password: 'password'
},
selectors: {
username: '#username',
password: '#password',
submit: 'button[type="submit"]'
}
});
// 세션으로 크롤링
const crawler = await client.crawl({
startUrl: 'https://example.com/dashboard',
sessionId: session.id,
followLinks: true
});
쿠키 관리
기존 쿠키를 사용하여 크롤링:
python
cookies = [
{'name': 'session_id', 'value': 'abc123', 'domain': 'example.com'},
{'name': 'auth_token', 'value': 'xyz789', 'domain': 'example.com'}
]
crawler = client.create_crawler({
'start_url': 'https://example.com/protected',
'cookies': cookies,
'follow_links': True
})
크롤링 규칙 및 필터
URL 필터링
크롤링할 URL 제어:
javascript
const crawler = await client.crawl({
startUrl: 'https://example.com',
urlFilters: {
include: [
/\/products\//, // 제품 페이지 포함
/\/blog\// // 블로그 포스트 포함
],
exclude: [
/\/admin\//, // 관리자 페이지 제외
/\.pdf$/, // PDF 파일 제외
/#/ // URL 프래그먼트 제외
]
}
});
콘텐츠 필터링
콘텐츠 기반 페이지 필터링:
python
def should_process(page):
# 특정 콘텐츠가 있는 페이지만 처리
return (
page['metadata'].get('language') == 'ko' and
len(page['content']) > 1000 and
'제품' in page['content'].lower()
)
crawler = client.create_crawler({
'start_url': 'https://example.com',
'content_filter': should_process
})
성능 최적화
동시 크롤링
동시성으로 크롤링 속도 향상:
javascript
const crawler = await client.crawl({
startUrl: 'https://example.com',
concurrency: 10, // 10개 페이지 동시 크롤링
requestDelay: 1000, // 요청 간 1초 대기
respectRobotsTxt: true
});
캐싱
변경되지 않은 페이지 재크롤링 방지:
python
crawler = client.create_crawler({
'start_url': 'https://example.com',
'cache': {
'enabled': True,
'ttl': 86400, # 24시간 캐시
'key_by': 'url_and_content_hash'
}
})
선택적 추출
처리 감소를 위해 필요한 데이터만 추출:
javascript
const crawler = await client.crawl({
startUrl: 'https://example.com/catalog',
extract: {
title: 'h1',
price: '.price',
description: '.product-description',
image: 'img.product-image@src'
},
skipFullContent: true // 전체 HTML 저장 안 함
});
오류 처리 및 재시도
자동 재시도
재시도 동작 구성:
python
crawler = client.create_crawler({
'start_url': 'https://example.com',
'retry': {
'max_attempts': 3,
'delay': 2000,
'exponential_backoff': True,
'on_errors': [429, 500, 502, 503, 504]
}
})
오류 복구
오류 후에도 크롤링 계속:
javascript
const crawler = await client.crawl({
startUrl: 'https://example.com',
errorHandling: {
continueOnError: true,
maxConsecutiveErrors: 5,
errorLog: true
}
});
crawler.on('error', (error) => {
console.error(`크롤링 오류 ${error.url}: ${error.message}`);
// 사용자 정의 오류 처리
});
모니터링 및 진행 상황
실시간 진행 상황
크롤링 진행 상황 추적:
python
crawler = client.create_crawler({
'start_url': 'https://example.com',
'progress_callback': lambda p: print(f"진행률: {p['crawled']}/{p['total']}")
})
# 또는 웹훅 사용
crawler = client.create_crawler({
'start_url': 'https://example.com',
'webhook': {
'url': 'https://your-app.com/crawl-progress',
'events': ['page_crawled', 'error', 'complete']
}
})
크롤링 통계
상세 통계 확인:
javascript
const stats = await crawler.getStats();
console.log({
totalPages: stats.totalPages,
successfulPages: stats.successful,
failedPages: stats.failed,
averageResponseTime: stats.avgResponseTime,
totalDataExtracted: stats.dataSize
});
모범 사례
1. 웹사이트 정책 존중
- 항상 robots.txt 확인 및 준수
- 요청 간 적절한 지연 구현
- 합리적인 동시성 제한 사용
2. 선택자 최적화
- 더 나은 성능을 위해 특정 CSS 선택자 사용
- 너무 많은 요소와 일치하는 광범위한 선택자 피하기
- 대규모 크롤링 전 선택자 테스트
3. 동적 콘텐츠 처리
- 추출 전 콘텐츠 로드 대기
- JavaScript에 적절한 대기 전략 사용
- 중요한 페이지는 스크린샷 검증 고려
4. 리소스 사용량 모니터링
- 최대 페이지 제한 설정
- 장시간 실행되는 크롤링에 타임아웃 구현
- 폴링 대신 장시간 크롤링에는 웹훅 사용
예제: 이커머스 사이트 크롤러
이커머스 사이트 크롤링 완전한 예제:
javascript
async function crawlEcommerceSite() {
const crawler = await client.crawl({
startUrl: 'https://shop.example.com',
// 크롤링 규칙
urlFilters: {
include: [/\/products\//, /\/category\//],
exclude: [/\/cart/, /\/checkout/, /\/account/]
},
// 성능 설정
concurrency: 5,
maxPages: 1000,
requestDelay: 2000,
// 추출 규칙
extract: {
title: 'h1.product-title',
price: '.price-now',
originalPrice: '.price-was',
description: '.product-description',
images: 'img.product-image@src',
inStock: '.availability',
reviews: {
selector: '.review',
multiple: true,
extract: {
rating: '.rating@data-rating',
text: '.review-text',
author: '.review-author'
}
}
},
// 오류 처리
retry: {
maxAttempts: 3,
delay: 5000
},
// 진행 상황 추적
webhook: {
url: 'https://your-app.com/crawl-webhook',
events: ['page_crawled', 'complete', 'error']
}
});
return crawler.run();
}
다음 단계
- 데이터 추출 기법 알아보기
- JavaScript 렌더링 옵션 탐색
- 지역 타겟팅 크롤링을 위한 프록시 사용 읽기
- 요청 제한 모범 사례 이해