LinkContentFetcher

LinkContentFetcher

LinkContentFetcher를 쓰면 여러 URL의 내용을 파이프라인의 데이터로 사용할 수 있어요. 인덱싱 파이프라인과 쿼리 파이프라인에서 주어진 URL의 내용을 가져올 수 있어요.

출처: LinkContentFetcher

본문

개요

LinkContentFetcher는 주어진 urls의 내용을 가져와서 콘텐츠 스트림 목록을 반환해요. 목록의 각 항목은 성공적으로 가져온 링크 하나의 내용을 담은 ByteStream 객체예요. 반환된 목록의 각 객체 메타데이터에는 콘텐츠 타입(content_type 키)과 URL(url 키)이 들어 있어요.

예를 들어 LinkContentFetcher에 URL 열 개를 넘기고 그중 여섯 개를 가져오는 데 성공하면, 출력은 여섯 개의 ByteStream 객체 목록이 돼요. 각각의 콘텐츠 타입과 URL 정보를 담고 있죠.

어떤 사이트는 LinkContentFetcher가 콘텐츠를 가져오지 못하게 차단할 수도 있어요. 그 경우 오류를 로그로 남기고 성공적으로 가져온 ByteStream 객체만 반환해요.

이 컴포넌트를 파이프라인에서 쓰려면 보통 반환된 ByteStream 객체 목록을 Document 객체 목록으로 변환해야 해요. 그러려면 HTMLToDocument 컴포넌트를 사용하면 돼요.

LinkContentFetcher를 인덱싱 파이프라인 시작 부분에 두면 URL 내용을 Document Store로 인덱싱할 수 있어요. 검색·증강 생성(RAG) 파이프라인 같은 쿼리 파이프라인에서도 바로 써서 URL 내용을 데이터 소스로 활용할 수 있어요.

보안 고려사항

LinkContentFetcher는 전달받은 URL을 요청해요. 그 URL이 최종 사용자에게서 직접 온다면, 서버 측 요청 위조(SSRF) 위험에 환경이 노출될 수 있어요.

LinkContentFetcher를 호출하기 전에 애플리케이션은 사용자가 제공한 URL을 검증하고 정화해야 해요. 예를 들어:

  • https 같은 기대하는 스킴만 허용해요.
  • 가능하면 신뢰할 수 있는 도메인의 허용 목록(allowlist)을 사용해요.
  • localhost, link-local, 사설 네트워크 대상은 차단해요.
  • 프로덕션에서는 아웃바운드 프록시나 네트워크 레벨의 이그레스(egress) 제한을 고려해요.

예를 들어 애플리케이션이 표준 라이브러리의 ipaddress 모듈로 사설, 루프백, link-local, 예약 IP, 커스텀 IP 범위를 차단할 수 있어요.

import ipaddress
from urllib.parse import urlparse

PRIVATE_RANGES = (
    ipaddress.ip_network("127.0.0.0/8"),
    ipaddress.ip_network("10.0.0.0/8"),
    ipaddress.ip_network("172.16.0.0/12"),
    ipaddress.ip_network("192.168.0.0/16"),
    ipaddress.ip_network("169.254.0.0/16"),
)

def is_unsafe_url(url: str) -> bool:
    parsed = urlparse(url)
    if parsed.scheme != "https" or not parsed.hostname:
        return True
    try:
        ip = ipaddress.ip_address(parsed.hostname)
    except ValueError:
        # Hostname (not a raw IP). Apply your own domain allowlist policy here. Filter out "LOCALHOST" etc.
        return False
    return (
        ip.is_private
        or ip.is_loopback
        or ip.is_link_local
        or ip.is_reserved
        or any(ip in net for net in PRIVATE_RANGES)
    )

사용법

단독 사용 예시예요. LinkContentFetcher가 URL 하나의 내용을 가져와요. 기본 설정으로 컴포넌트를 초기화하고 있어요. retry_attempts 같은 기본 설정을 바꾸려면 API reference 문서를 확인하세요.

from haystack.components.fetchers import LinkContentFetcher

fetcher = LinkContentFetcher()

fetcher.run(urls=["https://haystack.deepset.ai"])

파이프라인 안에서:

아래는 LinkContentFetcher로 지정한 URL의 내용을 InMemoryDocumentStore에 인덱싱하는 인덱싱 파이프라인 예시예요. HTMLToDocument 컴포넌트로 ByteStream 객체 목록을 Document 객체로 변환하는 점을 눈여겨보세요.

from haystack import Pipeline
from haystack.document_stores.in_memory import InMemoryDocumentStore
from haystack.components.fetchers import LinkContentFetcher
from haystack.components.converters import HTMLToDocument
from haystack.components.writers import DocumentWriter

document_store = InMemoryDocumentStore()
fetcher = LinkContentFetcher()
converter = HTMLToDocument()
writer = DocumentWriter(document_store=document_store)

indexing_pipeline = Pipeline()
indexing_pipeline.add_component(instance=fetcher, name="fetcher")
indexing_pipeline.add_component(instance=converter, name="converter")
indexing_pipeline.add_component(instance=writer, name="writer")

indexing_pipeline.connect("fetcher.streams", "converter.sources")
indexing_pipeline.connect("converter.documents", "writer.documents")

indexing_pipeline.run(
    data={
        "fetcher": {
            "urls": [
                "https://haystack.deepset.ai/blog/guide-to-using-zephyr-with-haystack2",
            ],
        },
    },
)

더 알아보기 (Learn more)