Au début de ma carrière en tant que Data Engineer (qui remonte à 2016), j’avais la responsabilité de récupérer des données à partir de différents sites web. Web scraping consiste à utiliser des outils automatisés pour obtenir de grandes quantités de données à partir des sites web, généralement à partir de leur 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.
Une idée qui m’est venue à l’esprit lorsque j’ai commencé à lire sur Large Language Models (LLMs) était : « Puis-je éviter tous ces pièges auxquels j’ai été confronté en utilisant des LLMs pour structurer les données à partir des pages web ? »
Voyons si je le peux.
Outils et techniques de Web Scraping
A l’époque, les principaux outils que j’utilisais étaient Requests, BeautifulSoup, et Selenium. Chaque service a un objectif différent et cible différents types d’environnements web.
- Requests est une bibliothèque Python qui peut être utilisée pour facilement effectuer des requêtes HTTP. Cette bibliothèque réalise des opérations GET et POST contre les URL fournies dans les requêtes. Elle est fréquemment utilisée pour récupérer le contenu HTML qui peut être analysé par BeautifulSoup.
- BeautifulSoup est une bibliothèque Python pour la manipulation d’HTML et XML, elle construit un arbre de parsement à partir du code source de la page qui permet d’accéder facilement aux différents éléments de la page. Habituellement, elle est utilisée conjointement avec d’autres bibliothèques comme Requests ou Selenium qui fournissent le code HTML source.
- Selenium est principalement utilisé pour les sites web qui impliquent beaucoup de JavaScript. Contrairement à BeautifulSoup, Selenium n’analyse pas simplement le HTML : il interagit avec les sites en simulant les actions des utilisateurs comme les clics et les défilements. Cela facilite l’extraction de données à partir de sites qui génèrent du contenu dynamiquement.
Ces outils étaient indispensables lorsque j’essayais d’extraire des données de sites web. Cependant, ils posaient également des défis : le code, les balises et les éléments structuraux devaient être régulièrement mis à jour pour s’adapter aux changements de la mise en page du site, compliquant ainsi la maintenance à long terme.
Qu’est-ce que les Grandes Modèles Linguistiques (LLMs)?
Grandes Modèles Linguistiques (LLMs) sont des programmes informatiques de nouvelle génération capables d’apprendre en lisant et en analysant d’énormes quantités de données textuelles. À notre époque, ils sont dotés de la capacité incroyable de rédiger des narrations similaires à celles des humains, les rendant efficaces pour traiter le langage et comprendre le langage humain. Leur capacité remarquable s’est manifestée dans ce genre de situation, où le contexte du texte était vraiment important.
Intégration des LLMs dans le Web Scraping
Le processus de scraping web peut être optimisé de manière significative en y intégrant des LLMs. Nous devons prendre le code HTML d’une page web et le transmettre au LLM, qui extraira les objets auxquels il se réfère. Par conséquent, cette tactique facilite la maintenance, car la structure de balisage peut évoluer, mais le contenu lui-même ne change généralement pas.
Voici à quoi ressemblerait l’architecture d’un tel système intégré:
- Récupération du HTML: Utiliser des outils comme Selenium ou Requests pour récupérer le contenu HTML d’une page web. Selenium peut gérer le contenu dynamique chargé avec JavaScript, tandis que Requests convient pour les pages statiques.
- Analyse du HTML: En utilisant BeautifulSoup, nous pouvons analyser cet HTML en texte, éliminant ainsi le bruit de l’HTML (pied de page, en-tête, etc.).
- Création de modèles Pydantic: Typons le modèle Pydantic dans lequel nous allons effectuer le scraping. Cela garantit que les données saisies et structurées sont conformes aux schémas prédéfinis.
- Génération de prompts pour les LLMs: Concevoir un prompt qui informera le LLM des informations à extraire.
- Traitement par LLM: Le modèle lit l’HTML, le comprend et utilise les instructions pour le traitement et la structuration des données.
- Sortie de données structurées: Le LLM fournira la sortie sous forme d’objets structurés définis par le modèle Pydantic.
Ce workflow aide à transformer le HTML (données non structurées) en données structurées en utilisant des LLMs, résolvant des problèmes tels que la conception non standard ou la modification dynamique de la source HTML du web.
Intégration de LangChain Avec BeautifulSoup et Pydantic
Ceci est la page Web statique sélectionnée pour l’exemple. L’idée est de récupérer toutes les activités listées et de les présenter de manière structurée.
Cette méthode extraira le HTML brut de la page Web statique et le nettoiera avant que le LLM ne le traite.
from bs4 import BeautifulSoup
import requests
def extract_html_from_url(url):
try:
# Récupérer le contenu HTML depuis l'URL en utilisant requests
response = requests.get(url)
response.raise_for_status() # Raise an exception for bad responses (4xx and 5xx)
# Analyser le contenu HTML en utilisant BeautifulSoup
soup = BeautifulSoup(response.content, "html.parser")
excluded_tagNames = ["footer", "nav"]
# Exclure les éléments avec les noms de tags 'footer' et 'nav'
for tag_name in excluded_tagNames:
for unwanted_tag in soup.find_all(tag_name):
unwanted_tag.extract()
# Traiter la soupe pour maintenir les href dans les tags d'ancre
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
La prochaine étape consiste à définir les objets Pydantic que nous allons récupérer depuis la page Web. Deux objets doivent être créés:
Activity
: Il s’agit d’un objet Pydantic qui représente toutes les métadonnées liées à l’activité, avec ses attributs et types de données spécifiés. Nous avons marqué certains champs commeOptional
au cas où ils ne seraient pas disponibles pour toutes les activités. Fournir une description, des exemples et toute métadonnée aidera le LLM à avoir une meilleure définition de l’attribut.ActivityScraper
: Ceci est l’enveloppe Pydantic autour deActivity
. L’objectif de cet objet est de s’assurer que l’LLM comprend qu’il est nécessaire de récupérer plusieurs activités.
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")
Enfin, nous avons la configuration de l’LLM. Nous utiliserons la bibliothèque LangChain, qui fournit un excellent kit de démarrage.
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.
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
La dernière étape consiste à invoquer la chaîne et à récupérer les résultats.
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
Voici à quoi ressemble les données. Il faut 46 secondes pour récupérer l’ensemble de la page web.
[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='€')
...
]
Démo et Référentiel Complet
I have created a quick demo using Streamlit available here.
Dans la première partie, vous êtes présenté au modèle. Vous pouvez ajouter autant de lignes que nécessaire et spécifier le nom, le type et la description de chaque attribut. Cela génèrera automatiquement un modèle Pydantic à utiliser dans le composant de web scraping.
La partie suivante vous permet d’entrer une URL et de récupérer toutes les données en cliquant sur le bouton de la page web. Un bouton de téléchargement apparaîtra lorsque le scraping sera terminé, vous permettant de télécharger les données au format JSON.
N’hésitez pas à jouer avec !
Conclusion
LLM ouvre de nouvelles possibilités pour extraire efficacement des données de données non structurées telles que les sites web, les PDF, etc. L’automatisation du web scraping par LLM non seulement économisera du temps mais assurera également la qualité des données récupérées.
Cependant, envoyer du HTML brut à l’API LLM pourrait augmenter le coût des jetons et rendre le processus inefficace. Étant donné que le HTML inclut souvent divers balises, attributs et contenu, le coût peut rapidement augmenter.
Par conséquent, il est crucial de prétraiter et de nettoyer le HTML, en supprimant tous les métadonnées inutiles et les informations non utilisées. Cette approche aidera à utiliser l’API LLM comme extracteur de données pour les sites web tout en maintenant un coût décent.
Utilisez le bon outil pour le bon travail!
Source:
https://dzone.com/articles/enhancing-web-scraping-with-large-language-models