Оригинал: How I Automated Scraping Using AI
Перевод для канала Мы ж программист
В течение многих лет веб-парсинг казался бесконечной игрой в кошки-мышки. Как только я доводил до совершенства скрипт для извлечения данных с важнейшего сайта, какое-нибудь незначительное изменение в дизайне полностью выводило его из строя. Часы отладки, перенастройка селекторов и постоянный страх быть заблокированным — это был изнурительный цикл. Но потом я открыл для себя возможности ИИ, и вдруг «невозможное» стало легко автоматизируемым.
Это не футуристическая фантазия; это подробное руководство о том, как я перешел от хрупких, зависимых от селекторов скрейперов к надежному извлечению данных на основе ИИ, которое адаптируется к изменениям и понимает контекст. Если вы когда-нибудь боролись с тем, что «div.product-name a.title» внезапно превращалось в «h2.item-heading span.name», эта статья для вас.
Старый мир: нестабильный скрапинг
Прежде чем углубиться в тему революции ИИ, давайте кратко вспомним о слабых местах традиционного скрапинга, ведь их понимание позволяет лучше оценить преимущества ИИ:
➡️ Ненадежные селекторы: полагаться на CSS-селекторы или XPath — все равно что строить карточный домик. Достаточно одного небольшого изменения в HTML-структуре сайта, и все рушится.
➡️ Меры против скрапинга: веб-сайты становятся умнее. CAPTCHA, блокировка IP-адресов, ограничение скорости и сложные системы обнаружения ботов стали стандартом.
➡️ Динамический контент: Многие современные сайты загружают контент динамически с помощью JavaScript. Традиционные библиотеки запросов часто видят только исходный HTML, упуская важные данные.
➡️ Очистка данных: Необработанные данные, полученные скрапингом, редко бывают идеальными. Несоответствия в форматировании, отсутствующие значения и нерелевантный текст часто требуют обширной пост-обработки.
➡️ Кошмар обслуживания: Постоянные усилия по обслуживанию набора скраперов для различных сайтов могут быстро превратиться в работу на полную ставку.
Я сталкивался со всем этим, зачастую одновременно. Мои выходные часто уходили на починку сломанных скребков, и данные, которые я собирал, хотя и были ценными, обходились мне значительными личными затратами. Я понимал, что должен быть лучший способ.
Как ИИ меняет наш образ жизни и работу
Озарение пришло, когда я понял, что то, чем я занимался — ручной поиск закономерностей, выявление взаимосвязей между элементами и интерпретация текста, понятного человеку, — по сути, было когнитивной задачей. А кто сегодня лучше всех справляется с когнитивными задачами? ИИ.
В частности, я начал изучать крупные языковые модели (LLM) и их способность:
- Понимать контекст: вместо того, чтобы просто искать тег с определенным классом, LLM могут «читать» содержание страницы и понимать, что тот или иной блок текста представляет собой описание товара, независимо от его HTML-тега.
- Распознавать сущности: они могут выделять имена, цены, даты, адреса и другие сущности на основе их семантического значения.
- Адаптироваться к изменениям: если название товара перемещается из тега в тег, LLM все равно сможет распознать его как название, поскольку понимает значение текста в данном контексте.
- Генерировать структурированный вывод: они могут принимать неструктурированный текст и преобразовывать его в JSON, CSV или любой другой структурированный формат, который мне нужен.
Речь шла не о создании сложной нейронной сети с нуля, а об использовании предварительно обученных моделей и инженерии подсказок, чтобы дать им инструкции о том, какие данные извлекать.
Мое пошаговое руководство по скрапингу с помощью ИИ
Давайте разберем процесс, который я использую сейчас, с примерами.
Шаг 1️⃣: Выбор инструментов
Для этого не нужно иметь диплом по науке о данных. Вот набор инструментов, которым я пользуюсь:
➡️ Python
Язык, который выбирают за его универсальность и обширную экосистему.
➡️ Selenium или Playwright
Для автоматизации действий в браузере. Эти инструменты необходимы для работы с контентом, отображаемым с помощью JavaScript, и для обхода некоторых механизмов обнаружения ботов. Playwright часто работает быстрее и имеет более удобный API.
➡️ BeautifulSoup4 (необязательно, но полезно)
Для первоначального разбора и очистки HTML перед отправкой в LLM. Иногда нужно просто извлечь основной блок контента.
➡️ API OpenAI (или аналогичный LLM API)
Это мозг нашей операции. Альтернативы включают Claude от Anthropic, Gemini от Google или даже самохостинговые модели, если у вас есть ресурсы. Я в основном использую gpt-4-turbo от OpenAI из-за его надежности и способности следовать инструкциям.
➡️ Requests (необязательно)
Для статических страниц или первоначального извлечения страниц перед передачей в Selenium/Playwright, если необходимо.
Шаг 2️⃣: Получение исходного содержимого веб-страницы
Здесь мы фактически «посещаем» веб-сайт и получаем его полный, отрендеренный HTML-код.
Пример кода (с использованием Playwright):
from playwright.sync_api import sync_playwright
def fetch_page_content(url):
with sync_playwright() as p:
browser = p.chromium.launch(headless=True) # Run in background
page = browser.new_page()
page.goto(url, wait_until="networkidle") # Wait for page to fully load
content = page.content()
browser.close()
return content
# Let's say we want to scrape a product page
# For this example, let's use a hypothetical e-commerce product page structure
# as we cannot scrape live sites for demonstration
# Imagine this content is from a rendered product page
sample_html_content = """
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Awesome Gadget - Super Store</title>
</head>
<body>
<header><h1>Super Gadget Store</h1></header>
<div id="main-content">
<div class="product-detail">
<h1 class="product-title">The Ultimate AI Scraper 5000</h1>
<p class="product-price">$999.99</p>
<div class="product-description">
<p>This revolutionary device automates all your web scraping needs using advanced AI.</p>
<ul>
<li>Effortless data extraction</li>
<li>Adapts to website changes</li>
<li>Supports JSON output</li>
</ul>
<p>Grab yours today!</p>
</div>
<div class="product-specs">
<h2>Specifications</h2>
<ul>
<li>**Model:** AIS5000</li>
<li>**Weight:** 1.2 kg</li>
<li>**Dimensions:** 20x15x5 cm</li>
<li>**Color:** Obsidian Black</li>
</ul>
</div>
<div class="reviews">
<h3>Customer Reviews (4.8/5)</h3>
<div class="review-item">
<span class="reviewer-name">Alice P.</span>
<span class="review-rating">5/5</span>
<p class="review-text">"Amazing product, totally changed my workflow!"</p>
</div>
<div class="review-item">
<span class="reviewer-name">Bob M.</span>
<span class="review-rating">4/5</span>
<p class="review-text">"A bit pricey, but worth every penny."</p>
</div>
</div>
<p class="availability">In Stock: Yes</p>
<p class="shipping-info">Free shipping on all orders over $500.</p>
</div>
</div>
<footer>© 2026 Super Gadget Store</footer>
</body>
</html>
"""
# For a real scenario, you'd call:
# page_content = fetch_page_content("https://example.com/product/ultimate-ai-scraper-5000")
page_content = sample_html_content # Using the sample for demonstration
print("--- Fetched HTML Content (abbreviated) ---")
print(page_content[:500] + "...")Основные моменты этого шага:
- Параметр
headless=trueозначает, что браузер работает в фоновом режиме без видимого окна. - Параметр
wait_until="network"имеет решающее значение. Он указывает Playwright ждать, пока сетевая активность не будет отсутствовать в течение определенного периода времени, что свидетельствует о загрузке большей части динамического контента. - Возможно, вам придется поэкспериментировать с параметрами
wait_until(например, domcontentloaded, load) или добавить явные вызовыpage.wait_for_selector(), если определенные элементы отображаются с задержкой.
Шаг 3️⃣: Предварительная обработка HTML (необязательно, но рекомендуется для повышения эффективности LLM)
Отправка всего необработанного HTML-кода сложной веб-страницы в LLM может быть неэффективной и затратной (с точки зрения использования токенов). Часто его можно предварительно отфильтровать, чтобы отправлять только нужные фрагменты. Для этого отлично подходит BeautifulSoup4.
Допустим, из нашего sample_html_content нас интересуют только основные сведения о продукте, а не верхний и нижний колонтитулы или панель навигации.
Пример кода (с использованием BeautifulSoup4):
from bs4 import BeautifulSoup
def clean_html_for_llm(html_content, relevant_selector="div#main-content"):
soup = BeautifulSoup(html_content, 'html.parser')
# Find the most relevant container
main_content_div = soup.select_one(relevant_selector)
if main_content_div:
# Optionally, remove irrelevant elements within the main content
# For example, remove script and style tags that LLMs don't need
for script_or_style in main_content_div(["script", "style", "nav", "footer"]):
script_or_style.decompose() # Remove it
return str(main_content_div)
else:
return html_content # Fallback if main content not found
cleaned_content = clean_html_for_llm(page_content)
print("\n--- Cleaned HTML for LLM (abbreviated) ---")
print(cleaned_content[:500] + "...")Почему это полезно:
- Сокращение количества токенов: LLM взимают плату за каждый токен. Сокращение объема ненужного HTML-кода позволяет сэкономить средства.
- Повышение эффективности: устраняя лишнюю информацию, вы помогаете LLM сосредоточиться на тех данных, которые вам действительно нужны.
- Ускорение обработки: меньший объем входных данных означает более быстрый ответ от LLM.
Шаг 4️⃣: Составление запроса для ИИ (часть «мозг»)
Это самый важный шаг. Ваш запрос указывает LLM, что нужно делать. Представьте, что вы даете инструкции очень умному стажеру, который умеет читать HTML, но нуждается в четких указаниях.
Ключевые элементы хорошего запроса:
Номер 1:
Понятная цель
— Какие данные вы хотите извлечь?Номер 2:
Формат вывода
— Укажите, в каком формате (например, JSON, CSV) вы хотите получить данные. Обычно JSON лучше всего подходит для структурированного вывода.Номер 3:
Контекст/Роль (не обязательно, но полезно)
— Сообщите LLM, какую она играет роль (например, «Ты — бот, извлекающий данные…»).Номер 4:
Примеры
— Если данные сложные или неоднозначные, предоставьте пример ожидаемого ввода/вывода (хотя для простых извлечений четкого описания обычно достаточно).Номер 5:
Ограничения/Инструкции
— Опишите, что делать с граничными условиями, недостающими данными, а также специфичные правила форматирования.
Пример запроса для извлечения данных о продукте:
product_extraction_prompt = f"""
You are an expert web scraping and data extraction bot. Your task is to extract product information from the provided HTML content.
Return the extracted data in a JSON object.
Extract the following fields:
- `product_name`: The main title of the product.
- `price`: The price of the product, including currency symbol.
- `description`: A concise summary of the product's description. Combine text from paragraphs and list items if relevant.
- `model`: The model number from the specifications. If not found, use "N/A".
- `weight_kg`: The weight in kilograms. Extract only the number. If not found, use null.
- `availability`: "In Stock" or "Out of Stock".
- `customer_reviews_count`: The total number of unique customer reviews found.
- `customer_reviews`: An array of objects, where each object contains:
- `reviewer_name`: The name of the reviewer.
- `rating`: The numerical rating (e.g., "5/5" -> 5).
- `review_text`: The text of the review.
If a piece of information is explicitly not present on the page, set its value to `null` or "N/A" as specified above.
The output MUST be a valid JSON object.
HTML Content to extract from:
---
{cleaned_content}
---
"""Подсказки по разработке запросов:
- Будьте конкретны: «Основной заголовок» лучше, чем «заголовок».
- Укажите типы данных: «числовая оценка» помогает LLM преобразовать «5/5» в 5.
- Обработка отсутствующих данных: четко укажите, что делать, если данные не найдены (null, «N/A»).
- Используйте разделители: три дефиса (-) вокруг HTML-контента помогают LLM отличать инструкции от данных.
Шаг 5️⃣: Отправка в LLM и парсинг вывода
Теперь мы отправляем наш запрос и очищенный HTML-код в API OpenAI (или выбранную вами модель LLM).
Пример кода (с использованием API OpenAI):
from openai import OpenAI
import json
import os
# Ensure your OpenAI API key is set as an environment variable
# For example: export OPENAI_API_KEY='your_api_key_here'
# Or, if you must, hardcode it (not recommended for production)
# client = OpenAI(api_key="sk-your-api-key")
client = OpenAI()
def extract_data_with_llm(prompt):
try:
response = client.chat.completions.create(
model="gpt-4-turbo-preview", # Or "gpt-3.5-turbo" for cheaper, faster results (less accurate sometimes)
messages=[
{"role": "system", "content": "You are a helpful assistant that extracts structured data from text."},
{"role": "user", "content": prompt}
],
response_format={"type": "json_object"} # Crucial for getting JSON back
)
# The LLM's response content is a string
json_string = response.choices[0].message.content
return json.loads(json_string)
except Exception as e:
print(f"Error calling LLM or parsing response: {e}")
return None
extracted_data = extract_data_with_llm(product_extraction_prompt)
print("\n--- Extracted Data (JSON) ---")
if extracted_data:
print(json.dumps(extracted_data, indent=2))
else:
print("Failed to extract data.")Ожидаемый вывод (на основе sample_html_content):
{
"product_name": "The Ultimate AI Scraper 5000",
"price": "$999.99",
"description": "This revolutionary device automates all your web scraping needs using advanced AI. It offers effortless data extraction, adapts to website changes, and supports JSON output. Grab yours today!",
"model": "AIS5000",
"weight_kg": 1.2,
"availability": "In Stock",
"customer_reviews_count": 2,
"customer_reviews": [
{
"reviewer_name": "Alice P.",
"rating": 5,
"review_text": "Amazing product, totally changed my workflow!"
},
{
"reviewer_name": "Bob M.",
"rating": 4,
"review_text": "A bit pricey, but worth every penny."
}
]
}Почему это революционно:
- Надежность: даже если класс product_title изменится, LLM, скорее всего, по-прежнему будет распознавать «The Ultimate AI Scraper 5000» как название продукта, поскольку понимает семантический контекст внутри тега .
- Гибкость: легко добавляйте новые поля для извлечения, просто обновляя запрос, без необходимости переписывать логику разбора.
- Сложные структуры данных: LLM отлично справляются со структурированием сложных данных, таких как вложенные массивы JSON (например, customer_review).
Шаг 6️⃣: Итерации и доработка
Сбор данных с помощью ИИ изначально не является процессом типа «настроил и забыл», но после нескольких итераций он становится очень близок к этому.
Тестирование с вариациями
- Попробуйте собирать данные со страниц, имеющих слегка отличающийся макет или с отсутствующими данными.
Уточнение запросов
- Если LLM что-то упускает, обновите свой запрос, сделав его более конкретным. Например, если он извлекает «$999.99» как «999.99», вы можете добавить «Включить символ валюты» в инструкцию по цене.
Обработка ошибок
- Реализуйте надежную обработку ошибок для сетевых проблем, сбоев API LLM и некорректных ответов JSON.
Дополнительные соглашения и лучшие практики
Этичный скрапинг
- Всегда соблюдайте правила файла robots.txt. Не перегружайте серверы. Идентифицируйте своего бота с помощью
User-Agent. Не собирайте частные или конфиденциальные данные без явного разрешения. Используйте полученные данные ответственно.
Ограничение частоты запросов
- Вводите задержки между запросами (
time.sleep()) во избежание блокировки.
Ротация прокси
- Для сбора данных в больших объемах рассмотрите возможность использования прокси-сервисов для ротации IP-адресов и предотвращения обнаружения.
Работа с CAPTCHA
- Хотя LLM не могут напрямую решать визуальные CAPTCHA, вы можете интегрировать такие сервисы, как 2Captcha или Anti-Captcha, в свой рабочий процесс Playwright/Selenium. Некоторые продвинутые LLM могут описывать изображения, что потенциально может быть использовано для помощи в решении CAPTCHA, но это более сложная настройка.
Управление затратами
Вызовы API LLM требуют затрат.
- Мониторинг токенов: следите за использованием токенов.
- Эффективная предварительная обработка: максимально очищайте HTML-код, чтобы сократить количество токенов.
- Выбор модели:
gpt-3.5-turboзначительно дешевле, чемgpt-4-turbo-preview, и может оказаться достаточной для более простых задач.
Локальные LLM
Для очень больших объемов данных или данных, требующих соблюдения конфиденциальности, можно рассмотреть возможность использования локальных LLM с открытым исходным кодом (таких как Llama 2 через Ollama), но для них требуется мощное оборудование.
Проверка данных
Даже при использовании ИИ всегда проверяйте извлеченные данные. Является ли цена действительным числом? Правильный ли формат даты?
Часто задаваемые вопросы (FAQ)
- Является ли этот метод законным?
- Вопрос законности веб-парсинга сложен и зависит от юрисдикции. Как правило, сбор общедоступной информации является законным, но необходимо соблюдать требования файлов robots.txt и условий предоставления услуг, а также не нарушать законы об авторском праве и о конфиденциальности.
- В конкретных ситуациях всегда обращайтесь за юридической консультацией. Данный метод автоматизирует процесс извлечения данных, но юридические обязательства остаются прежними.
- Всегда ли скрапинг с помощью ИИ лучше традиционного скрапинга?
- «Не всегда». Для очень простых статических веб-сайтов с чрезвычайно однородной структурой традиционный скрипт BeautifulSoup может оказаться быстрее и дешевле.
- Однако для динамического контента, сайтов, которые часто меняются, или сложных структур данных скрапинг с помощью ИИ обеспечивает непревзойденную надежность и удобство обслуживания.
- Что делать, если на сайте используются сложные меры защиты от ботов?
- Этот метод в первую очередь решает проблему анализа страницы, но не обязательно проблему доступа.
Playwright/Seleniumпомогают с рендерингом JavaScript и базовым обнаружением ботов. - В случае очень агрессивных мер защиты от ботов (таких как расширенный фингерпринтинг или постоянные CAPTCHA) вам все же могут понадобиться специализированные прокси-сервисы, сервисы для решения CAPTCHA или даже фермы «безголовых» браузеров. Использование ИИ начинается после успешного извлечения содержимого страницы.
- Сколько стоит использование LLM API для скрапинга?
- Стоимость зависит от поставщика LLM, используемой модели и объема данных. Например, OpenAI взимает плату за токен (входной и выходной).
gpt-4-turbo-previewстоит дороже, чемgpt-3.5-turbo. - При нескольких сотнях страниц в месяц затраты могут быть незначительными (5–20 долларов). При тысячах или миллионах страниц они могут стать существенными (от сотен до тысяч и более долларов), что потребует тщательного управления токенами и оптимизации затрат.
- Можно ли использовать это для сбора данных в режиме реального времени?
- Да, но с некоторыми оговорками. Задержка при вызове API LLM может быть значительной (секунды, а не миллисекунды).
- Для данных, требующих действительно реального времени (например, высокочастотная торговля акциями), это может быть слишком медленно. Для почти реального времени (от минут до часов) это вполне приемлемо.
- Что делать, если LLM допустит ошибку при извлечении?
Это может случиться. LLM не идеальны.
- Уточните запросы: Самым распространенным решением является уточнение запросов и добавление примеров.
- Проверка после обработки: реализуйте собственную логику проверки извлеченных данных (например, проверьте, является ли цена числом, является ли дата действительной).
- Проверка человеком: для критически важных данных все же может потребоваться этап проверки человеком.
- Логика повторной попытки: если ответ LLM представляет собой некорректный JSON, повторите вызов (возможно, с немного измененным запросом).
- Можно ли использовать эту технологию для извлечения данных из PDF-файлов или изображений?
- Да! Именно в этом и заключается преимущество мультимодальных LLM (таких как GPT-4 Vision). Сначала нужно извлечь текст из PDF-файла с помощью библиотеки типа PyPDF2 или Tesseract для изображений (OCR), а затем передать этот текст в LLM с соответствующим запросом.
- GPT-4 Vision может даже напрямую интерпретировать изображения, что открывает возможности для извлечения данных из визуальных элементов, которые трудно получить с помощью традиционного синтаксического анализа HTML.
Наконец-то будущее стало реальностью
Автоматизация сбора данных с помощью ИИ превратила серьезную проблему в элегантное решение. Речь идет не просто о получении данных, а о получении надежных, адаптируемых и структурированных данных, требующих значительно меньших затрат на обслуживание. Хотя освоение техники составления подсказок и интеграция инструментов требуют первоначальных усилий, долгосрочные преимущества в плане эффективности и надежности просто неоценимы.
Если вы все еще мучаетесь с регулярными выражениями и неустойчивыми CSS-селекторами, я настоятельно рекомендую вам воспользоваться «шептуном ИИ». Пришло время навсегда покончить с трудностями скрапинга.
