Migliorare la Cattura Web con Grandi Modelli di Lingua: Un Approccio Moderno

Durante i miei primi giorni come Data Engineer (risalenti al 2016), avevo la responsabilità di estrarre dati da diversi siti web. Web scraping consiste nell’utilizzo di strumenti automatizzati per ottenere grandi quantità di dati dai siti web, solitamente dal loro HTML.

I remember building around the application, digging into the HTML code, and trying to figure out the best solutions for scraping all the data. One of my main challenges was dealing with frequent changes to the websites: for example, the Amazon pages I was scraping changed every one to two weeks.

Un pensiero che mi è venuto in mente quando ho iniziato a leggere su Large Language Models (LLMs) è stato: “Posso evitare tutti quei problemi che ho incontrato utilizzando LLMs per strutturare dati da pagine web?”

Vediamo se posso.

Strumenti e Tecniche di Web Scraping

Al tempo, gli strumenti principali che stavo utilizzando erano Requests, BeautifulSoup, e Selenium. Ogni servizio ha uno scopo diverso e è rivolto a diversi tipi di ambienti web.

  • Requests è una libreria Python che può essere utilizzata per facilmente effettuare richieste HTTP. Questa libreria esegue operazioni GET e POST contro gli URL forniti nelle richieste. È spesso usata per recuperare contenuto HTML che può essere analizzato da BeautifulSoup.
  • BeautifulSoup è una libreria Python per la parsing di documenti HTML e XML, che costruisce un albero di parsing dal codice sorgente della pagina che consente di accedere facilmente ai vari elementi della pagina. Di solito, viene abbinato ad altre librerie come Requests o Selenium che forniscono il codice HTML sorgente.
  • Selenium viene principalmente utilizzato per siti web che hanno una quantità significativa di JavaScript coinvolto. A differenza di BeautifulSoup, Selenium non analizza semplicemente il codice HTML: interagisce con i siti web simulando azioni utente come clic e scorrimento. Ciò facilita l’estrazione dei dati da siti web che creano contenuti in modo dinamico.

Questi strumenti erano indispensabili quando cercavo di estrarre dati da siti web. Tuttavia, hanno anche posto alcune sfide: il codice, le etichette e gli elementi strutturali dovevano essere aggiornati regolarmente per adattarsi ai cambiamenti nella disposizione del sito web, complicando la manutenzione a lungo termine.

Cosa sono i Large Language Models (LLM)?

I Large Language Models (LLM) sono programmi di computer di prossima generazione che possono imparare leggendo e analizzando grandi quantità di dati di testo. In questa epoca, sono dotati della straordinaria capacità di scrivere in modo narrativo simile all’uomo rendendoli agenti efficienti nel processare il linguaggio e comprendere il linguaggio umano. La capacità eccezionale si è manifestata in quel tipo di situazione, dove il contesto del testo era davvero importante.

Integrazione di LLM nello scraping web

Il processo di web scraping può essere ottimizzato in misura notevole quando si implementano modelli linguistici gerarchici (LLM) al suo interno. Dobbiamo prendere il codice HTML di una pagina web e inserirlo nell’LLM, il quale estrarrà gli oggetti a cui si riferisce. Pertanto, questa tattica facilita la manutenzione, poiché la struttura di markup può evolversi, ma il contenuto stesso di solito non cambia.

Ecco come apparirebbe l’architettura di un sistema integrato di questo tipo:

  1. Ottenere HTML: Utilizzare strumenti come Selenium o Requests per recuperare il contenuto HTML di una pagina web. Selenium può gestire contenuti dinamici caricati con JavaScript, mentre Requests è adatto per pagine statiche.
  2. Analisi dell’HTML: Utilizzando BeautifulSoup, possiamo analizzare questo HTML come testo, rimuovendo così il rumore dall’HTML (piè di pagina, intestazione, ecc.).
  3. Creazione di modelli Pydantic: Digitare il modello Pydantic in cui eseguiremo lo scraping. Ciò garantisce che i dati digitati e strutturati rispettino gli schemi predefiniti.
  4. Generazione di prompt per LLM: Progettare un prompt che informi l’LLM quale informazione deve essere estratta.
  5. Elaborazione da parte dell’LLM: Il modello legge l’HTML, lo comprende e applica le istruzioni per il trattamento e la strutturazione dei dati.
  6. Uscita di dati strutturati: L’LLM fornirà l’output sotto forma di oggetti strutturati definiti dal modello Pydantic.

Questo flusso di lavoro aiuta a trasformare l’HTML (dati non strutturati) in dati strutturati utilizzando LLM, risolvendo problemi come progettazione non standard o modifica dinamica del codice sorgente HTML del web.

Integrazione di LangChain con BeautifulSoup e Pydantic

Questa è la pagina web statica selezionata per l’esempio. L’idea è quella di estrarre tutte le attività elencate lì e presentarle in modo strutturato.

Questo metodo estrarrà l’HTML grezzo dalla pagina web statica e lo pulirà prima che l’LLM lo elabori.

Python

 

from bs4 import BeautifulSoup
import requests


def extract_html_from_url(url):
    try:
        # Recupera il contenuto HTML dall'URL utilizzando requests
        response = requests.get(url)
        response.raise_for_status()  # Raise an exception for bad responses (4xx and 5xx)

        # Analizza il contenuto HTML utilizzando BeautifulSoup
        soup = BeautifulSoup(response.content, "html.parser")
        excluded_tagNames = ["footer", "nav"]
        # Escludi elementi con nomi di tag 'footer' e 'nav'
        for tag_name in excluded_tagNames:
            for unwanted_tag in soup.find_all(tag_name):
                unwanted_tag.extract()

        # Processa la zuppa per mantenere href negli elementi di collegamento
        for a_tag in soup.find_all("a"):
            href = a_tag.get("href")
            if href:
                a_tag.string = f"{a_tag.get_text()} ({href})"

        return ' '.join(soup.stripped_strings)  # Return text content with preserved hrefs

    except requests.exceptions.RequestException as e:
        print(f"Error fetching data from {url}: {e}")
        return None

Il passo successivo è definire gli oggetti Pydantic che estrarremo dalla pagina web. Due oggetti devono essere creati:

  • Attività: Questo è un oggetto Pydantic che rappresenta tutta la metadati relativa all’attività, con i suoi attributi e tipi di dati specificati. Abbiamo contrassegnato alcuni campi come Opzionale nel caso in cui non siano disponibili per tutte le attività. Fornire una descrizione, esempi e qualsiasi metadato aiuterà l’LLM ad avere una definizione migliore dell’attributo.
  • ActivityScraper: Questo è il wrapper Pydantic intorno a Activity. L’obiettivo di questo oggetto è assicurare che l’LLM comprenda che è necessario strappare diverse attività.
Python

 

from pydantic import BaseModel, Field
from typing import Optional

class Activity(BaseModel):
    title: str = Field(description="The title of the activity.")
    rating: float = Field(description="The average user rating out of 10.")
    reviews_count: int = Field(description="The total number of reviews received.")
    travelers_count: Optional[int] = Field(description="The number of travelers who have participated.")
    cancellation_policy: Optional[str] = Field(description="The cancellation policy for the activity.")
    description: str = Field(description="A detailed description of what the activity entails.")
    duration: str = Field(description="The duration of the activity, usually given in hours or days.")
    language: Optional[str] = Field(description="The primary language in which the activity is conducted.")
    category: str = Field(description="The category of the activity, such as 'Boat Trip', 'City Tours', etc.")
    price: float = Field(description="The price of the activity.")
    currency: str = Field(description="The currency in which the price is denominated, such as USD, EUR, GBP, etc.")

    
class ActivityScrapper(BaseModel):
    Activities: list[Activity] = Field("List of all the activities listed in the text")

Infine, abbiamo la configurazione dell’LLM. Utilizzeremo la libreria LangChain, che fornisce un eccellente toolkit per iniziare.

A key component here is the PydanticOutputParser. Essentially, this will translate our object into instructions, as illustrated in the Prompt, and also parse the output of the LLM to retrieve the corresponding list of objects.

Python

 

from langchain.prompts import PromptTemplate
from langchain.output_parsers import PydanticOutputParser
from langchain_openai import ChatOpenAI
from dotenv import load_dotenv

load_dotenv()

llm = ChatOpenAI(temperature=0)
output_parser = PydanticOutputParser(pydantic_object = ActivityScrapper)

prompt_template = """
You are an expert making web scrapping and analyzing HTML raw code.
If there is no explicit information don't make any assumption.
Extract all objects that matched the instructions from the following html
{html_text}
Provide them in a list, also if there is a next page link remember to add it to the object.
Please, follow carefulling the following instructions
{format_instructions}
"""

prompt = PromptTemplate(
    template=prompt_template,
    input_variables=["html_text"],
    partial_variables={"format_instructions": output_parser.get_format_instructions}
)

chain = prompt | llm | output_parser

Il passo finale è richiamare la catena e recuperare i risultati.

Python

 

url = "https://www.civitatis.com/es/budapest/"
html_text_parsed = extract_html_from_url(url)
activites = chain.invoke(input={
    "html_text": html_text_parsed
})
activites.Activities

Ecco come appaiono i dati. Ci vogliono 46 secondi per strappare l’intera pagina web.

Python

 

[Activity(title='Paseo en barco al anochecer', rating=8.4, reviews_count=9439, travelers_count=118389, cancellation_policy='Cancelación gratuita', description='En este crucero disfrutaréis de las mejores vistas de Budapest cuando se viste de gala, al anochecer. El barco es panorámico y tiene partes descubiertas.', duration='1 hora', language='Español', category='Paseos en barco', price=21.0, currency='€'),
 Activity(title='Visita guiada por el Parlamento de Budapest', rating=8.8, reviews_count=2647, travelers_count=34872, cancellation_policy='Cancelación gratuita', description='El Parlamento de Budapest es uno de los edificios más bonitos de la capital húngara. Comprobadlo vosotros mismos en este tour en español que incluye la entrada.', duration='2 horas', language='Español', category='Visitas guiadas y free tours', price=27.0, currency='€')
 ...
]

Demo e Full Repository

I have created a quick demo using Streamlit available here.

Nella prima parte, ti viene presentato il modello. Puoi aggiungere tutte le righe necessarie e specificare il nome, il tipo e la descrizione di ogni attributo. Questo genererà automaticamente un modello Pydantic da utilizzare nel componente di scraping web.

La parte successiva ti permette di inserire un URL e strappare tutti i dati cliccando il pulsante sulla pagina web. Un pulsante di download apparirà quando lo scraping sarà terminato, permettendoti di scaricare i dati in formato JSON.

Sentiti libero di giocarci!

Conclusione

LLM offre nuove possibilità per estrarre dati in modo efficiente da dati non strutturati come siti web, PDF, ecc. L’automatizzazione dello scraping web da parte di LLM non solo risparmierà tempo, ma garantirà anche la qualità dei dati recuperati.

Tuttavia, inviare HTML grezzo al LLM potrebbe aumentare il costo dei token e renderlo inefficiente. Poiché l’HTML spesso include vari tag, attributi e contenuti, il costo può rapidamente aumentare. 

Pertanto, è cruciale preprocessare e pulire l’HTML, rimuovendo tutti i metadati inutili e le informazioni non utilizzate. Questo approccio aiuterà a utilizzare il LLM come estrae dati per siti web mantenendo un costo decente.

Il giusto strumento per il lavoro giusto!

Source:
https://dzone.com/articles/enhancing-web-scraping-with-large-language-models