🔥알림🔥
① 테디노트 유튜브 -
구경하러 가기!
② LangChain 한국어 튜토리얼
바로가기 👀
③ 랭체인 노트 무료 전자책(wikidocs)
바로가기 🙌
④ RAG 비법노트 LangChain 강의오픈
바로가기 🙌
⑤ 서울대 PyTorch 딥러닝 강의
바로가기 🙌
랭체인(langchain) + 웹사이트 정보 추출 - 스키마 활용법 (6)
이번 포스팅에서는 랭체인(LangChain) 을 활용하여 웹사이트 본문을 스크래핑한 뒤, 형식(schema) 에 맞게 정보 추출 하는 방법에 대해 알아보겠습니다.
이번 튜토리얼에서는 langchain 의 웹사이트가 다소 복잡한 구조를 가지더라도 쉽게 크롤링해주는 Chromium 기반의 AsyncChromiumLoader()
의 사용법에 대해 다룹니다.
또한, 스크래핑된 웹 정보를 파싱해주는 도구인 BeautifulSoup
기반의 BeautifulSoupTransformer()
을 활용하여 스크래핑 된 HTML 문서에서 원하는 태그 정보만 추출하는 방법을 알아보겠습니다.
끝으로, 형식(schema) 기반 문서내용을 추출해 주는 create_extraction_chain()
을 활용하여 추출된 내용을 형식에 맞게 정리하는 방법도 알아보겠습니다.
✔️ (이전글) LangChain 튜토리얼
- 랭체인(langchain)의 OpenAI GPT 모델(ChatOpenAI) 사용법
- 랭체인(langchain) + 허깅페이스(HuggingFace) 모델 사용법
- 랭체인(langchain) + 챗(chat) - ConversationChain, 템플릿 사용법
- 랭체인(langchain) + 정형데이터(CSV, Excel) - ChatGPT 기반 데이터분석
- 랭체인(langchain) + 웹사이트 크롤링 - 웹사이트 문서 요약
🌱 환경설정
# 필요한 라이브러리 설치
# !pip install -q openai langchain playwright beautifulsoup4 nest-asyncio
# !playwright install
# OPENAI_API
# import os
# os.environ['OPENAI_API_KEY'] = 'OPENAI API KEY 입력'
# 토큰 정보로드를 위한 라이브러리
# 설치: pip install python-dotenv
from dotenv import load_dotenv
# 토큰 정보로드
load_dotenv()
True
# Async 로 Html 받아올 때 발생하는 에러 방지용 임시 코드
import nest_asyncio
nest_asyncio.apply()
🔥 웹스크래핑
① AsyncChromiumLoader()
-
Chromium은 브라우저 자동화를 제어하는 데 사용되는 라이브러리인 플레이라이트(
Playwright
) 에서 지원하는 브라우저 중 하나입니다. 여기서 Head-less 인스턴스의 Chromium을 실행합니다. Head-less 모드는 그래픽 사용자 인터페이스 없이 브라우저가 실행되고 있음을 의미합니다. -
AsyncChromiumLoader
는 페이지를 로드하고, 이후에Html2TextTransformer
를 사용하여 텍스트로 변환합니다.
from langchain.document_loaders import AsyncChromiumLoader
from langchain.document_transformers import BeautifulSoupTransformer
# Load HTML
loader = AsyncChromiumLoader(["https://news.naver.com/main/list.naver?mode=LS2D&mid=shm&sid1=101&sid2=259"])
html = loader.load()
html[0].page_content[:300]
'<!DOCTYPE html><html lang="ko" data-useragent="Mozilla/5.0 (X11; Linux aarch64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/117.0.5938.62 Safari/537.36"><head>\n<meta charset="euc-kr">\n<meta http-equiv="X-UA-Compatible" content="IE=edge">\n<meta name="referrer" contents="always">\n<meta http-'
HTML 콘텐츠에서 <p>
, <li>
, <div>
, <a>
태그와 같은 텍스트 콘텐츠 태그를 스크레이핑합니다.
(참고) HTML 태그 목록
-
<p>
: 단락 태그입니다. HTML에서 단락을 정의하며, 관련된 문장 및/또는 구를 함께 그룹화하는 데 사용됩니다. -
<li>
: 목록 항목 태그입니다. 정렬된 (<ol>
) 및 정렬되지 않은 (<ul>
) 목록 내에서 개별 항목을 정의하는 데 사용됩니다. -
<div>
: 구획 태그입니다. 다른 인라인 또는 블록 레벨 요소를 그룹화하는 데 사용되는 블록 레벨 요소입니다. -
<a>
: 앵커 태그입니다. 하이퍼링크를 정의하는 데 사용됩니다. -
<span>
: 텍스트의 일부 또는 문서의 일부를 마크업하는 데 사용되는 인라인 컨테이너입니다.
많은 뉴스 웹사이트(예: 네이버 뉴스, 다음 등)에서는 제목과 요약이 모두 태그 내에 있습니다.
② BeautifulSoupTransformer()
BeautifulSoupTransformer()
는 BeautifulSoup
을 사용하여 HTML/XML 문서를 파싱 하고 특정 태그와 콘텐츠만 추출할 수 있게 해줍니다.
# html 문서를 파싱
bs_transformer = BeautifulSoupTransformer()
docs_transformed = bs_transformer.transform_documents(html, tags_to_extract=['span'])
# 파싱결과의 일부 출력
print(docs_transformed[0].page_content[:500])
메인 메뉴로 바로가기 본문으로 바로가기 뉴스검색 전체삭제 자동저장 끄기켜기 도움말 전체삭제 자동저장 끄기켜기 끄기 켜기 도움말 | | 검색 NAVER 뉴스 언론사별 정치 경제 선택됨 사회 생활/문화 IT/과학 세계 랭킹 신문보기 오피니언 TV 팩트체크 알고리즘 안내 정정보도 모음 10.03(화) (화) 선택됨 2016년 6월 이후 7년 만에 셔틀 회의 재개 예정 한국과 일본이 금융당국 간 셔틀 회의를 7년 만에 재개하기로 했다. 금융위 … 더팩트 35분전 태국 중앙은행이 한국 인터넷은행의 성장성에 주목하며 토스뱅크를 찾았다. 토스뱅크는 태국 중앙은행의 로나돌 놈논다(Ronadol … 뉴시스 1시간전 가계대출 증가 억제 위해 금융당국 DSR 개편 추진 중장년층 미래소득 적으면 DSR 산정때 만기 축소 검토 강제성 부족했던 규제 … 매일경제 2시간전 추석 상여금 등으로 여유자금이 생겨 투자처를 고민하는 사람들이 많다. 전문가들은 경제 불확실성이 여전히 큰 상황에서 안전 자산
③ 문서를 Chunk 단위로 쪼개기
문서의 내용이 LLM 의 허용토큰의 최대 길이를 넘어가는 경우 에러가 발생합니다. 따라서, 문서를 특정 기준으로 쪼개는 작업을 선행합니다.
여기서는 RecursiveCharacterTextSplitter
모듈을 사용하여 문서를 3000개 chunk size 단위로 쪼개도록 하겠습니다.
from langchain.text_splitter import RecursiveCharacterTextSplitter
# 웹스크래핑 내용의 3000 글자 기준으로 내용 스플릿, 오버랩 없음.
splitter = RecursiveCharacterTextSplitter.from_tiktoken_encoder(chunk_size=3000,
chunk_overlap=0)
splits = splitter.split_documents(docs_transformed)
# 첫번째 스플릿 결과 출력
print(splits[0].page_content)
메인 메뉴로 바로가기 본문으로 바로가기 뉴스검색 전체삭제 자동저장 끄기켜기 도움말 전체삭제 자동저장 끄기켜기 끄기 켜기 도움말 | | 검색 NAVER 뉴스 언론사별 정치 경제 선택됨 사회 생활/문화 IT/과학 세계 랭킹 신문보기 오피니언 TV 팩트체크 알고리즘 안내 정정보도 모음 10.03(화) (화) 선택됨 2016년 6월 이후 7년 만에 셔틀 회의 재개 예정 한국과 일본이 금융당국 간 셔틀 회의를 7년 만에 재개하기로 했다. 금융위 … 더팩트 35분전 태국 중앙은행이 한국 인터넷은행의 성장성에 주목하며 토스뱅크를 찾았다. 토스뱅크는 태국 중앙은행의 로나돌 놈논다(Ronadol … 뉴시스 1시간전 가계대출 증가 억제 위해 금융당국 DSR 개편 추진 중장년층 미래소득 적으면 DSR 산정때 만기 축소 검토 강제성 부족했던 규제 … 매일경제 2시간전 추석 상여금 등으로 여유자금이 생겨 투자처를 고민하는 사람들이 많다. 전문가들은 경제 불확실성이 여전히 큰 상황에서 안전 자산으 … 디지털타임스 신문10면 2시간전 '킹 달러' 공포 속에 엔·달러 환율이 연중 최저치를 경신했다. 3일 도쿄 외환시장에서 엔·달러 환율은 장중 한때 149.91엔 … 디지털타임스 신문16면 2시간전 자영업자들이 은행·저축은행·상호금융 등 금융권에서 빌린 돈이 최근 2년 새 100조원 이상 불어난 것으로 나타났다. 경기침체가 … 아시아경제 2시간전 3개사 수익·실적 동반 악화 속 성장기반 확장 등 긍정적 평가 연말 인사철, 유임여부 촉각 임기 만료를 앞둔 카드사 CEO(대표 … 디지털타임스 신문10면 TOP 3시간전 블록체인 전문 투자사 해시드가 웹3 빌더 커뮤니티 '프로토콜 캠프(Protocol Camp)' 5기 활동을 시작했다고 3일 밝혔 … 뉴시스 3시간전 금융감독원은 업무혁신 로드맵(FSS) 도입 이후 지난 1년간 분쟁처리 건수가 30% 넘게 늘어나고 비조치 의견서 처리기간이 절반 … 파이낸셜뉴스 신문9면 3시간전 자산 2조원 이상 금융회사 74개사 중 30개사는 여성 등기이사가 한 명도 선임되지 않은 것으로 나타났다. 여성 등기이사 비율도 … 파이낸셜뉴스 신문9면 3시간전 은행연합회가 일본 은행협회와 함께 디지털화, ESG확산 등 글로벌 금융환경 변화에 대한 공동대응을 강화한다. 김광수 은행연합회 … 파이낸셜뉴스 신문9면 3시간전 "반월·시화BIZ프라임센터에는 다양한 분야에서 오랫동안 경험을 쌓은 RM들이 많습니다. 고객들이 우리은행의 문을 두드린 순간, … 파이낸셜뉴스 신문9면 3시간전 최근 '돈맥경화'에 시달리는 부동산 프로젝트파이낸싱(PF) 사업장에 대해 정부와 금융권이 21조원 이상의 신규 자금 공급이란 ' … 파이낸셜뉴스 신문9면 3시간전 KDB산업은행의 신입 행원 채용 일정(국제신문 지난달 7일 자 5면 보도)이 전면 연기됐다. 서류심사 평가위원에 부적격 인사가 … 국제신문 3시간전 보험업계의 숙원인 '실손보험 청구 간소화법'과 '보험사기 방지 특별법'이 여야 간 극한대립으로 표류하고 있다. 실손보험 청구 간 …
④ 스키마 정의 & 내용 추출
스키마는 문서에서 내용 추출시 원하는 형식이나 내용을 정의할 수 있도록 도와줍니다.
아래의 예시처럼 스키마를 정의하면, 웹스크래핑 문서에서 제목, 카테고리, 키워드 를 알아서 추출하고, 형식에 맞게 결과를 json 형식으로 반환합니다.
이때 create_extraction_chain()
모듈을 사용하여 쉽게 적용할 수 있습니다.
import pprint
from langchain.chains import create_extraction_chain
from langchain.chat_models import ChatOpenAI
# 스키마 정의
schema = {
"properties": {
"뉴스기사_제목": {"type": "string"},
"뉴스기사_카테고리": {"type": "string"},
"뉴스기사_키워드": {"type": "string"},
},
"required": ["뉴스기사_제목", "뉴스기사_카테고리", "뉴스기사_키워드"],
}
# LLM 정의
llm = ChatOpenAI(model_name="gpt-3.5-turbo-16k",
temperature=0)
# 문서내용 추출 체인객체 생성
ext_chain = create_extraction_chain(schema=schema, llm=llm)
# 첫번째 스플릿으로 실행한 결과
pprint.pprint(ext_chain.run(splits[0].page_content))
[{'뉴스기사_제목': '한국과 일본이 금융당국 간 셔틀 회의를 7년 만에 재개하기로 했다.', '뉴스기사_카테고리': '금융', '뉴스기사_키워드': '한국, 일본, 금융당국, 셔틀 회의'}, {'뉴스기사_제목': '태국 중앙은행이 한국 인터넷은행의 성장성에 주목하며 토스뱅크를 찾았다.', '뉴스기사_카테고리': '금융', '뉴스기사_키워드': '태국, 중앙은행, 한국 인터넷은행, 성장성, 토스뱅크'}, {'뉴스기사_제목': '가계대출 증가 억제 위해 금융당국 DSR 개편 추진', '뉴스기사_카테고리': '금융', '뉴스기사_키워드': '가계대출, 금융당국, DSR 개편'}, {'뉴스기사_제목': '추석 상여금 등으로 여유자금이 생겨 투자처를 고민하는 사람들이 많다.', '뉴스기사_카테고리': '금융', '뉴스기사_키워드': '추석, 상여금, 여유자금, 투자처'}, {'뉴스기사_제목': "'킹 달러' 공포 속에 엔·달러 환율이 연중 최저치를 경신했다.", '뉴스기사_카테고리': '금융', '뉴스기사_키워드': '킹 달러, 엔·달러 환율, 최저치'}, {'뉴스기사_제목': '자영업자들이 은행·저축은행·상호금융 등 금융권에서 빌린 돈이 최근 2년 새 100조원 이상 불어난 것으로 나타났다.', '뉴스기사_카테고리': '금융', '뉴스기사_키워드': '자영업자, 은행, 저축은행, 상호금융, 금융권, 빌린 돈'}, {'뉴스기사_제목': '3개사 수익·실적 동반 악화 속 성장기반 확장 등 긍정적 평가', '뉴스기사_카테고리': '금융', '뉴스기사_키워드': '수익, 실적, 성장기반'}, {'뉴스기사_제목': '은행연합회가 일본 은행협회와 함께 디지털화, ESG확산 등 글로벌 금융환경 변화에 대한 공동대응을 강화한다.', '뉴스기사_카테고리': '금융', '뉴스기사_키워드': '은행연합회, 일본 은행협회, 디지털화, ESG확산, 글로벌 금융환경'}, {'뉴스기사_제목': "최근 '돈맥경화'에 시달리는 부동산 프로젝트파이낸싱(PF) 사업장에 대해 정부와 금융권이 21조원 이상의 신규 자금 " "공급이란 ' …", '뉴스기사_카테고리': '금융', '뉴스기사_키워드': '돈맥경화, 부동산, 프로젝트파이낸싱, 정부, 금융권, 신규 자금'}, {'뉴스기사_제목': 'KDB산업은행의 신입 행원 채용 일정이 전면 연기됐다.', '뉴스기사_카테고리': '금융', '뉴스기사_키워드': 'KDB산업은행, 신입 행원, 채용 일정'}, {'뉴스기사_제목': "보험업계의 숙원인 '실손보험 청구 간소화법'과 '보험사기 방지 특별법'이 여야 간 극한대립으로 표류하고 있다.", '뉴스기사_카테고리': '금융', '뉴스기사_키워드': '보험업계, 실손보험 청구 간소화법, 보험사기 방지 특별법, 여야 간 극한대립'}]
🔥 전체코드
import pprint
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.document_loaders import AsyncChromiumLoader
from langchain.document_transformers import BeautifulSoupTransformer
from langchain.chains import create_extraction_chain
from langchain.chat_models import ChatOpenAI
def scrape_with_playwright(urls, extraction_chain):
# URL 로부터 본문 내용 웹스크래핑
loader = AsyncChromiumLoader(urls)
# 웹스크래핑 내용 로드
docs = loader.load()
# HTML 로더로 컨텐츠 로드
bs_transformer = BeautifulSoupTransformer()
# 특정 태그에 대한 내용만 추출 ('span')
docs_transformed = bs_transformer.transform_documents(docs,
tags_to_extract=["span"])
# 웹스크래핑 내용의 3000 글자 기준으로 내용 스플릿, 오버랩 없음.
splitter = RecursiveCharacterTextSplitter.from_tiktoken_encoder(chunk_size=3000,
chunk_overlap=0)
splits = splitter.split_documents(docs_transformed)
# 반환할 결과를 담을 리스트
extracted_contents = []
# 스플릿을 순회하며 schema 에 따라 내용 추출
for split in splits:
# 각 스플릿에 대하여 스키마 기반 내용 추출
extracted_content = extraction_chain.run(split.page_content)
extracted_contents.extend(extracted_content)
return extracted_contents
# 스키마 정의
schema = {
"properties": {
"뉴스기사_제목": {"type": "string"},
"뉴스기사_카테고리": {"type": "string"},
"뉴스기사_키워드": {"type": "string"},
},
"required": ["뉴스기사_제목", "뉴스기사_카테고리", "뉴스기사_키워드"],
}
# LLM 정의
llm = ChatOpenAI(model_name="gpt-3.5-turbo-16k",
temperature=0)
# 문서내용 추출 체인객체 생성
ext_chain = create_extraction_chain(schema=schema, llm=llm)
# 웹스크래핑 URL 정의
urls = ["https://news.naver.com/main/list.naver?mode=LS2D&mid=shm&sid1=101&sid2=259"]
# 웹스크래핑 및 스키마 기반 내용 추출
extracted_content = scrape_with_playwright(urls, ext_chain)
# 결과 출력
pprint.pprint(extracted_content)
댓글남기기