rs-trafilatura를 spider-rs와 함께 사용하는 방법
Source: Dev.to
Introduction
spider는 Rust로 작성된 고성능 비동기 웹 크롤러입니다. URL을 발견하고, 가져오며, 큐에 넣지만, 콘텐츠 추출은 여러분에게 맡겨집니다. rs‑trafilatura는 추출 레이어로 작동하여 페이지 유형을 인식하고, 크롤링된 모든 페이지에 품질 점수를 매겨 콘텐츠를 추출합니다.
의존성 추가
두 개의 크레이트를 Cargo.toml에 추가합니다:
[dependencies]
rs-trafilatura = { version = "0.2", features = ["spider"] }
spider = "2"
tokio = { version = "1", features = ["full"] }
spider 기능 플래그는 rs_trafilatura::spider_integration을 활성화하며, 이는 spider의 Page 타입을 직접 받아들이는 편리한 함수를 제공합니다.
간단한 추출 (크롤링 후 처리)
use spider::website::Website;
use rs_trafilatura::spider_integration::extract_page;
#[tokio::main]
async fn main() {
let mut website = Website::new("https://example.com");
website.crawl().await;
for page in website.get_pages().into_iter().flatten() {
match extract_page(&page) {
Ok(result) => {
println!(
"[{}] {} (confidence: {:.2})",
result.metadata.page_type.unwrap_or_default(),
result.metadata.title.unwrap_or_default(),
result.extraction_quality,
);
println!(" Content: {} chars", result.content_text.len());
}
Err(e) => eprintln!(" Extraction failed: {e}"),
}
}
}
extract_page은 &Page를 받아 Result를 반환합니다. 페이지 URL은 페이지 유형 감지를 위해 자동으로 분류기에 전달됩니다.
스트리밍 추출 (페이지가 도착하는 대로 처리)
use spider::website::Website;
use rs_trafilatura::spider_integration::extract_page;
#[tokio::main]
async fn main() {
let mut website = Website::new("https://example.com");
let mut rx = website.subscribe(0).unwrap();
let handle = tokio::spawn(async move {
let mut count = 0;
while let Ok(page) = rx.recv().await {
if let Ok(result) = extract_page(&page) {
count += 1;
println!(
"[{count}] {} → {} ({:.2})",
page.get_url(),
result.metadata.page_type.unwrap_or_default(),
result.extraction_quality,
);
}
}
println!("Extracted {count} pages");
});
website.crawl().await;
website.unsubscribe();
let _ = handle.await;
}
각 페이지는 spider가 가져오자마자 생성된 작업에서 추출됩니다. 추출에는 페이지당 약 44 ms가 소요되므로 일반적인 크롤링 속도를 충분히 따라잡을 수 있습니다.
extract_page_with_options 로 세밀한 제어
use rs_trafilatura::{Options, spider_integration::extract_page_with_options};
use rs_trafilatura::page_type::PageType;
let options = Options {
output_markdown: true, // Get GFM Markdown output
include_images: true, // Extract image metadata
favor_precision: true, // Stricter filtering
page_type: Some(PageType::Product), // Force page type
..Options::default()
};
let result = extract_page_with_options(&page, &options)?;
if let Some(md) = &result.content_markdown {
println!("Markdown:\n{}", md);
}
for img in &result.images {
println!("Image: {} (hero: {})", img.src, img.is_hero);
}
옵션에 URL을 제공하면 페이지 URL보다 우선적으로 분류에 사용됩니다; 그렇지 않으면 페이지 URL이 자동으로 사용됩니다.
추출 품질에 따른 필터링
for page in website.get_pages().into_iter().flatten() {
let url = page.get_url().to_string();
let result = extract_page(&page)?;
if result.extraction_quality {
// Add your filtering logic here
}
}
결과 필드
| 필드 | 형식 | 설명 |
|---|---|---|
content_markdown | Option<String> | GFM 마크다운 (활성화된 경우) |
content_html | Option<String> | HTML로 추출된 콘텐츠 |
metadata.title | Option<String> | 페이지 제목 |
metadata.author | Option<String> | 작성자 이름 |
metadata.date | Option<String> | 발행일 |
metadata.page_type | Option<PageType> | 감지된 페이지 유형 |
extraction_quality | f64 | 0.0–1.0 신뢰도 점수 |
images | Vec<Image> | 이미지 URL, 대체 텍스트, 캡션 |
spider_transformations와의 비교
spider는 자체 spider_transformations 크레이트를 제공하며, 페이지를 Markdown이나 일반 텍스트로 변환할 수 있습니다. 작동은 하지만, 기본적인 가독성 스타일 추출기로 다음과 같은 기능이 부족합니다:
- 머신러닝 기반 페이지 유형 분류
- 유형별 추출 프로파일(포럼 댓글 처리, 다중 섹션 병합, JSON‑LD 폴백)
- 추출 품질 점수화
- JSON‑LD, Open Graph, Dublin Core에서 구조화된 메타데이터 추출
rs‑trafilatura는 이러한 모든 기능을 제공합니다. 기사 중심의 크롤링에서는 spider_transformations만으로도 충분할 수 있지만, 다양한 페이지 유형을 마주하는 크롤링에서는 rs‑trafilatura가 훨씬 더 좋은 결과를 제공합니다.
링크
rs-trafilatura:- Python package:
spider:- Benchmark: