AI&GameDev

AI와 게임개발에 관련된 이야기

Ollama #7: Crawl4AI로 AI 웹 크롤링의 혁명 – 로컬 LLM으로 더 스마트하게

crawl4ai 로컬llm ai

웹에서 필요한 정보를 효율적으로 수집하는 것은 현대 데이터 분석의 핵심입니다. 크롤링은 이러한 데이터 수집 과정을 자동화하여 웹사이트에서 대량의 정보를 체계적으로 추출하는 기술입니다. 최근 AI 기술의 발전으로 크롤링 분야에도 혁신이 일어나고 있는데, 그 중심에 Crawl4AI가 있습니다. 이 강력한 파이썬 라이브러리는 LLM(대규모 언어 모델)의 능력을 활용하여 웹 크롤링과 데이터 추출 과정을 획기적으로 간소화합니다. 이 글에서는 Crawl4AI의 특징을 살펴보고, Ollama를 이용한 로컬 LLM 활용 방법까지 함께 알아보겠습니다.

Ollama 사용법은 Ollama #1: 비용 걱정 없이 내 컴퓨터에서 제약 없는 LLM 실행하기 부분을, LLM을 활용한 다른 유용한 라이브러리는 Ollama #6: GPT와 로컬LLM으로 PandasAI의 강력한 데이터 분석 기능 테스트 부분을 참고하시기 바랍니다.

Crawl4AI 소개

Crawl4AI는 웹 페이지를 크롤링하고 대규모 언어 모델(LLM) 및 AI 애플리케이션에 유용한 정보를 추출하는 프로세스를 간소화하도록 설계되었습니다. REST API, Python 라이브러리 또는 Google Colab 노트북을 통해 사용할 수 있으며, Crawl4AI는 웹 데이터 추출을 더 쉽고 효율적으로 만드는 강력한 기능을 제공합니다.

다음과 같이 URL만 입력하면 간단하게 웹페이지의 내용을 크롤링할 수 있습니다:

from crawl4ai import WebCrawler

crawler = WebCrawler(verbose=True)
crawler.warmup()
result = crawler.run(url="https://www.nbcnews.com/business")

result는 CrawlResult라는 형식으로 되어 있으며, 다음과 같은 다양한 정보를 포함합니다:

  • url: 크롤링된 URL
  • success: 크롤링과 추출 성공 여부
  • html: 웹 페이지의 원시 HTML 콘텐츠
  • cleaned_html: 정리된 HTML 콘텐츠
  • media: 추출된 미디어 요소 목록
  • links: 추출한 내부 및 외부 링크 목록
  • screenshot: 웹 페이지의 base64 인코딩된 스크린샷
  • markdown: 마크다운 형식으로 변환된 웹 페이지 내용
  • extracted_content: 지정된 추출 전략에 따라 추출된 콘텐츠
  • metadata: 웹 페이지에서 추출한 메타데이터
  • error_message: 크롤링 중 발생한 오류

Crawl4AI 설치

Crawl4AI 라이브러리를 설치하려면 다음 명령어를 사용하세요:

pip install "crawl4ai[all] @ git+https://github.com/unclecode/crawl4ai.git"

설치 중 오류가 발생하면 pip 버전을 22.1.2로 다운그레이드해야 할 수 있습니다:

!python -m pip install pip==22.1.2

Crawl4AI의 기본 크롤링 기능

주의: Crawl4AI는 기본적으로 크롤링 시 Google Chrome을 사용하므로 Chrome 설치가 필요합니다.

웹페이지의 내용을 markdown 형식으로 확인하는 예제:

from crawl4ai import WebCrawler

crawler = WebCrawler()
crawler.warmup()
result = crawler.run(url="https://www.nbcnews.com/business")

print(result.markdown)

html, cleaned_html, extracted_content 등 다른 형식의 내용도 동일한 방법으로 확인할 수 있습니다.

웹페이지를 Screenshot으로 저장

Crawl4AI를 사용하여 웹페이지의 스크린샷을 저장할 수 있습니다:

import base64

result = crawler.run(url="https://www.nbcnews.com/business", screenshot=True)
with open("screenshot.png", "wb") as f:
    f.write(base64.b64decode(result.screenshot))

print(f"Screenshot saved to screenshot.png")

이 코드를 실행하면 프로젝트 폴더에 ‘screenshot.png’라는 파일명으로 스크린샷이 저장됩니다.

LLM 전략을 활용한 고급 기능

원하는 정보 추출

GPT-4를 사용하여 OpenAI의 API 요금을 정리하는 예제:

import os
from crawl4ai import WebCrawler
from crawl4ai.extraction_strategy import LLMExtractionStrategy
from pydantic import BaseModel, Field

class OpenAIModelFee(BaseModel):
    model_name: str = Field(..., description="Name of the OpenAI model.")
    input_fee: str = Field(..., description="Fee for input token for the OpenAI model.")
    output_fee: str = Field(..., description="Fee for output token ßfor the OpenAI model.")

url = 'https://openai.com/api/pricing/'
crawler = WebCrawler()
crawler.warmup()

result = crawler.run(
        url=url,
        word_count_threshold=1,
        extraction_strategy= LLMExtractionStrategy(
            provider= "openai/gpt-4o", 
            api_token = os.getenv('OPENAI_API_KEY'), 
            schema=OpenAIModelFee.model_json_schema(),
            extraction_type="schema",
            instruction="""From the crawled content, extract all mentioned model names along with their fees for input and output tokens. 
            Do not miss any models in the entire content. One extracted model JSON format should look like this: 
            {"model_name": "GPT-4", "input_fee": "US$10.00 / 1M tokens", "output_fee": "US$30.00 / 1M tokens"}."""
        ),            
        bypass_cache=True,
    )

print(result.extracted_content)

결과는 JSON 형식으로 출력됩니다:

[
    {
        "model_name": "gpt-3.5-turbo-1106",
        "input_fee": "US$0.001 / 1K tokens",
        "output_fee": "US$0.002 / 1K tokens",
        "error": false
    },
    {
        "model_name": "gpt-4-2024-04-09",
        "input_fee": "US$0.001 / 1K tokens",
        "output_fee": "US$0.002 / 1K tokens",
        "error": false
    },
    .
    .
    .
]

웹사이트 요약 기능

GPT-4 모델을 사용하여 웹사이트 내용을 요약하는 기능 구현:

import os
import json
from crawl4ai import WebCrawler
from pydantic import BaseModel, Field
from crawl4ai.extraction_strategy import LLMExtractionStrategy

def get_crawler():
    crawler = WebCrawler(verbose=True)
    crawler.warmup()
    return crawler

class PageSummary(BaseModel):
    title: str = Field(..., description="Title of the page.")
    summary: str = Field(..., description="Summary of the page.")
    brief_summary: str = Field(..., description="Brief summary of the page.")
    keywords: list = Field(..., description="Keywords assigned to the page.")

def summary_extraction(url, model_name='openai/gpt-4o'):
    result = get_crawler().run(
        url=url,
        word_count_threshold=1,
        extraction_strategy=LLMExtractionStrategy(
            provider= model_name, 
            api_token = os.getenv('OPENAI_API_KEY'), 
            schema=PageSummary.model_json_schema(),
            extraction_type="schema",
            apply_chunking=False,
            instruction=(
                "From the crawled content, extract the following details: "
                "1. Title of the page "
                "2. Summary of the page, which is a detailed summary "
                "3. Brief summary of the page, which is a paragraph text "
                "4. Keywords assigned to the page, which is a list of keywords. "
                'The extracted JSON format should look like this: '
                '{ "title": "Page Title", "summary": "Detailed summary of the page.", '
                '"brief_summary": "Brief summary in a paragraph.", "keywords": ["keyword1", "keyword2", "keyword3"] }'
            )
        ),
        bypass_cache=True,
    )
    result = result.extracted_content.encode('utf-8', errors='ignore').decode("unicode_escape")
    result_json = json.loads(result)
    return result_json

def print_result_json(result_json):
    print(f"\ntitle: {result_json[0]['title']}")
    print('---------------------------------------------')
    print(f"summary: {result_json[0]['summary']}")
    print(f"brief_summary: {result_json[0]['brief_summary']}")
    print(f"keywords: {result_json[0]['keywords']}")

url = 'https://ollama.com/blog/gemma2'
print_result_json(summary_extraction(url))

요약 결과:

title: Google Gemma 2
---------------------------------------------
summary: Google Gemma 2, released on June 27, 2024, is available in two sizes, 9B and 27B, featuring a brand new architecture designed for class-leading performance and efficiency. The model requires Ollama 0.1.47 or later. The 27 billion parameter version of Gemma 2 delivers performance surpassing models more than twice its size in benchmarks, setting a new standard in the open model landscape. The initial release includes two sizes: 9B and 27B parameters. The model can be run using the command 'ollama run gemma2' for the 9B version and 'ollama run gemma2:27b' for the 27B version. Additionally, Gemma 2 can be integrated with popular tooling such as LangChain and LlamaIndex.
brief_summary: Google Gemma 2, available in 9B and 27B sizes, features a new architecture for top performance and efficiency. It requires Ollama 0.1.47 or later and surpasses larger models in benchmarks. The model can be run using specific commands and integrated with tools like LangChain and LlamaIndex.
keywords: ['Google Gemma 2', 'Ollama', '9B parameters', '27B parameters', 'LangChain', 'LlamaIndex', 'performance', 'efficiency']

Ollama의 qwen2 모델을 사용한 간단한 페이지 요약:

url = 'https://marketplace.visualstudio.com/items?itemName=Unclecode.groqopilot'
print_result_json(summary_extraction(url, 'ollama/qwen2'))

요약 결과:

title: Groqopilot
---------------------------------------------
summary: Groqopilot is a Visual Studio Code extension that integrates Llama3 and Groq, a high-speed inference engine, into your coding environment.
brief_summary: Groqopilot VSCode Extension provides features like chat interface, code generation, session management, and auto-completion. It allows users to interact with the active editor by selecting code, asking questions, and receiving context-based responses that can be inserted or replaced in the selected text or cursor location.
keywords: ['Visual Studio Code', 'extension', 'Llama3', 'Groq', 'code generation', 'session management', 'auto-completion']

특정 내용 추출 및 요약

웹페이지에서 특정 키워드(예: ‘gpt’)와 관련된 내용만 추출한 후 요약하는 기능:

import os
from crawl4ai.extraction_strategy import LLMExtractionStrategy
from crawl4ai import WebCrawler

def get_crawler():
    crawler = WebCrawler(verbose=True)
    crawler.warmup()
    return crawler

url = 'https://www.artificialintelligence-news.com/'

result = get_crawler().run(
    url = url,
    extraction_strategy=LLMExtractionStrategy(
        provider= 'openai/gpt-4o',
        api_token=os.getenv('OPENAI_API_KEY'),
        instruction='Extract only GPT-related news and summarise the key points.',
    ),
    bypass_cache=True,
)

print(result.extracted_content)

결과:

[
    {
        "index": 0,
        "tags": [
            "news"
        ],
        "content": [
            "Tech war escalates: OpenAI shuts door on China",
            "This week, OpenAI has decisively blocked access to its site from mainland China and Hong Kong, cutting off developers and companies from some of the most advanced AI technologies available today."
        ],
        "error": false
    },
    {
        "index": 0,
        "tags": [
            "news"
        ],
        "content": [
            "OpenAI disrupts five covert influence operations",
            "In the last three months, OpenAI has disrupted five covert influence operations (IO) that attempted to exploit the company's models for deceptive activities online. As of May 2024, these campaigns have not shown a substantial increase in audience engagement or reach due to OpenAI's..."
        ],
        "error": false
    },
    {
        "index": 0,
        "tags": [
            "GPT-related news"
        ],
        "content": [
            "Apple is reportedly getting free ChatGPT access ![\\\\\\\"\\\\\\\"](\\\\\\\"https://www.artificialintelligence-news.com/wp-content/uploads/sites/9/2024/06/openai-chatgpt-partnership-apple-intelligence-ai-artificial-350x236.jpg\\\\\\\") unsuccessfully) for a vast range of different things. Let\u2019s face it: we\u2019ve got stars in our eyes when it comes to AI right now - but what\u2019s it doing to one of the vast industries on our... 14 June 2024 | Applications"
        ],
        "error": false
    },
    .
    .
    .

REST API 사용

Crawl4AI.com에서 제공하는 API를 통해 크롤링을 수행할 수 있습니다:

import requests

data = {
    "urls": ['https://www.nbcnews.com/business'],
    "extraction_strategy": "CosineStrategy",
    "extraction_strategy_args": {
        "semantic_filter": 'Presidential elections',
    },
}

response = requests.post("https://crawl4ai.com/crawl", json=data)
response_data = response.json()

print(response_data['results'][0]['extracted_content'])

주의: 테스트 시 결과가 정상적으로 출력되지 않는 문제가 있었습니다.

고급 크롤링 기능

JavaScript 실행 및 CSS 필터링

  1. JavaScript 실행 (‘Load More’ 버튼 클릭)
  2. CSS 선택기로 데이터 필터링 (css_selector에서 ‘p’ 필터링)
  3. cosine similarity 전략을 사용한 콘텐츠 추출 (‘technology’와 유사한 결과값 추출)
# Import necessary modules
from crawl4ai import WebCrawler
from crawl4ai.chunking_strategy import *
from crawl4ai.extraction_strategy import *
from crawl4ai.crawler_strategy import *

# Define the JavaScript code to click the "Load More" button
js_code = ["""
const loadMoreButton = Array.from(document.querySelectorAll('button')).find(button => button.textContent.includes('Load More'));
loadMoreButton && loadMoreButton.click();
"""]

crawler = WebCrawler(verbose=True)
crawler.warmup()
# Run the crawler with keyword filtering and CSS selector
result = crawler.run(
    url="https://www.nbcnews.com/business",
    js=js_code,
    css_selector="p",
    extraction_strategy=CosineStrategy(
        semantic_filter="technology",
    ),
)

# Display the extracted result
print(result)

Hooks & Auth

크롤링 프로세스의 특정 지점에서 호출되는 함수를 구현할 수 있습니다:

def on_driver_created(driver):
    print("[HOOK] on_driver_created")
    # Example customization: maximize the window
    driver.maximize_window()

    # Example customization: logging in to a hypothetical website
    driver.get('https://example.com/login')

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

    WebDriverWait(driver, 10).until(
        EC.presence_of_element_located((By.NAME, 'username'))
    )
    driver.find_element(By.NAME, 'username').send_keys('testuser')
    driver.find_element(By.NAME, 'password').send_keys('password123')
    driver.find_element(By.NAME, 'login').click()
    WebDriverWait(driver, 10).until(
        EC.presence_of_element_located((By.ID, 'welcome'))
    )
    # Add a custom cookie
    driver.add_cookie({'name': 'test_cookie', 'value': 'cookie_value'})
    return driver        
.
.
.

이러한 함수를 필요한 타이밍에 실행되도록 추가할 수 있습니다:

crawler = WebCrawler(verbose=True)
crawler.warmup()
crawler.set_hook('on_driver_created', on_driver_created)
.
.
.

정리

Crawl4AI는 AI 기반 웹 크롤링의 새로운 지평을 여는 혁신적인 도구입니다. LLM과 AI 기술을 활용하여 웹 데이터 수집 및 분석을 더욱 효율적으로 만들어줍니다.

현재의 한계점

  • 설치 과정의 불안정성
  • 일부 기능의 불완전한 동작
  • Ollama를 통한 로컬 LLM 사용 시 복잡한 페이지 처리의 한계

활용 가능한 영역

  • 간단한 크롤링 작업과 특정 데이터 추출
  • 기본적인 웹 콘텐츠 분석 및 요약

Crawl4AI와 로컬 LLM의 효과적인 조합

  • 로컬 LLM을 이용한 간단한 데이터 후처리 (예: 추출된 데이터의 간단한 번역 또는 요약)
  • 대규모 처리가 필요하지 않은 소규모 프로젝트에서의 활용

향후 전망

  • 지속적인 개발로 인한 높은 발전 가능성
  • 특정 용도에 따른 가치 있는 도구로서의 잠재력
  • LLM과의 통합 개선을 통한 기능 확장 기대

Crawl4AI는 아직 완벽하지 않지만, AI 기반 웹 크롤링의 미래를 보여주는 중요한 이정표입니다. 현재의 한계점들이 개선된다면, 웹 데이터 수집 및 분석 분야에 혁명적인 변화를 가져올 수 있을 것입니다. 특히 로컬 LLM과의 효과적인 조합을 통해, 소규모 프로젝트나 특정 용도에 맞춘 크롤링 작업에서 큰 잠재력을 보여줍니다. 앞으로의 발전이 더욱 기대되는 라이브러리임이 틀림없습니다.

Ollama #7: Crawl4AI로 AI 웹 크롤링의 혁명 – 로컬 LLM으로 더 스마트하게

답글 남기기

Scroll to top