В начале моей карьеры Data Engineer (это было еще в 2016 году), я занимался скрапингом данных с различных веб-сайтов. Web scraping заключается в использовании автоматизированных инструментов для получения больших объемов данных с веб-сайтов, обычно из их 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.
Когда я начал читать о Large Language Models (LLMs), у меня возник вопрос: “Могу ли я избежать всех тех подводных камней, с которыми я сталкивался, используя LLMs для структурирования данных из веб-страниц?”
Давайте посмотрим, смогу ли я.
Инструменты и методы Web Scraping
В то время основными инструментами, которыми я пользовался, были Requests, BeautifulSoup и Selenium. Каждый из этих сервисов имеет свое назначение и ориентирован на разные типы веб-сред.
- Requests — это Python библиотека, которая может использоваться для легкого создания HTTP-запросов. Эта библиотека выполняет операции GET и POST по указанным URL. Она часто используется для получения HTML-содержимого, которое затем можно анализировать с помощью BeautifulSoup.
- BeautifulSoup — это библиотека Python для парсинга документов HTML и XML, которая строит дерево разбора из исходного кода страницы, позволяя легко получать доступ к различным элементам на странице. Обычно она используется в паре с другими библиотеками, такими как Requests или Selenium, которые предоставляют исходный код HTML.
- Selenium в основном применяется для сайтов, где много JavaScript. В отличие от BeautifulSoup, Selenium не просто анализирует HTML код: он взаимодействует с сайтами, имитируя действия пользователя, такие как нажатия и прокрутка. Это облегчает извлечение данных из сайтов, создающих контент динамически.
Эти инструменты были незаменимы, когда я пытался извлечь данные из веб-сайтов. Однако они также создавали некоторые проблемы: код, теги и структурные элементы должны были регулярно обновляться для адаптации к изменениям в макете сайта, что усложняло долгосрочное обслуживание.
Что такое Большие Языковые Модели (LLMs)?
Большие Языковые Модели (LLMs) — это следующее поколение компьютерных программ, способных учиться, читая и анализируя огромное количество текстовых данных. В наше время они обладают удивительной способностью создавать повествование, подобное человеческому, что делает их эффективными агентами для обработки языка и понимания человеческого языка. Отличительная способность проявилась в таких ситуациях, где контекст текста был действительно важен.
Интеграция LLMs в Веб-скрейпинг
Процесс web scraping можно значительно оптимизировать, интегрировав в него LLMs. Нам нужно взять HTML-код с веб-страницы и ввести его в LLM, который извлечет объекты, на которые он ссылается. Таким образом, этот подход облегчает обслуживание, так как структура разметки может развиваться, но содержимое обычно не меняется.
Вот как будет выглядеть архитектура такой интегрированной системы:
- Получение HTML: Используйте инструменты, такие как Selenium или Requests, для получения HTML-содержимого веб-страницы. Selenium может обрабатывать динамическое содержимое, загруженное с помощью JavaScript, а Requests подходит для статических страниц.
- Парсинг HTML: С помощью BeautifulSoup мы можем распарсить этот HTML как текст, тем самым удаляя шум из HTML (подвал, шапка и т.д.).
- Создание моделей Pydantic: Введите Pydantic модель, которую мы собираемся собирать. Это гарантирует, что данные, введенные и структурированные, соответствуют предварительно определенным схемам.
- Генерация подсказок для LLMs: Создайте подсказку, которая сообщит LLM, какую информацию необходимо извлечь.
- Обработка LLM: Модель читает HTML, понимает его и использует инструкции для обработки и структурирования данных.
- Вывод структурированных данных: LLM предоставит вывод в виде структурированных объектов, которые определяются моделью Pydantic.
Данная рабочая схема помогает преобразовать HTML (неструктурированные данные) в структурированные данные с использованием LLM, решая такие проблемы, как нестандартное проектирование или динамическое изменение исходного HTML веб-страницы.
Интеграция LangChain с BeautifulSoup и Pydantic
Это статическая веб-страница, выбранная для примера. Идея заключается в том, чтобы выкачать все указанные там активности и представить их в структурированном виде.
Данный метод извлекает исходный HTML из статической веб-страницы и очищает его перед обработкой LLM.
from bs4 import BeautifulSoup
import requests
def extract_html_from_url(url):
try:
# Извлечение содержимого HTML по URL с использованием requests
response = requests.get(url)
response.raise_for_status() # Raise an exception for bad responses (4xx and 5xx)
# Разбор содержимого HTML с использованием BeautifulSoup
soup = BeautifulSoup(response.content, "html.parser")
excluded_tagNames = ["footer", "nav"]
# Исключение элементов с именами тегов 'footer' и 'nav'
for tag_name in excluded_tagNames:
for unwanted_tag in soup.find_all(tag_name):
unwanted_tag.extract()
# Обработка супа для сохранения href в тегах атрибутов
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
Следующим шагом является определение объектов Pydantic, которые мы собираемся выкачивать с веб-страницы. Необходимо создать два объекта:
Activity
: Это объект Pydantic, представляющий все метаданные, связанные с активностью, с указанными атрибутами и типами данных. Некоторые поля мы пометили какOptional
на случай, если они не доступны для всех активностей. Предоставление описания, примеров и любых метаданных поможет LLM лучше определить атрибут.ActivityScraper
: Это обертка Pydantic вокругActivity
. Цель этого объекта — убедить LLM в том, что необходимо выполнить сбор нескольких активностей.
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")
Наконец, у нас есть конфигурация LLM. Мы будем использовать библиотеку LangChain, которая предоставляет отличный набор инструментов для начала работы.
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
Последний шаг — вызвать цепочку и получить результаты.
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
Вот как выглядят данные. На выполнение сбора информации со всей веб-страницы уходит 46 секунд.
[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='€')
...
]
Демо и полная репозитория
I have created a quick demo using Streamlit available here.
В первой части вам представляют модель. Вы можете добавлять столько строк, сколько необходимо, и указывать имя, тип и описание каждого атрибута. Это автоматически сгенерирует модель Pydantic для использования в компоненте веб-скрапинга.
Следующая часть позволяет ввести URL и собрать всю данные, нажав кнопку на веб-странице. Появится кнопка загрузки, когда сбор данных будет завершен, позволяя скачать данные в формате JSON.
Не стесняйтесь экспериментировать!
Заключение
LLM открывает новые возможности для эффективного извлечения данных из неструктурированных данных, таких как веб-сайты, PDF и т.д. Автоматизация веб-скрапинга с помощью LLM не только сэкономит время, но и обеспечит качество извлекаемых данных.
Однако отправка необработанного HTML в LLM может увеличить стоимость токенов и сделать процесс неэффективным. Поскольку HTML часто включает различные теги, атрибуты и содержимое, стоимость может быстро расти.
Поэтому крайне важно предварительно обрабатывать и очищать HTML, удаляя все ненужные метаданные и неиспользуемую информацию. Этот подход поможет использовать LLM в качестве экстрактора данных для веб-страниц, сохраняя при этом разумные затраты.
Правильный инструмент для правильной работы!
Source:
https://dzone.com/articles/enhancing-web-scraping-with-large-language-models