# Trafilatura 분석 및 기능 명세 분석 대상: `C:\Users\lasta\MyProject\AI\참고\trafilatura-master` 분석일: 2026-05-13 대상 버전: `trafilatura.__version__ = 2.0.0` 라이선스: Apache-2.0 ## 1. 결론 요약 Trafilatura는 웹 문서에서 본문, 댓글, 메타데이터, 링크 후보를 추출하기 위한 Python 라이브러리이자 CLI 도구다. 범용 온톨로지 구축 플랫폼에서는 “웹 원천 데이터 수집 및 정제 계층”의 기본 소스로 거의 그대로 사용하기에 적합하다. 가장 가치가 큰 기능은 다음이다. - 웹 페이지 다운로드: `fetch_url()`, `fetch_response()` - HTML 본문 추출: `extract()`, `bare_extraction()` - 구조 보존 추출: XML/HTML/Markdown/JSON/TEI 출력 - 메타데이터 추출: 제목, 저자, 날짜, canonical URL, 사이트명, 설명, 태그, 라이선스, 대표 이미지 - 링크 발견: RSS/Atom/JSON Feed, sitemap, robots.txt sitemap, focused crawler - 중복 제거: 본문 세그먼트 LRU 중복 검사, 문서 fingerprint용 SimHash - 설정 객체: `Extractor`, 결과 객체: `Document` 플랫폼 통합 권장 방식은 `bare_extraction(output_format="python", with_metadata=True)`를 기본으로 삼는 것이다. 이 방식은 문자열 출력으로 손실되기 전의 `Document` 객체, `body` XML tree, `commentsbody`, 정규화 텍스트, 메타데이터를 받을 수 있어 온톨로지 구축 전처리 단계와 연결하기 쉽다. 주의할 점은 전역 상태다. 다운로드 pool, 중복 LRU cache, crawler URL store가 모듈 전역에 존재한다. 단일 작업에서는 편하지만, 멀티 프로젝트/멀티 테넌트 플랫폼에서는 작업 단위 격리, cache reset, 도메인별 crawl 상태 저장을 별도 래퍼에서 관리해야 한다. ## 2. 프로젝트 구조 주요 디렉터리와 파일: | 경로 | 역할 | |---|---| | `trafilatura/__init__.py` | 공개 API re-export | | `trafilatura/core.py` | 추출 파이프라인 진입점 | | `trafilatura/main_extractor.py` | Trafilatura 기본 본문/댓글 추출 알고리즘 | | `trafilatura/htmlprocessing.py` | HTML 정리, 태그 변환, 링크 밀도 제거 | | `trafilatura/metadata.py` | 메타 태그, JSON-LD, OpenGraph, 날짜/저자/URL 추출 | | `trafilatura/json_metadata.py` | JSON-LD/schema.org 메타데이터 파싱 | | `trafilatura/downloads.py` | HTTP 다운로드, Response 객체, 병렬 다운로드 | | `trafilatura/feeds.py` | RSS/Atom/JSON feed 발견 및 URL 추출 | | `trafilatura/sitemaps.py` | sitemap/robots.txt 기반 URL 발견 | | `trafilatura/spider.py` | focused crawler | | `trafilatura/deduplication.py` | LRU segment dedup, SimHash fingerprint | | `trafilatura/xml.py` | JSON/CSV/XML/TEI/TXT 변환 | | `trafilatura/settings.py` | `Extractor`, `Document`, 전역 상수 | | `trafilatura/settings.cfg` | 사용자 조정 가능한 기본 설정 | | `docs/` | 사용법/설정/다운로드/크롤링/중복제거 문서 | | `tests/` | 단위 테스트, 실제 웹 페이지 평가 데이터 | ## 3. 외부 의존성 `pyproject.toml` 기준 필수 의존성: - `certifi`: TLS 인증서 - `charset_normalizer >= 3.4.0`: 인코딩 탐지 - `courlan >= 1.3.2`: URL 정규화, 필터링, URL store, 링크 추출 - `htmldate >= 1.9.2`: 날짜 추출 - `justext >= 3.0.1`: fallback 본문 추출 - `lxml`: HTML/XML 파싱 및 XPath - `urllib3 >= 1.26, < 3`: HTTP client 선택 의존성 `trafilatura[all]`: - `brotli`, `zstandard`: 압축 응답 처리 강화 - `py3langid`: 언어 판별 - `pycurl`: 빠른 HTTP backend - `urllib3[socks]`: SOCKS proxy - `htmldate[speed]`: 날짜 추출 속도 개선 ## 4. 핵심 데이터 모델 ### 4.1 `Extractor` 파일: `trafilatura/settings.py` 추출 옵션을 담는 설정 객체다. 함수 인자가 많기 때문에 플랫폼에서는 개별 인자보다 `Extractor` 객체를 만들어 넘기는 방식을 권장한다. 주요 속성: | 속성 | 의미 | 기본값 | |---|---|---| | `format` | 출력 형식 | `txt` | | `fast` | fallback 알고리즘 생략 | `False` | | `focus` | `balanced`, `precision`, `recall` | `balanced` | | `comments` | 댓글 추출 | `True` | | `formatting` | 굵게/기울임 등 구조 보존 | `False`, Markdown이면 자동 True | | `links` | 링크 target 보존 | `False` | | `images` | 이미지 정보 보존 | `False` | | `tables` | table 추출 | `True` | | `dedup` | 중복 세그먼트 제거 | `False` | | `lang` | 목표 언어 필터 | `None` | | `url` | 원문 URL | `None` | | `with_metadata` | 메타데이터 추출/출력 포함 | `False` | | `only_with_metadata` | 핵심 메타데이터 없으면 폐기 | `False` | | `tei_validation` | TEI 출력 검증 | `False` | | `date_params` | `htmldate` 날짜 추출 옵션 | 현재 날짜 max_date | | `author_blacklist` | 제외할 저자명 집합 | 빈 set | | `url_blacklist` | 제외할 URL 집합 | 빈 set | ### 4.2 `Document` 파일: `trafilatura/settings.py` 추출 결과와 메타데이터를 담는 객체다. 필드: | 필드 | 설명 | |---|---| | `title` | 제목 | | `author` | 저자 | | `url` | canonical URL 또는 입력 URL | | `hostname` | 호스트명 | | `description` | 설명/요약 메타 | | `sitename` | 사이트명/매체명 | | `date` | 발행일 | | `categories` | 카테고리 목록 | | `tags` | 태그 목록 | | `fingerprint` | SimHash 기반 문서 fingerprint | | `id` | 호출자가 넘긴 record id | | `license` | 라이선스 정보 | | `body` | 본문 XML tree | | `comments` | 댓글 텍스트 | | `commentsbody` | 댓글 XML tree | | `raw_text` | 내부 추출 텍스트 | | `text` | 최종 출력 문자열 또는 python 모드 텍스트 | | `language` | 감지 언어 | | `image` | 대표 이미지 | | `pagetype` | OpenGraph page type | | `filedate` | 파일 날짜 | `Document.as_dict()`로 dict 변환이 가능하다. ## 5. 본문 추출 파이프라인 핵심 진입점: - `extract(filecontent, ...) -> Optional[str]` - `extract_with_metadata(filecontent, ...) -> Optional[Document]` - `bare_extraction(filecontent, ...) -> Optional[Document]` 권장 기본 호출: ```python from trafilatura import bare_extraction doc = bare_extraction( html, url=url, output_format="python", with_metadata=True, include_comments=False, include_tables=True, include_formatting=True, include_links=True, deduplicate=True, ) ``` 처리 순서: 1. `load_html()`로 문자열/bytes/LXML 입력을 HTML tree로 변환한다. 2. `target_language`가 있고 fast mode이거나 언어 판별 모듈이 없으면 HTML lang 속성을 먼저 검사한다. 3. `with_metadata=True`이면 `extract_metadata()`로 메타데이터를 추출한다. 4. `only_with_metadata=True`이면 `date`, `title`, `url`이 모두 없을 때 문서를 폐기한다. 5. 사용자가 지정한 `prune_xpath`를 tree에서 제거한다. 6. `tree_cleaning()`으로 불필요 태그와 섹션을 제거한다. 7. `convert_tags()`로 HTML 태그를 내부 구조 태그로 변환한다. 8. `include_comments=True`이면 댓글 영역을 먼저 추출하고 본문 tree에서 분리한다. 9. `extract_content()`로 Trafilatura 기본 본문 추출을 수행한다. 10. `fast=False`이면 readability/jusText 계열 fallback과 비교하여 더 나은 결과를 선택한다. 11. 본문 길이가 너무 짧고 precision 모드가 아니면 `baseline()` fallback을 수행한다. 12. `deduplicate=True`이면 LRU cache 기반 중복 본문을 폐기한다. 13. `target_language`가 있으면 최종 텍스트 언어를 검사한다. 14. 요청 형식에 따라 TXT/Markdown/JSON/CSV/HTML/XML/TEI로 변환한다. ## 6. 출력 형식 지원 형식: | 형식 | 함수 인자 | 용도 | |---|---|---| | Python object | `bare_extraction(output_format="python")` | 온톨로지 파이프라인 권장 | | Plain text | `output_format="txt"` | 단순 텍스트 저장 | | Markdown | `output_format="markdown"` | 구조 일부 보존, LLM 입력에 유용 | | JSON | `output_format="json"` | API 저장/교환 | | CSV | `output_format="csv"` | 배치 처리 결과 | | HTML | `output_format="html"` | 정제된 HTML preview | | XML | `output_format="xml"` | 구조 보존 | | XML-TEI | `output_format="xmltei"` | 인문학/말뭉치 표준 | 온톨로지 구축 플랫폼에서는 다음 전략이 적합하다. - 원천 보존: raw HTML 별도 저장 - 추출 본문: `Document.text` - 구조 본문: `Document.body` - 메타데이터: `Document.as_dict()` 중 primitive 필드 - LLM/IE 입력: Markdown 또는 XML 변환본 - 장기 말뭉치 교환: XML-TEI 선택 가능 ## 7. 메타데이터 추출 기능 파일: `trafilatura/metadata.py`, `trafilatura/json_metadata.py` 추출 출처: - OpenGraph: `og:title`, `og:description`, `og:site_name`, `og:image`, `og:type`, `og:url` - Twitter cards: `twitter:title`, `twitter:description`, `twitter:image`, `twitter:site`, `twitter:url` - 표준 meta name: `author`, `description`, `keywords`, `publisher`, `dc.*`, `dcterms.*`, `citation_*` - JSON-LD/schema.org: `application/ld+json` - HTML heading: `h1`, `h2` - canonical/base/alternate link - `htmldate.find_date()` 기반 날짜 추출 - Creative Commons license URL/text 패턴 기능 명세: | 기능명 | 입력 | 출력 | 실패 조건 | |---|---|---|---| | `extract_metadata` | HTML tree/string, URL, date params | `Document` | HTML 파싱 실패 시 빈/부분 Document | | `extract_meta_json` | HTML tree, Document | JSON-LD 반영 Document | JSON 파싱 실패 시 fallback parser 사용 | | `extract_opengraph` | HTML tree | dict | 해당 meta 없으면 None 값 | | `extract_title` | HTML tree | str 또는 None | 제목 후보 없음 | | `extract_author` | HTML tree | str 또는 None | 저자 후보 없음 | | `extract_url` | HTML tree, default URL | str 또는 None | URL 후보 없음/invalid | | `extract_license` | HTML tree | str 또는 None | license 후보 없음 | 플랫폼 적용: - `title`, `author`, `date`, `sitename`, `url`, `description`, `tags`, `categories`를 `SourceDocument` 메타로 저장한다. - `url`과 `date`는 provenance 및 temporal ontology 축의 핵심 속성으로 사용한다. - `tags/categories`는 초기 후보 개념(seed concept)으로 사용할 수 있으나, 사이트별 노이즈가 많으므로 confidence를 낮게 둔다. ## 8. 다운로드 기능 파일: `trafilatura/downloads.py` 주요 API: | 기능명 | 설명 | |---|---| | `fetch_url(url)` | HTML을 다운로드하고 decode한 문자열 반환 | | `fetch_response(url, decode=False, with_headers=False)` | `Response` 객체 반환 | | `buffered_downloads()` | URL buffer 병렬 다운로드 | | `buffered_response_downloads()` | Response 객체 병렬 다운로드 | | `is_live_page(url)` | URL 접근 가능성 확인 | `Response` 필드: - `data`: bytes - `headers`: optional dict - `html`: optional decoded string - `status`: HTTP status - `url`: 최종 URL 설정: | 설정 | 기본값 | 설명 | |---|---:|---| | `DOWNLOAD_TIMEOUT` | 30 | 요청 timeout | | `MAX_FILE_SIZE` | 20000000 | 최대 파일 크기 | | `MIN_FILE_SIZE` | 10 | 최소 파일 크기 | | `SLEEP_TIME` | 5.0 | 동일 host 요청 간격 | | `MAX_REDIRECTS` | 2 | redirect 허용 횟수 | | `USER_AGENTS` | empty | 사용자 user-agent 후보 | | `COOKIE` | empty | 요청 cookie | 플랫폼 적용: - 이미 프로젝트에 크롤러가 있다면 `fetch_url()`을 직접 대체하기보다 HTML 추출 단계에 Trafilatura를 붙이는 것이 안전하다. - Trafilatura downloader를 쓰는 경우 도메인별 throttling과 robots 정책을 서비스 단에서 명시적으로 기록해야 한다. - `fetch_response(decode=True, with_headers=True)`는 최종 URL, status, header provenance 저장에 적합하다. ## 9. 링크 발견 기능 ### 9.1 Feed 발견 파일: `trafilatura/feeds.py` 주요 API: ```python from trafilatura.feeds import find_feed_urls urls = find_feed_urls("https://example.com", target_lang="ko") ``` 지원: - Atom - RSS/RDF - JSON Feed - HTML 내 `` - HTML 내 feed 후보 `` - Google News RSS fallback - 언어 필터/도메인 유사도 필터 기능 명세: | 기능명 | 입력 | 출력 | 정책 | |---|---|---|---| | `find_feed_urls` | URL, target_lang, external, sleep_time | 정렬/중복 제거 URL 목록 | 기본적으로 유사 도메인만 허용 | | `determine_feed` | HTML 문자열 | feed URL 목록 | feed MIME/type/URL 패턴 사용 | | `extract_links` | feed 문자열 | article URL 목록 | feedburner/feedproxy 예외 처리 | ### 9.2 Sitemap 발견 파일: `trafilatura/sitemaps.py` 주요 API: ```python from trafilatura.sitemaps import sitemap_search urls = sitemap_search("https://example.com", target_lang="ko") ``` 지원: - `robots.txt`의 Sitemap 항목 - 일반 sitemap guess: `sitemap.xml`, `sitemap.xml.gz`, `sitemap_index.xml`, `sitemap_news.xml` - XML sitemap - TXT sitemap - hreflang 기반 target language - nested sitemap - URL filter - 유사 도메인 필터 기능 명세: | 기능명 | 입력 | 출력 | 제한 | |---|---|---|---| | `sitemap_search` | URL, target_lang, external, sleep_time, max_sitemaps | URL 목록 | 기본 최대 sitemap 10,000개 | | `find_robots_sitemaps` | base URL | sitemap URL 목록 | robots.txt 10KB 초과 시 폐기 | | `is_plausible_sitemap` | URL, contents | bool | HTML 응답이면 sitemap 아님 | ### 9.3 Focused crawler 파일: `trafilatura/spider.py` 주요 API: ```python from trafilatura.spider import focused_crawler todo, known = focused_crawler( "https://example.com", max_seen_urls=10, max_known_urls=100000, lang="ko", ) ``` 특징: - 시작 URL 기준 내부 링크 탐색 - robots.txt 파싱 및 `can_fetch("*", link)` 적용 - `Crawl-Delay` 반영 - navigation page 우선 탐색 - `todo`, `known_links`를 외부에서 주입해 단계별 crawl 가능 - 언어 필터 가능 주의: - `URL_STORE`가 모듈 전역이다. 여러 crawl 작업을 동시에 실행하면 상태 충돌 위험이 있다. - 플랫폼에서는 Trafilatura crawler를 그대로 병렬 호출하기보다, 작업별 프로세스 격리 또는 `courlan.UrlStore` 래핑이 필요하다. ## 10. 중복 제거와 fingerprint 파일: `trafilatura/deduplication.py` 기능: - 세그먼트 중복 제거: `duplicate_test(element, options)` - 문서 fingerprint: `content_fingerprint(content)` - SimHash 비교: `Simhash.similarity()` - 도메인 문자열 유사도: `is_similar_domain()` - token sampling과 BLAKE2b hash 기능 명세: | 기능명 | 입력 | 출력 | 용도 | |---|---|---|---| | `duplicate_test` | LXML element, Extractor/options | bool | 반복 boilerplate 제거 | | `content_fingerprint` | 문자열 | hex SimHash | 문서 near-duplicate 키 | | `Simhash.similarity` | 다른 Simhash | 0.0-1.0 | 유사 문서 판정 | | `generate_bow_hash` | 문자열 | bytes | bag-of-words hash | 설정: - `MIN_DUPLCHECK_SIZE = 100` - `MAX_REPETITIONS = 2` - 전역 LRU cache 크기: `LRU_SIZE = 4096` 플랫폼 적용: - 추출 중 `deduplicate=True`는 페이지 내부 반복 요소 제거에 유용하다. - 문서 단위 중복 제거는 `content_fingerprint(title + raw_text)`를 저장하고, 플랫폼 DB에서 유사도/중복 정책을 별도로 운영하는 것이 좋다. - 전역 `LRU_TEST`는 긴 배치 작업에서 도메인 간 영향을 줄 수 있으므로 작업 단위로 `trafilatura.meta.reset_caches()` 호출을 고려한다. ## 11. HTML 처리와 구조 보존 파일: `trafilatura/htmlprocessing.py`, `trafilatura/main_extractor.py`, `trafilatura/xml.py` 보존 가능한 구조: - 문단: `p` - 제목: `head` - 목록: `list`, `item` - 인용: `quote` - 코드: `code` - 줄바꿈: `lb` - 삭제/변경: `del` - 강조/서식: `hi` - 링크: `ref target="..."` - 이미지: `graphic` - 표: `table`, `row`, `cell` 온톨로지 플랫폼 관점에서는 `Document.body` XML tree가 중요하다. 활용 예: - 제목/소제목을 문서 chunk hierarchy로 사용 - 목록 항목을 독립 주장 후보로 분해 - 표를 entity-attribute 후보로 변환 - 링크를 외부 참조 관계로 저장 - 이미지 alt/title을 보조 설명 텍스트로 저장 - 코드 블록은 일반 자연어 추출 대상에서 제외하거나 별도 타입으로 저장 ## 12. 설정 명세 파일: `trafilatura/settings.cfg` 플랫폼 기본 권장값: | 목적 | 설정/인자 | 권장 | |---|---|---| | 고품질 본문 추출 | `fast=False` | 기본 | | 대량 수집 속도 | `fast=True` | 낮은 priority batch | | 온톨로지 입력 | `output_format="python"` | 기본 | | 구조 보존 | `include_formatting=True`, `include_links=True` | 권장 | | 댓글 제외 | `include_comments=False` | 기본 권장 | | 표 포함 | `include_tables=True` | 권장 | | 이미지 후보 | `include_images=True` | 필요 시 | | 언어 필터 | `target_language="ko"` 등 | 소스 도메인별 설정 | | URL blacklisting | `url_blacklist` | 플랫폼 정책 DB와 연동 | | 저자 제외 | `author_blacklist` | “편집부”, “관리자” 등 제거 | | 날짜 strictness | `date_extraction_params` | max_date 고정 | `settings.cfg`에서 조정할 값: | 키 | 의미 | |---|---| | `DOWNLOAD_TIMEOUT` | 다운로드 제한 시간 | | `MAX_FILE_SIZE` | 입력 최대 크기 | | `MIN_FILE_SIZE` | 입력 최소 크기 | | `SLEEP_TIME` | 동일 도메인 요청 간격 | | `MAX_REDIRECTS` | redirect 횟수 | | `MIN_EXTRACTED_SIZE` | fallback 발동 기준 본문 길이 | | `MIN_OUTPUT_SIZE` | 최종 본문 최소 길이 | | `EXTRACTION_TIMEOUT` | CLI 추출 timeout | | `MIN_DUPLCHECK_SIZE` | 중복 검사 최소 길이 | | `MAX_REPETITIONS` | 허용 반복 횟수 | | `EXTENSIVE_DATE_SEARCH` | 날짜 탐색 범위 | | `EXTERNAL_URLS` | feed/sitemap 외부 URL 허용 | ## 13. 범용 온톨로지 구축 플랫폼 통합 설계 ### 13.1 권장 파이프라인 ```text Seed URL -> Feed/Sitemap/Crawler URL discovery -> URL normalization/dedup -> Download raw HTML -> Trafilatura bare_extraction -> Document metadata/provenance 저장 -> 구조 유지 chunking -> 언어/품질/중복 필터 -> 엔티티/관계/속성 후보 추출 -> ontology schema mapping -> graph/vector/document store 적재 ``` ### 13.2 Trafilatura 채택 범위 거의 그대로 사용 권장: - `core.py`의 `extract`, `bare_extraction`, `extract_with_metadata` - `metadata.py`의 메타데이터 추출 - `downloads.py`의 단일 다운로드 및 Response 모델 - `feeds.py`의 feed discovery - `sitemaps.py`의 sitemap discovery - `deduplication.py`의 `content_fingerprint`, `Simhash` - `xml.py`의 출력 변환 - `settings.py`의 `Extractor`, `Document` 래퍼 필요: - `spider.py`: 전역 `URL_STORE` 때문에 작업별 격리 필요 - `downloads.py`: 전역 HTTP pool과 user-agent/cookie 정책 관리 필요 - `deduplication.py`: 전역 LRU cache 초기화 정책 필요 - CLI 계층: 플랫폼 내부에서는 직접 CLI보다 Python API 사용 권장 수정 또는 확장 후보: - 한국어/다국어 품질 점수 산정 - ontology chunk id/provenance 부여 - 표를 relation candidate로 변환하는 후처리 - link target을 source graph edge로 변환 - source별 extraction profile 관리 - 실패 사유와 추출 품질 metrics 기록 ### 13.3 플랫폼 내 모듈 제안 | 플랫폼 모듈 | Trafilatura 연결 | |---|---| | `SourceDiscoveryService` | `find_feed_urls`, `sitemap_search`, `focused_crawler` | | `PageFetchService` | `fetch_response` | | `ContentExtractionService` | `bare_extraction` | | `MetadataNormalizer` | `Document` 필드 정규화 | | `DocumentChunker` | `Document.body` XML tree 기반 | | `QualityScorer` | 본문 길이, 언어, 메타 completeness, 중복 여부 | | `ProvenanceStore` | URL, hostname, date, fingerprint, raw HTML path | | `OntologyCandidateBuilder` | title/head/list/table/ref/tag 기반 candidate 생성 | ## 14. 정확한 기능 명세 ### F-001 웹 페이지 다운로드 - 입력: URL, SSL 옵션, config/options - 처리: HTTP GET, redirect 제한, timeout, 크기 제한, charset decode - 출력: HTML 문자열 또는 `Response` - 예외/실패: non-200, 크기 미달/초과, SSL/네트워크 오류 - 수용 기준: 성공 시 최종 URL과 status를 기록할 수 있어야 한다. ### F-002 HTML 파싱 - 입력: HTML string/bytes/LXML element - 처리: 압축 파일 처리, encoding detect, faulty HTML repair, LXML tree 생성 - 출력: `HtmlElement` - 실패: 빈 입력, 파싱 불가 - 수용 기준: 문자열과 이미 파싱된 LXML tree 모두 동일 추출 파이프라인에 들어갈 수 있어야 한다. ### F-003 본문 추출 - 입력: HTML tree, `Extractor` - 처리: cleanup, tag conversion, main extractor, fallback 비교, baseline rescue - 출력: `Document.body`, `Document.text`, `Document.raw_text` - 실패: 본문 최소 길이 미달, 언어 불일치, 중복 폐기 - 수용 기준: `favor_precision`, `favor_recall`, `fast` 옵션에 따라 결과가 조정되어야 한다. ### F-004 댓글 추출 - 입력: HTML tree, `include_comments` - 처리: 댓글 XPath 후보 추출 후 본문 tree에서 제거 - 출력: `Document.comments`, `Document.commentsbody` - 실패: 댓글 길이 미달이면 빈 댓글로 처리 - 수용 기준: 댓글 포함 여부를 소스/도메인별로 설정할 수 있어야 한다. ### F-005 표 추출 - 입력: HTML `