Веб-скрейпинг с ChatGPT незаметно изменил способ написания большей части кода извлечения данных. Старый подход был хрупким: осмотреть страницу, написать вручную CSS-селекторы и переписывать их каждый раз, когда сайт обновлял разметку. Новый подход опирается на модель. Вы получаете чистую копию страницы, передаёте её модели OpenAI и запрашиваете нужные поля в виде структурированного JSON. Селекторы живут в вашем промпте, а не в коде, и переживают изменения макета, которые сломали бы жёстко заданный парсер.
Есть одна честная оговорка, которую маркетинг обычно обходит стороной: ChatGPT не может загрузить страницу за вас. У него нет надёжного браузера, он блокируется как любой другой клиент, и запрос живого URL нередко возвращает уверенную галлюцинацию вместо реальных данных. Поэтому данное руководство чётко разделяет задачи. Crawlbase выполняет загрузку и рендеринг за надёжным IP, модель OpenAI выполняет понимание, а Python скрепляет их вместе. Всё описанное ниже готово к запуску, ограничено публичными страницами и рассчитано на работу со страницами, слишком большими для передачи в модель за один раз.
Как на самом деле работает веб-скрейпинг с ChatGPT
Полезно точно разобраться, какой инструмент что делает, потому что именно путаница между ними является источником ошибок в большинстве туториалов. Языковая модель является слоем рассуждений, а не сетевой клиент. Дайте ей чистый текст, и она отлично справится с извлечением структурированных полей из беспорядочного контента. Попросите её самостоятельно получить этот контент, и она потерпит неудачу: нет движка рендеринга, нет пула прокси, нет обработки CAPTCHA, и есть сильная склонность изобретать правдоподобно выглядящие значения, когда она не может загрузить страницу.
Поэтому рабочий конвейер состоит из трёх этапов. Сначала загрузить и отрендерить цель с помощью Crawling API, который запускает страницу в настоящем браузере за ротирующими резидентными IP и возвращает готовый HTML. Затем свести этот HTML к компактному виду: либо к очищенному тексту, либо к markdown, чтобы не платить за отправку навигационных и скриптовых тегов модели. Наконец, дать промпт модели OpenAI прочитать этот контент и вернуть JSON, соответствующий определённой вами схеме. Модель никогда не касается сети; она читает только то, что вы ей передаёте.
Держите эти обязанности разделёнными. Crawlbase загружает страницу, рендерит JavaScript и обходит блокировки. Модель OpenAI ничего не загружает: она только читает переданный вами HTML или markdown и возвращает структурированные данные. Если вы напрямую просите ChatGPT загрузить живой URL, он не может сделать это надёжно и может придумать ответ.
Что нужно перед началом
Это сборка уровня начинающий-средний. Вам нужны Python 3.9 или новее, аккаунт Crawlbase для обычного и JavaScript-токена, а также ключ OpenAI API. Бесплатный уровень Crawlbase покрывает более чем достаточно запросов для прохождения руководства, а вызовы моделей здесь используют небольшую и недорогую модель. Задайте оба секрета как переменные окружения вместо того, чтобы вставлять их непосредственно в скрипт.
python --version mkdir chatgpt-scraper && cd chatgpt-scraper pip install crawlbase openai beautifulsoup4 html2text export CRAWLBASE_TOKEN="your_normal_token" export CRAWLBASE_JS_TOKEN="your_javascript_token" export OPENAI_API_KEY="your_openai_key"
Четыре библиотеки выполняют всю работу. crawlbase, клиент для Crawling API, openai, официальный SDK для вызовов модели, beautifulsoup4 сводит отрендеренную страницу к читаемому тексту, а html2text преобразует HTML в markdown, когда вы хотите, чтобы модель видела структуру, такую как заголовки и таблицы. Не всегда нужны обе: BeautifulSoup и html2text, выбирайте то представление, которое подходит для конкретной страницы.
Шаг 1: загрузка отрендеренной страницы с помощью Crawling API
Начните с получения чистой копии страницы. Используйте JavaScript-токен для любого сайта, который рендерит контент на стороне клиента, что характерно для большинства современных страниц, и передайте ajax_wait плюс page_wait, чтобы контент, загружаемый с задержкой, успел появиться до возврата HTML. Пример ниже указывает на публичную страницу товара; замените её на любой публичный URL, с которым вы работаете.
import os from crawlbase import CrawlingAPI api = CrawlingAPI({"token": os.environ["CRAWLBASE_JS_TOKEN"]}) target_url = "https://www.example.com/products/widget" def fetch_html(url): response = api.get(url, {"ajax_wait": "true", "page_wait": 4000}) if response["status_code"] != 200: raise RuntimeError(f"Fetch failed: {response['status_code']}") return response["body"].decode("utf-8", "ignore") if __name__ == "__main__": html = fetch_html(target_url) print(len(html), "bytes of rendered HTML")
Запустите код, и вы должны увидеть значительное количество байт и, при выводе фрагмента, реальный контент, а не пустую оболочку. Это тот шаг, который ChatGPT не может выполнить самостоятельно: Crawling API отрендерил JavaScript и направил запрос через надёжный IP, чтобы страница вернулась целой. Имея чистый HTML на руках, модель может вступить в работу.
Шаг 2: сведение страницы к чистому тексту или markdown
Сырой HTML в основном является шумом для языковой модели: скрипты, стили, SVG-пути и теги отслеживания, которые расходуют токены и разбавляют сигнал. Сначала очистите их. Для простого извлечения полей достаточно текста BeautifulSoup. Когда страница имеет значимую структуру, например таблицу спецификаций или вложенный список, конвертируйте в markdown, чтобы модель видела иерархию.
from bs4 import BeautifulSoup import html2text def to_text(html): soup = BeautifulSoup(html, "html.parser") for tag in soup(["script", "style", "noscript", "svg"]): tag.decompose() return soup.get_text(separator=" ", strip=True) def to_markdown(html): converter = html2text.HTML2Text() converter.ignore_links = True converter.ignore_images = True return converter.handle(html)
Этот один шаг нередко сокращает количество токенов на порядок, что означает более дешёвое, быстрое и точное извлечение, потому что модель не пробирается сквозь разметку. Если вы предпочитаете пропустить этот шаг, Crawlbase может возвращать чистый LLM-ready markdown непосредственно при загрузке, поэтому страница приходит в форме, удобной для модели, без локального шага конвертации.
Шаг 3: промпт модели OpenAI для извлечения структурированного JSON
Теперь собственно веб-скрейпинг с ChatGPT. Отправьте очищенный контент модели OpenAI с промптом, который называет каждое нужное поле и принуждает вывод к JSON. Самая важная настройка, запрос ответа в виде JSON-объекта, чтобы получить разбираемые данные, а не прозу. Низкая температура удерживает модель от творческой интерпретации значений, которые должны быть скопированы дословно.
import json from openai import OpenAI client = OpenAI() SYSTEM = ( "You extract structured data from web page content. " "Return only valid JSON. Copy values verbatim from the text. " "If a field is not present, use null. Never invent data." ) def extract(content, fields): prompt = ( f"Extract these fields as JSON: {', '.join(fields)}.\n\n" f"Page content:\n{content}" ) response = client.chat.completions.create( model="gpt-4o-mini", temperature=0, response_format={"type": "json_object"}, messages=[ {"role": "system", "content": SYSTEM}, {"role": "user", "content": prompt}, ], ) return json.loads(response.choices[0].message.content)
Соедините три этапа вместе, и у вас получится полноценный скрейпер, который никогда не хардкодит ни одного селектора.
if __name__ == "__main__": html = fetch_html(target_url) text = to_text(html) data = extract(text, ["product_name", "price", "rating", "in_stock"]) print(json.dumps(data, indent=2))
Результат структурирован и готов к сохранению.
{ "product_name": "Acme Widget Pro", "price": "$49.99", "rating": "4.6", "in_stock": true }
Модель может извлекать данные только со страницы, которую она реально видит. Crawling API рендерит JavaScript в настоящем браузере, ротирует через резидентные IP на стороне сервера и возвращает готовый HTML или LLM-ready markdown в одном вызове, чтобы ChatGPT получил чистый контент вместо заблокированной оболочки. Начните с бесплатного уровня и направьте его на публичную страницу.
Проектирование промптов для надёжного извлечения
Промпт теперь является местом, где живёт ваша логика скрейпинга, поэтому имеет смысл писать его обдуманно. Несколько паттернов определяют разницу между ненадёжным выводом и данными, которым можно доверять.
Задавайте явную схему, а не расплывчатый запрос
«Получи важную информацию» даёт модели пространство для догадок. Называйте каждое поле, его тип и что делать, если оно отсутствует. Передача JSON-скелета в промпте ещё надёжнее, потому что модель заполняет видимую форму, а не ту, которую ей нужно угадать.
schema = { "product_name": "string", "price": "string, include currency symbol", "rating": "number or null", "specs": "object of key-value pairs", } prompt = ( f"Fill this schema from the page content. " f"Use null for anything absent.\n\n" f"Schema:\n{json.dumps(schema, indent=2)}\n\n" f"Content:\n{content}" )
Фиксируйте форматы и запрещайте изобретение данных
Укажите точно, как должно выглядеть каждое значение: сохраняйте символ валюты в ценах, нормализуйте даты до формата YYYY-MM-DD, возвращайте рейтинги как числа. Не менее важно сказать модели никогда не угадывать. Инструкция «используй null для отсутствующих полей, никогда не изобретай данные» в системном промпте : это то, что останавливает галлюцинированные значения, то есть главный риск при извлечении на основе модели.
Снижайте температуру и валидируйте вывод
Задайте temperature=0, чтобы одна и та же страница давала одинаковый JSON. Затем валидируйте то, что возвращается: убедитесь, что это разбирается, проверьте наличие обязательных ключей и типов. Модель возвращает текст, поэтому относитесь к её выводу как к недоверенному вводу, пока ваш код не проверит его, точно так же, как вы поступали бы с любым внешним источником.
Работа с большими страницами, превышающими контекстное окно
Описанный паттерн работает, пока страница не слишком велика для одного вызова модели. Длинные категориальные листинги, отзывы с сотнями записей и плотная документация могут выйти за пределы контекстного окна или просто стать слишком дорогими на запрос. Решение, разбить контент на чанки, извлекать из каждого и объединять результаты.
def chunk_text(text, size=12000, overlap=500): chunks = [] start = 0 while start < len(text): end = start + size chunks.append(text[start:end]) start = end - overlap return chunks def extract_large(text, fields): results = [] for chunk in chunk_text(text): part = extract(chunk, fields) if part: results.append(part) return results
Несколько правил делают разбивку на чанки надёжной. Перекрывайте чанки на несколько сотен символов, чтобы запись, находящаяся на границе, не оказалась разрезанной пополам. По возможности разбивайте на естественных границах, таких как абзацы или пункты списков, а не на середине слова. Для страниц-листингов запрашивайте в каждом чанке массив элементов и конкатенируйте массивы, затем дедуплицируйте по стабильному ключу, например по ID товара или URL, поскольку перекрытие создаёт несколько дубликатов. Этот паттерн совпадает с тем, что используют производственные системы, а более широкая механика описана в статье как работает извлечение данных с помощью ИИ.
Когда страница сопротивляется
Всё описанное выше предполагает, что загрузка проходит успешно. На хорошо защищённых сайтах так будет не всегда, по крайней мере не надолго. Crawling API обрабатывает рендеринг и ротацию IP в уже написанном вами вызове, что устраняет большинство блокировок. При более высоких объёмах или атаке на особенно агрессивные цели маршрутизируйте через Smart AI Proxy, который адаптирует стратегию под каждую цель, чтобы поддерживать высокий процент успеха, или обращайтесь к Crawling API, когда для сайта уже есть готовый парсер и вам нужны чистые поля без вызова LLM.
Главное, сохранять разделение ответственности: Crawlbase отвечает за преодоление защиты и доставку реальной страницы, а модель OpenAI отвечает за её чтение. Путаница между ними, когда вы просите ChatGPT загрузить URL, и приводит к заблокированным запросам и галлюцинированным ответам. Держите их раздельно, и каждый будет делать ту часть, в которой хорош. Если хотите сравнить семейства моделей для части извлечения, наше руководство по использованию Gemini AI для веб-скрейпинга следует той же схеме «загрузка, извлечение».
Ключевые выводы
- Разделите задачу на две части. Crawlbase загружает и рендерит страницу; модель OpenAI извлекает данные из чистого контента. Модель никогда не касается сети.
- Сокращайте перед промптингом. Сводите HTML к тексту или markdown, чтобы тратить токены на контент, а не на теги скриптов, и получать более дешёвое и точное извлечение.
-
Сделайте промпт своей схемой. Называйте каждое поле и тип, принуждайте к JSON-выводу, задавайте
temperature=0и говорите модели использовать null вместо изобретения значений. - Разбивайте большие страницы на чанки. Разбивайте с перекрытием, извлекайте из каждого чанка, затем объединяйте и дедуплицируйте по стабильному ключу, когда контент превышает контекстное окно.
- Валидируйте вывод. Модель возвращает текст; убедитесь, что он разбирается и содержит ожидаемые ключи и типы перед сохранением.
- Оставайтесь на публичных данных. Соблюдайте условия использования каждого сайта и robots.txt; никаких аккаунтов, персональных данных, никаких действий за логином.
Часто задаваемые вопросы
Может ли ChatGPT скрейпить сайт напрямую?
Нет. У ChatGPT нет надёжного способа загрузить живую страницу: он блокируется как любой другой клиент и нередко придумывает ответ, когда не может загрузить URL. То, что он делает хорошо,, читает переданный ему контент и возвращает структурированные данные. Поэтому вы загружаете страницу с помощью такого инструмента, как Crawling API, а затем передаёте чистый HTML или markdown модели для извлечения.
Почему стоит использовать Crawlbase вместо Python requests?
Потому что обычный запрос возвращает пустую оболочку на JavaScript-тяжёлых сайтах и блокируется на защищённых. Crawling API рендерит страницу в настоящем браузере и маршрутизирует через ротирующие резидентные IP, поэтому контент, который видит модель, : это тот же контент, что видит человек. Без этого шага модель извлекает данные из пустого листа или страницы обнаружения ботов.
Какую модель OpenAI использовать для извлечения?
Небольшая быстрая модель, такая как gpt-4o-mini, хорошо справляется с большинством задач извлечения полей и сохраняет низкие затраты в масштабе. Обращайтесь к более крупной модели только тогда, когда страница требует реального рассуждения: например, для вывода полей, которые подразумеваются, а не указаны явно, или для согласования конфликтующих значений. Начинайте с малого, измеряйте точность на ваших страницах и увеличивайте размер только если небольшая модель не справляется.
Как предотвратить галлюцинации значений моделью?
Три вещи вместе. Задавайте temperature=0 для детерминированного вывода, инструктируйте модель в системном промпте использовать null для отсутствующих полей и никогда не изобретать данные, и валидируйте возвращённый JSON в коде. Просьба копировать значения дословно из текста, а не пересказывать их, также сокращает придуманные ответы.
Как работать со страницей, слишком большой для одного запроса?
Разбейте очищенный контент на перекрывающиеся чанки, извлекайте из каждого чанка отдельно и объединяйте результаты. Для страниц-листингов возвращайте массив для каждого чанка и дедуплицируйте по стабильному ключу, такому как ID товара, поскольку перекрытие создаёт несколько дубликатов. Предварительное сведение HTML к тексту также уменьшает страницу настолько, что многие «слишком большие» страницы помещаются в один вызов.
Является ли веб-скрейпинг с ChatGPT законным?
Это зависит от условий использования целевого сайта, вашей юрисдикции и того, что вы делаете с данными. Строго ограничивайтесь публичным контентом, соблюдайте robots.txt и ожидания по скорости запросов и никогда не трогайте аккаунты, персональные данные или что-либо за логином. Для коммерческого переиспользования получайте разрешение или официальное соглашение о данных, а не полагайтесь на скрейпер.
Обходите любой сайт в масштабе, без борьбы с инфраструктурой.
Crawlbase берёт на себя прокси, отпечатки и CAPTCHA, чтобы ваша команда выпускала конвейеры данных вместо поддержки обвязки краулинга. 1 000 запросов бесплатно, без карты.
