5가지 웹 스크래핑 방법

LangChain과 대형 언어 모델(LLM)을 이용한 웹 스크래핑 방법 포함!

소개

웹 스크래핑은 웹사이트에서 데이터를 추출하는 기술로, 데이터 수집과 분석을 자동화할 수 있는 강력한 도구입니다. 현대의 데이터 중심 사회에서 웹 스크래핑은 비즈니스, 연구, 개발 등의 다양한 분야에서 널리 사용되고 있습니다. 예를 들어, 경쟁사 분석을 위해 가격 정보를 수집하거나, 시장 동향을 파악하기 위해 소셜 미디어 데이터를 수집하는 등의 용도로 활용됩니다. 이처럼 웹 스크래핑은 수작업으로는 불가능한 대규모 데이터 수집을 가능하게 하여, 시간과 비용을 절감하고, 정확한 데이터 기반 의사 결정을 지원합니다.

웹 스크래핑을 효과적으로 수행하려면 다양한 기술과 도구를 이해하고 사용할 수 있어야 합니다. 간단한 HTML 파싱부터 복잡한 동적 웹 페이지의 데이터 추출, 그리고 최신의 대형 언어 모델(LLM)을 활용한 방법까지, 각각의 방법은 고유한 장점과 사용 사례를 가지고 있습니다. 이번 글에서는 웹 스크래핑의 기초를 시작으로, 다섯 가지 주요 웹 스크래핑 방법을 소개합니다. 특히, 최신 기술인 LangChain과 LLM을 활용한 웹 스크래핑 방법에 대해 자세히 다루어, 독자들이 최신 웹 스크래핑 기술을 이해하고 적용할 수 있도록 돕고자 합니다.

I. 기본 HTML 이해하기

웹 스크래핑을 시작하기 전에 HTML의 기본 구조를 이해하는 것이 중요합니다. HTML(하이퍼텍스트 마크업 언어)은 웹 페이지를 구성하는 기본 언어로, 태그와 속성으로 구성됩니다. 웹 페이지의 콘텐츠는 HTML 태그 안에 포함되며, 이러한 태그는 웹 페이지의 구조를 정의합니다. 웹 스크래핑을 통해 데이터를 추출하려면 이러한 태그와 속성을 잘 이해하고, 원하는 데이터를 정확히 찾아낼 수 있어야 합니다.

HTML 문서는 계층 구조로 되어 있으며, 각 요소는 다른 요소를 포함하거나 포함될 수 있습니다. 예를 들어, <html> 태그는 전체 HTML 문서를 감싸고, 그 안에는 <head><body> 태그가 있습니다. <body> 태그 안에는 다양한 콘텐츠 태그가 포함되며, 각 태그는 고유한 역할을 합니다. 예를 들어, <h1> 태그는 주요 제목을 나타내고, <p> 태그는 단락을 나타내며, <a> 태그는 하이퍼링크를 나타냅니다.

웹 스크래핑을 할 때는 특정 태그를 찾고 그 안에 포함된 데이터를 추출하는 것이 일반적입니다. 이를 위해 태그의 이름, 클래스, ID 등을 활용하여 특정 요소를 선택할 수 있습니다. 예를 들어, BeautifulSoup을 사용하면 .find() 메서드를 통해 특정 태그를 찾고, .find_all() 메서드를 통해 여러 태그를 찾을 수 있습니다. 이러한 메서드는 태그의 이름, 클래스, ID 등을 기준으로 요소를 선택할 수 있게 해줍니다.

또한, HTML 문서에는 종종 자바스크립트로 동적으로 생성되는 콘텐츠가 포함됩니다. 이러한 경우에는 기본적인 HTML 파싱만으로는 데이터를 추출할 수 없으며, 자바스크립트 실행을 지원하는 도구가 필요합니다. Selenium과 같은 도구는 실제 브라우저를 자동으로 제어하여 동적으로 생성된 콘텐츠를 포함한 모든 요소를 추출할 수 있습니다.

웹 스크래핑을 효과적으로 수행하기 위해서는 HTML 구조를 이해하는 것뿐만 아니라, 다양한 웹 페이지의 특성과 이를 처리하기 위한 도구와 기술을 잘 활용하는 것이 중요합니다. 이를 통해 원하는 데이터를 정확하고 효율적으로 추출할 수 있습니다.

II. 웹 스크래핑 방법

방법 1: BeautifulSoup과 Requests 사용하기

BeautifulSoup과 Requests는 파이썬에서 가장 많이 사용되는 웹 스크래핑 라이브러리입니다. Requests는 웹 페이지를 요청하고 응답을 받는 역할을 하며, BeautifulSoup은 HTML이나 XML 문서를 파싱하여 원하는 데이터를 추출하는 데 사용됩니다.

import requests
from bs4 import BeautifulSoup

url = "https://example.com"
response = requests.get(url)
soup = BeautifulSoup(response.content, "html.parser")

title = soup.find("h1").text
print(title)

방법 2: Scrapy 사용하기

Scrapy는 웹 스크래핑을 위한 강력한 프레임워크로, 대규모 데이터 수집에 최적화되어 있습니다. Scrapy를 사용하면 크롤러를 정의하고, 여러 페이지에서 데이터를 효율적으로 수집할 수 있습니다.

import scrapy

class ExampleSpider(scrapy.Spider):
    name = "example"
    start_urls = ["https://example.com"]

    def parse(self, response):
        title = response.xpath("//h1/text()").get()
        print(title)

방법 3: Selenium

Selenium은 웹 브라우저를 자동화하기 위한 도구로, 웹 애플리케이션을 테스트하거나 동적으로 생성된 웹 페이지의 콘텐츠를 스크래핑하는 데 유용합니다. Selenium은 다양한 웹 브라우저를 제어할 수 있으며, 자바스크립트로 동적으로 생성된 콘텐츠를 포함한 모든 요소를 추출할 수 있습니다. 이를 통해 단순한 HTML 파싱만으로는 접근할 수 없는 데이터도 수집할 수 있습니다.

Selenium 설치 및 설정

Selenium을 사용하려면 먼저 라이브러리를 설치해야 합니다. 다음 명령어를 사용하여 Selenium을 설치할 수 있습니다.

pip install selenium

또한, 사용하려는 웹 브라우저의 드라이버도 설치해야 합니다. 예를 들어, 크롬 브라우저를 사용할 경우 ChromeDriver를 다운로드하여 설치해야 합니다.

기본 사용법

Selenium을 사용하여 웹 페이지를 제어하고 데이터를 추출하는 기본 예제는 다음과 같습니다.

from selenium import webdriver

# Chrome 드라이버 경로를 설정하고 브라우저를 시작합니다.
driver = webdriver.Chrome(executable_path='/path/to/chromedriver')
driver.get("https://example.com")

# 특정 요소를 찾고 텍스트를 추출합니다.
title = driver.find_element_by_tag_name("h1").text
print(title)

# 브라우저를 닫습니다.
driver.quit()

이 예제에서는 Chrome 브라우저를 사용하여 https://example.com 페이지를 열고, <h1> 태그를 찾아 그 텍스트를 출력합니다.

동적 콘텐츠 처리

동적 콘텐츠를 처리할 때는 자바스크립트가 완료될 때까지 기다려야 합니다. Selenium은 WebDriverWaitexpected_conditions 모듈을 사용하여 조건이 충족될 때까지 기다릴 수 있습니다.

from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

driver = webdriver.Chrome(executable_path='/path/to/chromedriver')
driver.get("https://example.com")

# 특정 요소가 로드될 때까지 기다립니다.
element = WebDriverWait(driver, 10).until(
    EC.presence_of_element_located((By.TAG_NAME, "h1"))
)

# 텍스트를 추출합니다.
title = element.text
print(title)

driver.quit()

이 예제에서는 <h1> 태그가 로드될 때까지 최대 10초 동안 기다린 후, 해당 요소의 텍스트를 추출합니다.

양식 제출 및 상호작용

Selenium을 사용하면 웹 페이지의 양식을 자동으로 작성하고 제출할 수도 있습니다.

driver = webdriver.Chrome(executable_path='/path/to/chromedriver')
driver.get("https://example.com/login")

# 사용자 이름과 비밀번호를 입력하고 로그인 버튼을 클릭합니다.
username = driver.find_element_by_name("username")
password = driver.find_element_by_name("password")
login_button = driver.find_element_by_xpath("//input[@type='submit']")

username.send_keys("your_username")
password.send_keys("your_password")
login_button.click()

# 로그인 후 페이지에서 데이터를 추출합니다.
profile_name = driver.find_element_by_id("profile-name").text
print(profile_name)

driver.quit()

이 예제에서는 로그인 페이지에서 사용자 이름과 비밀번호를 입력하고 로그인 버튼을 클릭한 후, 로그인된 페이지에서 프로필 이름을 추출합니다.

Selenium은 이처럼 다양한 상호작용과 동적 콘텐츠 처리가 필요한 경우 매우 유용한 도구입니다. 웹 페이지의 모든 요소를 제어하고 데이터를 추출할 수 있는 강력한 기능을 제공하여, 복잡한 웹 스크래핑 작업을 간단하게 처리할 수 있습니다.

방법 4: Requests와 lxml

Requests와 lxml을 조합하여 웹 스크래핑을 수행하는 방법은 매우 효율적이며 강력합니다. Requests는 HTTP 요청을 쉽게 보낼 수 있는 라이브러리이며, lxml은 HTML과 XML 문서를 빠르고 유연하게 파싱할 수 있는 라이브러리입니다. 이 두 라이브러리를 함께 사용하면 웹 페이지에서 원하는 데이터를 효율적으로 추출할 수 있습니다.

Requests 설치 및 기본 사용법

Requests는 간단하고 직관적인 API를 제공하여 웹 페이지에 대한 HTTP 요청을 쉽게 보낼 수 있습니다. Requests를 설치하려면 다음 명령어를 사용합니다:

pip install requests

기본적인 사용 예시는 다음과 같습니다:

import requests

url = "https://example.com"
response = requests.get(url)

# 응답의 상태 코드 확인
print(response.status_code)

# 페이지 콘텐츠 출력
print(response.text)

lxml 설치 및 기본 사용법

lxml은 HTML과 XML 문서를 파싱하고, XPath를 사용하여 특정 요소를 추출할 수 있는 강력한 라이브러리입니다. lxml을 설치하려면 다음 명령어를 사용합니다:

pip install lxml

기본적인 사용 예시는 다음과 같습니다:

from lxml import html

# HTML 문자열을 파싱
tree = html.fromstring('<html><body><h1>Hello, world!</h1></body></html>')

# XPath를 사용하여 <h1> 태그의 텍스트 추출
title = tree.xpath('//h1/text()')[0]
print(title)

Requests와 lxml을 조합한 웹 스크래핑

Requests와 lxml을 함께 사용하면 웹 페이지에서 데이터를 효율적으로 추출할 수 있습니다. 다음은 Requests와 lxml을 사용하여 웹 페이지에서 특정 데이터를 추출하는 예제입니다:

import requests
from lxml import html

# 웹 페이지 요청
url = "https://example.com"
response = requests.get(url)

# HTML 파싱
tree = html.fromstring(response.content)

# XPath를 사용하여 원하는 데이터 추출
title = tree.xpath('//h1/text()')[0]
print(title)

이 예제에서는 https://example.com 웹 페이지를 요청하고, 응답 내용을 lxml을 사용하여 파싱한 후, XPath를 사용하여 <h1> 태그의 텍스트를 추출합니다.

고급 사용법: 여러 요소 추출

lxml을 사용하면 여러 요소를 한 번에 추출할 수도 있습니다. 예를 들어, 웹 페이지에서 모든 링크와 그 텍스트를 추출하려면 다음과 같이 할 수 있습니다:

import requests
from lxml import html

# 웹 페이지 요청
url = "https://example.com"
response = requests.get(url)

# HTML 파싱
tree = html.fromstring(response.content)

# XPath를 사용하여 모든 링크와 그 텍스트 추출
links = tree.xpath('//a')
for link in links:
    href = link.get('href')
    text = link.text_content()
    print(f"Link: {href}, Text: {text}")

이 예제에서는 모든 <a> 태그를 찾아 각 링크의 URL(href 속성)과 텍스트를 추출합니다.

예외 처리 및 리소스 관리

Requests와 lxml을 사용할 때는 예외 처리를 통해 에러에 대응하고, 리소스를 효율적으로 관리하는 것이 중요합니다. 다음은 예외 처리를 추가한 예제입니다:

import requests
from lxml import html

url = "https://example.com"

try:
    response = requests.get(url)
    response.raise_for_status()  # HTTP 에러가 발생하면 예외 발생
    tree = html.fromstring(response.content)
    title = tree.xpath('//h1/text()')[0]
    print(title)
except requests.exceptions.RequestException as e:
    print(f"HTTP 요청 중 오류 발생: {e}")
except IndexError:
    print("요소를 찾을 수 없습니다.")
except Exception as e:
    print(f"기타 오류 발생: {e}")

이 예제에서는 HTTP 요청 중 발생할 수 있는 다양한 예외를 처리하여 프로그램의 안정성을 높입니다.

Requests와 lxml은 간단한 HTML 파싱부터 복잡한 데이터 추출까지 다양한 작업을 수행할 수 있는 강력한 도구입니다. 이들을 활용하여 효율적이고 안정적인 웹 스크래핑을 구현할 수 있습니다.

방법 5: LangChain을 사용한 웹 스크래핑 개요

LangChain은 다양한 자연어 처리(NLP) 작업을 지원하는 프레임워크로, 대형 언어 모델(LLM)을 활용하여 웹 스크래핑 작업을 더욱 효율적이고 정교하게 수행할 수 있습니다. LangChain을 사용하면 단순한 HTML 파싱을 넘어 복잡한 텍스트 추출 및 데이터 구조화 작업을 자동화할 수 있습니다. 다음은 LangChain을 사용한 웹 스크래핑의 주요 개요입니다.

1. LangChain 설치 및 설정

LangChain을 사용하려면 먼저 필요한 라이브러리들을 설치해야 합니다. 일반적으로 langchain, requests, beautifulsoup4, lxml, 그리고 comet_llm 등의 패키지를 사용합니다. pip 명령어를 통해 설치할 수 있습니다.

pip install langchain requests beautifulsoup4 lxml comet_llm

2. 환경 변수 설정

OpenAI API 키와 Comet API 키를 환경 변수로 설정하여 프로젝트에서 사용할 수 있도록 합니다. .env 파일을 사용하여 환경 변수를 로드할 수 있습니다.

import os
import dotenv

# .env 파일에서 환경 변수를 불러옵니다.
dotenv.load_dotenv()

# 환경 변수에서 OpenAI와 Comet 키를 가져옵니다.
MY_OPENAI_KEY = os.getenv("MY_OPENAI_KEY")
MY_COMET_KEY = os.getenv("MY_COMET_KEY")

3. LangChain 초기화 및 HTML 로딩

LangChain의 다양한 모듈을 사용하여 HTML 콘텐츠를 로드하고 파싱합니다. AsyncChromiumLoader를 사용하여 비동기 방식으로 웹 페이지의 HTML 콘텐츠를 로드할 수 있습니다.

from langchain_openai import ChatOpenAI
from langchain_community.document_loaders import AsyncChromiumLoader

# OpenAI API 키로 ChatOpenAI 인스턴스를 초기화합니다.
llm = ChatOpenAI(openai_api_key=MY_OPENAI_KEY)

# AsyncChromiumLoader를 사용하여 HTML 콘텐츠를 로드합니다.
url = "https://www.imdb.com/list/ls566941243/"
loader = AsyncChromiumLoader([url])
docs = loader.load()

4. HTML 콘텐츠 변환 및 데이터 추출

BeautifulSoupTransformer를 사용하여 필요한 HTML 태그를 추출하고, RecursiveCharacterTextSplitter를 사용하여 문서를 분할합니다. 이러한 과정을 통해 필요한 데이터를 구조화합니다.

from langchain_community.document_transformers import BeautifulSoupTransformer
from langchain.text_splitter import RecursiveCharacterTextSplitter

# BeautifulSoupTransformer를 사용하여 필요한 태그를 추출합니다.
bs_transformer = BeautifulSoupTransformer()
docs_transformed = bs_transformer.transform_documents(
    docs, tags_to_extract=["h3", "p"]
)

# RecursiveCharacterTextSplitter를 사용하여 변환된 문서를 분할합니다.
splitter = RecursiveCharacterTextSplitter.from_tiktoken_encoder(chunk_size=1000, chunk_overlap=0)
splits = splitter.split_documents(docs_transformed)

5. LLM을 통한 데이터 추출 및 검증

LangChain의 create_extraction_chain을 사용하여 정의된 JSON 스키마에 따라 데이터를 추출하고 검증합니다. 이 과정에서 추출된 데이터는 Comet에 로그로 기록됩니다.

from langchain.chains import create_extraction_chain

# JSON 스키마 정의 (영화 데이터 검증용)
schema = {
    "properties": {
        "movie_title": {"type": "string"},
        "stars": {"type": "integer"},
        "genre": {"type": "array", "items": {"type": "string"}},
        "runtime": {"type": "string"},
        "rating": {"type": "string"},
    },
    "required": ["movie_title", "stars", "genre", "runtime", "rating"],
}

def extract_movie_data(content: str, schema: dict):
    """
    JSON 스키마를 사용하여 콘텐츠에서 영화 데이터를 추출합니다.

    매개변수:
    - content (str): 영화 데이터를 포함하는 텍스트 콘텐츠.
    - schema (dict): 영화 데이터를 검증하기 위한 JSON 스키마.

    반환값:
    - dict: 추출된 영화 데이터.
    """
    start_time = time.time()
    extracted_content = create_extraction_chain(schema=schema, llm=llm).run(content)
    end_time = time.time()

    # Comet 프로젝트에 메타데이터와 출력을 기록하여 추적합니다.
    comet_llm.log_prompt(
        prompt=str(content),
        metadata={
            "schema": schema
        },
        output=extracted_content,
        duration=end_time - start_time,
    )

    return extracted_content

# 첫 번째 분할 페이지 콘텐츠를 사용하여 영화 데이터를 추출합니다.
extracted_content = extract_movie_data(schema=schema, content=splits[0].page_content)

# 추출된 영화 데이터를 출력합니다.
print(extracted_content)

결론

LangChain을 사용한 웹 스크래핑은 단순한 HTML 파싱을 넘어서, LLM을 활용하여 복잡한 데이터 추출 및 구조화 작업을 자동화할 수 있는 강력한 방법입니다. 이를 통해 다양한 웹 페이지에서 효율적으로 데이터를 수집하고, 정교하게 처리할 수 있습니다.

방법 5: LangChain을 사용한 웹 스크래핑

LangChain은 다양한 자연어 처리(NLP) 작업을 지원하는 프레임워크로, 대형 언어 모델(LLM)을 활용하여 웹 스크래핑 작업을 더욱 효율적이고 정교하게 수행할 수 있습니다. LangChain을 사용하면 단순한 HTML 파싱을 넘어 복잡한 텍스트 추출 및 데이터 구조화 작업을 자동화할 수 있습니다.

import os
import dotenv
import time

# .env 파일에서 환경 변수를 불러옵니다.
dotenv.load_dotenv()

# 환경 변수에서 OpenAI와 Comet 키를 가져옵니다.
MY_OPENAI_KEY = os.getenv("MY_OPENAI_KEY")
MY_COMET_KEY = os.getenv("MY_COMET_KEY")

# LLM 프로젝트에서, Comet 프로젝트에 출력을 기록합니다.
# 이 데모에서는 단 하나의 URL만 사용합니다. 하지만 여러 URL을 반복 처리해야 하는 경우,
# Comet LLM의 실험 추적 기능이 매우 유용합니다.
import comet_llm

# Comet 프로젝트를 초기화합니다.
comet_llm.init(
    project="langchain-web-scraping",
    api_key=MY_COMET_KEY,
)

# nest_asyncio를 적용하여 비동기 문제를 해결합니다.
import nest_asyncio
nest_asyncio.apply()

# langchain에서 필요한 모듈을 가져옵니다.
from langchain_openai import ChatOpenAI
from langchain_community.document_loaders import AsyncChromiumLoader
from langchain_community.document_transformers import BeautifulSoupTransformer
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.chains import create_extraction_chain

# URL을 정의합니다.
url = "https://www.imdb.com/list/ls566941243/"

# OpenAI API 키로 ChatOpenAI 인스턴스를 초기화합니다.
llm = ChatOpenAI(openai_api_key=MY_OPENAI_KEY)

# AsyncChromiumLoader를 사용하여 HTML 콘텐츠를 로드합니다.
loader = AsyncChromiumLoader([url])
docs = loader.load()

# 참조용으로 HTML 콘텐츠를 텍스트 파일에 저장합니다.
with open("imdb_langchain_html.txt", "w", encoding="utf-8") as file:
    file.write(str(docs[0].page_content))
print("페이지 콘텐츠가 imdb_langchain_html.txt에 저장되었습니다.")

# BeautifulSoupTransformer를 사용하여 로드된 HTML을 변환합니다.
bs_transformer = BeautifulSoupTransformer()
docs_transformed = bs_transformer.transform_documents(
    docs, tags_to_extract=["h3", "p"]
)

# RecursiveCharacterTextSplitter를 사용하여 변환된 문서를 분할합니다.
splitter = RecursiveCharacterTextSplitter.from_tiktoken_encoder(chunk_size=1000, chunk_overlap=0)
splits = splitter.split_documents(docs_transformed)

이미지를 참고하여 필요한 데이터를 추출하기 위해 HTML 레이아웃을 탐색하는 방법을 설명하겠습니다. 이 예제에서는 영화 제목, 장르, 평점, 상영 시간을 추출하기 위해 <h3><p> 태그를 사용할 것입니다.

이미지 설명

이미지에는 영화 “Bullet Train”의 정보가 포함된 IMDb 페이지의 HTML 소스 코드가 나와 있습니다. 주요 요소는 다음과 같습니다:

  • <h3> 태그: 영화 제목이 포함됨
  • <p> 태그: 장르, 평점, 상영 시간 등이 포함됨
import comet_llm

# Comet 프로젝트를 초기화합니다.
comet_llm.init(
    project="langchain-web-scraping",
    api_key=MY_COMET_KEY,
)

# nest_asyncio를 적용하여 비동기 문제를 해결합니다.
import nest_asyncio
nest_asyncio.apply()

# langchain에서 필요한 모듈을 가져옵니다.
from langchain_openai import ChatOpenAI
from langchain_community.document_loaders import AsyncChromiumLoader
from langchain_community.document_transformers import BeautifulSoupTransformer
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.chains import create_extraction_chain

# URL을 정의합니다.
url = "https://www.imdb.com/list/ls566941243/"

# OpenAI API 키로 ChatOpenAI 인스턴스를 초기화합니다.
llm = ChatOpenAI(openai_api_key=MY_OPENAI_KEY)

# AsyncChromiumLoader를 사용하여 HTML 콘텐츠를 로드합니다.
loader = AsyncChromiumLoader([url])
docs = loader.load()

# 참조용으로 HTML 콘텐츠를 텍스트 파일에 저장합니다.
with open("imdb_langchain_html.txt", "w", encoding="utf-8") as file:
    file.write(str(docs[0].page_content))
print("페이지 콘텐츠가 imdb_langchain_html.txt에 저장되었습니다.")

# BeautifulSoupTransformer를 사용하여 로드된 HTML을 변환합니다.
# 필요한 태그를 추출하기 위해 'h3'와 'p' 태그를 사용합니다.
bs_transformer = BeautifulSoupTransformer()
docs_transformed = bs_transformer.transform_documents(
    docs, tags_to_extract=["h3", "p"]
)

# RecursiveCharacterTextSplitter를 사용하여 변환된 문서를 분할합니다.
splitter = RecursiveCharacterTextSplitter.from_tiktoken_encoder(chunk_size=1000, chunk_overlap=0)
splits = splitter.split_documents(docs_transformed)

# JSON 스키마 정의 (영화 데이터 검증용)
schema = {
    "properties": {
        "movie_title": {"type": "string"},
        "stars": {"type": "integer"},
        "genre": {"type": "array", "items": {"type": "string"}},
        "runtime": {"type": "string"},
        "rating": {"type": "string"},
    },
    "required": ["movie_title", "stars", "genre", "runtime", "rating"],
}

def extract_movie_data(content: str, schema: dict):
    """
    JSON 스키마를 사용하여 콘텐츠에서 영화 데이터를 추출합니다.

    매개변수:
    - content (str): 영화 데이터를 포함하는 텍스트 콘텐츠.
    - schema (dict): 영화 데이터를 검증하기 위한 JSON 스키마.

    반환값:
    - dict: 추출된 영화 데이터.
    """
    # 제공된 스키마와 콘텐츠로 추출 체인을 실행합니다.
    start_time = time.time()
    extracted_content = create_extraction_chain(schema=schema, llm=llm).run(content)
    end_time = time.time()

    # Comet 프로젝트에 메타데이터와 출력을 기록하여 추적합니다.
    comet_llm.log_prompt(
        prompt=str(content),
        metadata={
            "schema": schema
        },
        output=extracted_content,
        duration=end_time - start_time,
    )

    return extracted_content

# 첫 번째 분할 페이지 콘텐츠를 사용하여 영화 데이터를 추출합니다.
extracted_content = extract_movie_data(schema=schema, content=splits[0].page_content)

# 추출된 영화 데이터를 출력합니다.
print(extracted_content)

각 코드 라인에 대한 설명

  1. import comet_llm: Comet LLM 라이브러리를 임포트합니다.
  2. comet_llm.init(...): Comet 프로젝트를 초기화합니다.
  3. import nest_asyncio: nest_asyncio를 임포트합니다.
  4. nest_asyncio.apply(): 비동기 문제를 해결하기 위해 적용합니다.
  5. 필요한 langchain 모듈을 임포트합니다.
  6. IMDb URL을 정의합니다.
  7. ChatOpenAI 인스턴스를 OpenAI API 키로 초기화합니다.
  8. AsyncChromiumLoader를 사용하여 HTML 콘텐츠를 로드합니다.
  9. HTML 콘텐츠를 텍스트 파일에 저장합니다.
  10. BeautifulSoupTransformer를 사용하여 필요한 태그(h3p)를 추출합니다.
  11. RecursiveCharacterTextSplitter를 사용하여 변환된 문서를 분할합니다.
  12. 영화 데이터를 검증하기 위한 JSON 스키마를 정의합니다.
  13. extract_movie_data 함수를 정의하여 JSON 스키마를 사용하여 영화 데이터를 추출합니다.
  14. 첫 번째 분할 페이지 콘텐츠에서 extract_movie_data 함수를 사용하여 영화 데이터를 추출합니다.
  15. 추출된 영화 데이터를 출력합니다.

BeautifulSoupTransformer를 사용하여 필요한 태그(h3와 p)를 추출하는 이유는 다음과 같습니다:

  1. 필요한 데이터 필터링: IMDb 페이지에서 영화와 관련된 중요한 정보는 특정 태그 안에 있습니다. 예를 들어, 영화 제목은 <h3> 태그 안에, 영화의 장르, 평점, 상영 시간 등의 정보는 <p> 태그 안에 있습니다. 따라서 이러한 특정 태그를 추출함으로써 필요한 데이터만 필터링할 수 있습니다.
  2. 데이터 정리: 웹 페이지에는 많은 불필요한 데이터와 요소들이 포함되어 있습니다. 이러한 데이터를 모두 파싱하면 처리해야 할 데이터의 양이 많아지고, 원하는 정보를 찾기 어려워질 수 있습니다. 특정 태그만 추출하면 데이터의 양을 줄이고, 필요한 정보만 효율적으로 추출할 수 있습니다.
  3. 데이터 정확성 향상: 특정 태그를 추출하면 데이터의 정확성을 높일 수 있습니다. 예를 들어, 영화 제목이나 평점과 같이 특정 태그에 포함된 정보를 정확하게 추출함으로써 데이터의 일관성을 유지할 수 있습니다.
  4. 후속 처리 용이성: 추출된 특정 태그의 데이터를 후속 처리(예: 텍스트 분할, LLM을 통한 정보 추출 등)하기가 더 쉽습니다. 특정 태그를 추출하면 이러한 태그에 포함된 정보만을 대상으로 작업을 수행할 수 있어 처리 과정이 간단해집니다.

결론

웹 스크래핑은 데이터 수집과 분석에 필수적인 기술입니다. 이 글에서는 5가지 웹 스크래핑 방법에 대해 알아보았습니다. 각 방법의 특징과 장단점을 이해하고, 프로젝트의 요구사항에 맞는 방법을 선택하는 것이 중요합니다. 또한, LangChain과 같은 LLM 기반 도구를 활용하면 더욱 발전된 웹 스크래핑이 가능할 것입니다.

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다