본문으로 바로가기
반응형

WebBaseLoader

langchain_community의 WebBaseLoader는 LangChain 라이브러리에서 제공하는 커뮤니티 확장 로더 중 하나로, 웹 페이지의 내용을 쉽게 가져올 수 있도록 설계된 도구이다. 이 로더는 웹 페이지의 HTML 콘텐츠를 가져와 텍스트로 변환하고, 이를 LangChain의 문서 처리 파이프라인에 통합할 수 있도록 도와준다.

주요 특징

  • 웹 페이지의 텍스트를 추출하여 LangChain의 문서 객체로 변환
  • BeautifulSoup과 같은 HTML 파싱 라이브러리를 내부적으로 사용하여 웹 콘텐츠를 처리
  • 여러 URL을 한 번에 처리할 수있음

필자는 네이버 뉴스를 따왔다.

아무 뉴스 링크나 상관없다. 본인만의 방식으로 원하는 주제의 링크들을 가지고 오자.

지드래곤 콘서트가 최근 핫해서 지드래곤 콘서트 주제 위주로 네이버 뉴스에서 가지고 와서 중복을 제거한 후 

filtered_links에 넣어준다

 

이런 식의 결과를 받을 수 있다.

 

from langchain_community.document_loaders import WebBaseLoader
import bs4

loader = WebBaseLoader(
    web_paths=["https://example.com/news1", "https://example.com/news2"],
    bs_kwargs=dict(
        parse_only=bs4.SoupStrainer(class_="news-content")  # 특정 클래스만 추출
    ),
    requests_per_second=1,  # 초당 1개 요청
    show_progress=True,  # 진행 상황 출력
    headers={"User-Agent": "Mozilla/5.0"},  # 사용자 에이전트 설정, 크롤링 감지 못하게
    timeout=10  # 요청 타임아웃 10초
)

docs = loader.load()

 

이런식으로 WebBaseLoader를 사용하면 아래와 같은 docs 리스트가 생성된다

[
    Document(
        page_content="이것은 뉴스 본문입니다.",
        metadata={
            "source": "https://example.com/news1"
        }
    ),
    Document(
        page_content="이것은 또 다른 뉴스 본문입니다.",
        metadata={
            "source": "https://example.com/news2"
        }
    )
]

 

해당 docs를 다시 JSON으로 저장해보자

import json

# docs를 JSON 파일로 저장
with open("news_documents.json", "w", encoding="utf-8") as file:
    json_data = [
        {
            "url": doc.metadata['source'],  # URL 정보
            "content": doc.page_content    # 본문 내용
        }
        for doc in docs
    ]
    json.dump(json_data, file, ensure_ascii=False, indent=4)  # JSON 저장

print("뉴스 문서가 news_documents.json 파일에 저장되었습니다.")

 

 

이런식으로 url과 content로 나뉘어진다. 

 

하지만 content에 너무 쓸데없는 말이 많다.

그렇기에 이 부분을 없애는 전처리 과정이 필요하다. 

 

import json
import re

def clean_content(content):
    """
    본문에서 불필요한 텍스트를 제거하는 함수.
    """
    # 제거할 불필요한 텍스트 패턴 리스트
    patterns = [
        r'구독.*?\n',  # '구독' 관련 텍스트 제거
        r'Copyright.*',  # 저작권 관련 텍스트 제거
        r'기자.*?\n',  # 기자 정보 제거
        r'댓글.*?\n',  # 댓글 관련 텍스트 제거
        r'SNS 보내기.*?\n',  # SNS 관련 텍스트 제거
        r'닫기 글자 크기 변경하기 가1단계 작게 가2단계 보통 가3단계 크게 가4단계 아주크게 가5단계 최대크게 SNS 보내기 인쇄하기',  # 글자 크기 변경 관련 텍스트 제거
        r'댓글 본문 요약봇 본문 요약봇',  # 본문 요약봇 관련 텍스트 제거
        r'도움말 자동 추출 기술로 요약된 내용입니다.*?닫기',  # 요약봇 도움말 제거
        r'텍스트 음성 변환 서비스 사용하기.*?본문듣기 시작',  # 텍스트 음성 변환 관련 텍스트 제거
        r'쏠쏠정보.*?후속강추.*?\n',  # '쏠쏠정보' 관련 텍스트 제거
        r'이 기사를 추천합니다.*?닫기',  # 기사 추천 관련 텍스트 제거
        r'QR 코드를 클릭하면.*?촬영해보세요.',  # QR 코드 관련 텍스트 제거
        r'이 시각 가장 뜨거운 뉴스.*?닫기',  # '이 시각 가장 뜨거운 뉴스' 관련 텍스트 제거
        r'메인에서 바로 보는 언론사 편집 뉴스.*?확인해보세요!',  # 메인 뉴스 관련 텍스트 제거
        r'이슈.*?다음',  # '이슈' 섹션 관련 텍스트 제거
        r'주요뉴스.*?아웃링크',  # 주요뉴스 관련 텍스트 제거
    ]

    # 각 패턴을 순회하며 본문에서 제거
    for pattern in patterns:
        content = re.sub(pattern, '', content, flags=re.DOTALL)

    # 연속된 공백 및 줄바꿈 정리
    content = re.sub(r'\n+', '\n', content).strip()
    return content

# docs를 정리된 JSON 파일로 저장
with open("cleaned_news_documents.json", "w", encoding="utf-8") as file:
    json_data = [
        {
            "url": doc.metadata['source'],  # URL 정보
            "content": clean_content(doc.page_content)  # 본문 내용 정리
        }
        for doc in docs
    ]
    json.dump(json_data, file, ensure_ascii=False, indent=4)  # JSON 저장

print("정리된 뉴스 문서가 cleaned_news_documents.json 파일에 저장되었습니다.")

 

완벽하게 전처리가 이루어지진 않았지만 어느정도 이루어졌다고 생각하여 여기서 넘어가겠다.

다음은 청크 단위로 구분하는 포스트이다.

반응형