Bing, второй по популярности поисковик в мире и поисковая система по умолчанию на большой доле Windows-компьютеров, поэтому его публичная страница результатов, полезный второй источник мнений наряду с Google. Для исследования ключевых слов, отслеживания позиций SEO, анализа рынка или обучения моделей на реальных поисковых данных SERP Bing содержит именно тот структурированный сигнал, который вам нужен: заголовки, ссылки, сниппеты и порядок их появления.

Это руководство показывает, как надёжно парсить результаты поиска Bing с помощью Python. Вы создадите небольшой, готовый к запуску скрапер, который получает отрисованную страницу результатов через Crawling API, разбирает каждый органический результат с помощью BeautifulSoup, обрабатывает пагинацию и экспортирует данные в JSON и CSV. Всё руководство ограничено публичными данными страницы результатов поиска, доступными любому без учётной записи, а раздел о законности в конце стоит прочитать перед тем, как направить скрапер на реальные объёмы.

Что вы создадите

Скрипт на Python, который принимает публичный URL поиска Bing, получает HTML через Crawling API и извлекает структурированную запись по каждому органическому результату на странице. В качестве рабочего примера мы используем образцовый запрос и извлекаем следующие поля из каждого результата:

  • Position ранг результата на странице, считая сверху.
  • Title кликабельный заголовок результата в том виде, в каком он показан в листинге.
  • Link URL назначения, на который указывает результат.
  • Description отображаемый сниппет или краткое описание под заголовком.

Помимо полей отдельного результата, скрипт обходит несколько страниц результатов и записывает всё в файлы JSON и CSV, чтобы данные сразу можно было загрузить в таблицу или базу данных.

Почему обычный запрос не работает на Bing

Если направить чистый HTTP-запрос на URL результатов Bing из скрипта, вы редко получите чистую страницу, которую видите в своём браузере. Против вас работают два фактора. Во-первых, Bing использует JavaScript для формирования частей страницы результатов, поэтому сырой запрос может вернуться с оболочкой, в которой отсутствуют нужные вам листинги. Во-вторых, Bing следит за автоматизированным трафиком: запросы, не похожие на реальный браузер, проходят проверку, попадают на верификационную страницу или ограничиваются по частоте до того, как добираются до результатов.

Таким образом, работающий скрапер Bing требует двух вещей в одном запросе: IP-адреса, который платформа воспринимает как реального посетителя, и, когда страница опирается на скрипты, браузера для её отрисовки. Можно собрать это самостоятельно с помощью headless-браузера и пула ротируемых резидентных прокси, но поддержка их в рабочем состоянии, основная часть работы. Crawling API объединяет оба компонента в одном вызове: вы отправляете ему URL, он получает данные с доверенного IP и при необходимости выполняет отрисовку, а затем возвращает готовый HTML для разбора.

Почему важны отрисовка и доверенный IP

Bing сочетает серверный и скриптовый рендеринг контента и оценивает каждый запрос на предмет сходства с браузером. Отрисованный запрос с резидентного IP выглядит как обычный посетитель и возвращает полный листинг; сырой запрос с дата-центра часто возвращает усечённую страницу или проверку. Crawling API обрабатывает оба случая на стороне сервера, так что вам не нужно самостоятельно запускать парк браузеров или подбирать пул прокси. Вы можете начать с бесплатного уровня до 20 000 запросов без карты.

Предварительные требования

Прежде чем писать код, необходимо подготовить несколько вещей. Это не займёт много времени.

Базовые знания Python. Вы должны уметь писать и запускать скрипты на Python, а также устанавливать пакеты с помощью pip. Если BeautifulSoup для вас новинка, наше руководство по использованию BeautifulSoup в Python охватывает основы парсинга, которые предполагает этот учебник.

Python 3.8 или выше. Проверьте версию командой python --version. Если Python не установлен, установите его с сайта python.org или через дистрибутив, например Anaconda.

Аккаунт Crawlbase и токен. Зарегистрируйтесь, откройте панель управления и скопируйте токен запроса со страницы документации аккаунта. Вы получаете до 20 000 бесплатных запросов: 1 000 при регистрации и больше по мере прохождения шагов онбординга. Относитесь к токену как к паролю: он аутентифицирует ваши запросы, поэтому не добавляйте его в систему контроля версий.

Настройка проекта

Создайте виртуальное окружение, чтобы зависимости проекта оставались изолированными, затем установите две библиотеки, необходимые скраперу.

bash
python --version

python -m venv bing_env
source bing_env/bin/activate

pip install requests beautifulsoup4

В Windows активируйте окружение командой bing_env\Scripts\activate вместо строки с source. Две зависимости выполняют основную работу: requests отправляет HTTP-вызов к Crawling API, а beautifulsoup4 разбирает возвращаемый HTML, позволяя извлекать отдельные поля по CSS-селектору.

Шаг 1: Получение страницы через Crawling API

Начните с получения HTML. Напишите небольшую функцию crawl(), которая отправляет целевой URL в Crawling API с вашим токеном, запрашивает JavaScript-отрисовку для загрузки полного листинга, проверяет, что исходная страница вернулась со статусом 200, и возвращает HTML-тело. Проверка статуса перед разбором делает сбои явными, а не скрытыми.

python
import json
import requests

API_TOKEN = "YOUR_CRAWLBASE_TOKEN"  # replace with your token
API_ENDPOINT = "https://api.crawlbase.com/"

def crawl(url):
    params = {"token": API_TOKEN, "url": url, "javascript": "true"}
    response = requests.get(API_ENDPOINT, params=params)
    response.raise_for_status()

    data = json.loads(response.text)
    if data["original_status"] != 200:
        raise Exception(f"Unable to crawl '{url}'")

    return data["body"]

if __name__ == "__main__":
    url = "https://www.bing.com/search?q=samsung+s23+ultra"
    html = crawl(url)
    print(html[:500])

API возвращает JSON-конверт, поэтому вы загружаете ответ через json.loads и читаете два поля: original_status, статус, который вернул сам Bing, а body, HTML страницы. Параметр javascript=true указывает API отрисовать страницу в реальном браузере перед её возвратом, что гарантирует наличие полного списка результатов. Проверка original_status означает, что блокировка или проверка выбрасывает исключение вместо передачи мусора в парсер. Образцовый запрос "samsung s23 ultra" передаётся в параметре q, так Bing несёт поисковый запрос. Запустите скрипт командой python crawling.py и вы должны увидеть реальную разметку результатов в первых 500 символах, что подтверждает работоспособность получения данных до написания какого-либо селектора.

Crawlbase Bing Scraper

Проверка original_status читает 200 только потому, что запрос достиг Bing как реальный посетитель с полностью отрисованной страницей. Crawling API получает данные с ротируемого резидентного IP, запускает JavaScript при передаче javascript=true и передаёт вам готовый HTML, так что вам не нужно самостоятельно запускать парк headless-браузеров и подбирать пул резидентных прокси. Сначала направьте его на публичный URL результатов на бесплатном уровне.

Шаг 2: Разбор результатов с помощью BeautifulSoup

Получив HTML, загрузите его в BeautifulSoup и извлеките каждый результат по его селектору. Bing оборачивает каждый органический результат в элемент списка li.b_algo, с заголовком и ссылкой в якоре h2 a и сниппетом в параграфе p.b_algoSlug. Проверьте текущие имена классов в живой странице через инструменты разработчика браузера (правый клик, затем «Просмотр кода»); приведённые ниже селекторы соответствуют макету Bing на момент написания.

python
from bs4 import BeautifulSoup

def scrape_html(html):
    soup = BeautifulSoup(html, "html.parser")

    results = []
    for position, block in enumerate(soup.select("li.b_algo"), start=1):
        link = block.select_one("h2 a")
        snippet = block.select_one("p.b_algoSlug")
        if not link:
            continue
        results.append({
            "position": position,
            "title": link.get_text(strip=True),
            "url": link.get("href"),
            "description": snippet.get_text(strip=True) if snippet else None,
        })

    return results

Селектор li.b_algo, это контейнер, который Bing использует для каждого органического результата, поэтому перебор этих элементов списка даёт именно листинги и пропускает chrome страницы. Чтение текста заголовка и href из одного и того же якоря h2 a сохраняет выравнивание заголовка и ссылки назначения, а p.b_algoSlug содержит описание, показанное под каждым заголовком. enumerate(..., start=1) даёт позицию бесплатно при переборе, так что ранг определяется порядком на странице, а не хрупким атрибутом. Проверка if not link: continue пропускает любой блок без якоря заголовка, что не пускает в вывод рекламу, карусели видео и лишнюю разметку. Сниппет возвращает None, когда у результата нет параграфа с описанием.

Селекторы устаревают

Bing регулярно обновляет фронтенд, и имена классов, такие как b_algo и b_algoSlug, могут измениться при этом. Рассматривайте приведённые выше селекторы как отправную точку, а не контракт. Когда поле возвращается пустым для каждого результата, повторно проверьте живую страницу в инструментах разработчика браузера и обновите селектор. Периодическое обслуживание селекторов, норма для любого продакшн-скрапера, а не признак поломки.

Шаг 3: Сборка

Теперь соедините получение и разбор в один работоспособный скрипт. Получите отрисованную страницу результатов, передайте HTML парсеру, выведите результаты и запишите структурированный вывод в JSON.

python
import json
import requests
from bs4 import BeautifulSoup

API_TOKEN = "YOUR_CRAWLBASE_TOKEN"
API_ENDPOINT = "https://api.crawlbase.com/"

def crawl(url):
    params = {"token": API_TOKEN, "url": url, "javascript": "true"}
    response = requests.get(API_ENDPOINT, params=params)
    response.raise_for_status()
    data = json.loads(response.text)
    if data["original_status"] != 200:
        raise Exception(f"Unable to crawl '{url}'")
    return data["body"]

def scrape_html(html):
    soup = BeautifulSoup(html, "html.parser")
    results = []
    for position, block in enumerate(soup.select("li.b_algo"), start=1):
        link = block.select_one("h2 a")
        snippet = block.select_one("p.b_algoSlug")
        if not link:
            continue
        results.append({
            "position": position,
            "title": link.get_text(strip=True),
            "url": link.get("href"),
            "description": snippet.get_text(strip=True) if snippet else None,
        })
    return results

def main():
    url = "https://www.bing.com/search?q=samsung+s23+ultra"
    html = crawl(url)
    results = scrape_html(html)
    print(json.dumps(results, indent=2, ensure_ascii=False))
    with open("bing_results.json", "w", encoding="utf-8") as f:
        json.dump(results, f, ensure_ascii=False, indent=2)
    print(f"Saved {len(results)} results")

if __name__ == "__main__":
    main()

Запустите полный скрипт командой python main.py. Он получает страницу результатов по запросу "samsung s23 ultra", извлекает запись по каждому органическому листингу, выводит их и записывает всё в bing_results.json. Те же две функции, это всё, что нужно: замените запрос в URL, и парсер справится с тем, что придёт в ответ.

Как выглядит результат

Вы получаете чистый упорядоченный список объектов результатов, каждый с позицией, заголовком, ссылкой и описанием, готовых для записи в JSON, CSV или базу данных.

json
[
  {
    "position": 1,
    "title": "Samsung Galaxy S23 Ultra | Samsung US",
    "url": "https://www.samsung.com/us/smartphones/galaxy-s23-ultra/",
    "description": "Meet the latest Galaxy S23 Ultra phone, equipped with a built-in S Pen, Nightography camera, and a powerful chip for epic gaming."
  },
  {
    "position": 2,
    "title": "Samsung Galaxy S23 Ultra - Full phone specifications",
    "url": "https://www.gsmarena.com/samsung_galaxy_s23_ultra-12024.php",
    "description": "Samsung Galaxy S23 Ultra Android smartphone. Announced Feb 2023. Features 6.8 inch display, Snapdragon 8 Gen 2 chipset, 5000 mAh battery."
  }
]

Масштабирование на несколько страниц и запросов

Один запрос на одной странице, демонстрация; реальная задача охватывает несколько поисков и уходит глубже в результаты. Bing разбивает на страницы с помощью параметра first, который представляет собой индексируемое с единицы смещение с шагом 10: first=11, вторая страница, first=21, третья и так далее. Форма остаётся той же: создайте каждый URL, получите его через Crawling API и разберите той же функцией. Единственная привычка, которая поддерживает длительный запуск в здоровом состоянии, это задание темпа, поэтому делайте паузу между запросами, а не отправляйте их в плотном цикле.

python
import time
from urllib.parse import quote_plus

query = "samsung s23 ultra"
encoded = quote_plus(query)

all_results = []
for page in range(3):
    first = page * 10 + 1
    url = f"https://www.bing.com/search?q={encoded}&first={first}"
    html = crawl(url)
    all_results.extend(scrape_html(html))
    time.sleep(3)

print(f"Collected {len(all_results)} results across 3 pages")

Crawlbase обслуживает до 20 запросов в секунду по умолчанию, это достаточный запас для скрапера, который задаёт темп; при реальной необходимости поддержка может его увеличить. Любой 5XX-ответ от API бесплатен, поэтому повтор заблокированного или недоступного URL ничего не стоит. Если вы предпочитаете маршрутизировать собственный трафик через ротируемый пул, а не использовать управляемый API, Smart AI Proxy (также называемый AI Proxy) предоставляет ту же ротацию резидентных IP как конечную точку-замену.

Экспорт результатов в CSV

JSON удобен для кода, но CSV открывается прямо в таблице, поэтому именно этот формат чаще всего передают между командами. Поскольку каждый результат уже является плоским словарём с одинаковыми ключами, написание CSV занимает несколько строк с использованием стандартной библиотеки.

python
import csv

def save_csv(results, path="bing_results.csv"):
    fields = ["position", "title", "url", "description"]
    with open(path, "w", newline="", encoding="utf-8") as f:
        writer = csv.DictWriter(f, fieldnames=fields)
        writer.writeheader()
        writer.writerows(results)
    print(f"Wrote {len(results)} rows to {path}")

Вызовите save_csv(all_results) после постраничного запуска и вы получите bing_results.csv с одной строкой на органический результат и строкой заголовка сверху. Использование DictWriter с явным списком fieldnames поддерживает стабильный порядок столбцов, а newline="" не позволяет файлу получить пустые строки в Windows.

Как избежать блокировки

Даже при наличии доверенного IP и обработке отрисовки Bing следит за трафиком, характерным для скраперов. Несколько привычек помогают поддерживать запуск в здоровом состоянии.

  • Задавайте темп запросов. Обращение к страницам результатов в плотном цикле, самый быстрый способ пройти проверку. Распределяйте запросы и меняйте запросы вместо постраничного обхода одного термина на полной скорости.
  • Опирайтесь на ротацию. Пул резидентных IP распределяет запросы по многим реальным пользовательским адресам, чтобы ни один не превысил лимит. Crawling API делает это за вас; если вы строите собственную инфраструктуру, именно здесь нужно сосредоточить усилия.
  • Читайте коды статуса. Запуск, начавший возвращать проверки или верификационные страницы, сигнализирует о том, что текущая частота или IP-уровень больше недостаточны. Это сигнал к снижению активности, а не шум, который можно игнорировать.
  • Повторно проверяйте при пустых полях. Bing периодически меняет разметку. Если результаты перестали разбираться, откройте живую страницу в инструментах разработчика и обновите селекторы.

Более широкое руководство доступно в статье о том, как парсить сайты без блокировки. Если нужная вам страница Bing опирается на скрипты для отрисовки, наше руководство по сканированию JavaScript-сайтов объясняет важность отрисовки и способы её включения. Для более широкого обзора структуры страниц крупных поисковиков смотрите материал о том, что возвращают Google, Yahoo и Bing.

Законно ли парсить Bing?

Допустимость парсинга Bing зависит от условий обслуживания Microsoft, вашей юрисдикции и того, что вы делаете с данными. Условия Bing ограничивают автоматизированный доступ, поэтому парсинг может противоречить этим условиям независимо от тщательности вашего инструментария. Ни один из кодов здесь не изменяет этого; он лишь обеспечивает техническую реализацию. Прочитайте условия Bing и его файл robots.txt и считайте оба документа границами того, что вы собираете.

Несколько правил, которых стоит придерживаться. Собирайте только публичные данные результатов поиска: заголовки, ссылки, описания и позиции, которые любой может видеть на странице результатов без учётной записи. Поддерживайте объём запросов достаточно низким, чтобы не нагружать серверы Bing, и задавайте темп сканирования, а не запускайте его на полной скорости. Если вам нужны поисковые данные в масштабе и вы хотите санкционированный путь, Microsoft предлагает Bing Search APIs через Azure, это официальный, поддерживаемый способ программно запрашивать результаты Bing, правильный выбор, когда проект требует объёма или гарантий.

Это руководство намеренно ограничено публичными страницами результатов поиска, поскольку это граница, которая делает работу защитимой. Оно не охватывает ничего за авторизацией, данных аккаунтов или персональной информации, а также защищённых авторским правом материалов, извлечённых из связанных назначений. Только публичные данные SERP. Если ваш проект требует большего, официальное соглашение об использовании данных или Azure Bing Search API, правильный путь, а не более умный скрапер.

Итоги

Ключевые выводы

  • Bing сочетает отрисованный и скриптовый контент. Простой запрос может вернуть усечённую страницу, поэтому вы получаете данные через Crawling API с javascript=true, чтобы получить полный листинг.
  • Crawling API получает данные за реальным IP. Отправьте ему URL, он ротирует резидентные IP на стороне сервера и при необходимости выполняет отрисовку, возвращая готовый HTML для разбора.
  • BeautifulSoup выполняет извлечение. Выбирайте каждый li.b_algo, затем читайте заголовок и ссылку из h2 a и сниппет из p.b_algoSlug, ожидая, что имена классов будут меняться.
  • Пагинация через смещение first. Увеличивайте first на 10 (с единицы) для продвижения глубже в результаты и задавайте темп запросов с паузой между страницами.
  • Оставайтесь в рамках публичных данных. Соблюдайте ToS и robots.txt Bing, поддерживайте низкий объём и используйте официальный Azure Bing Search API для санкционированного масштаба.

Часто задаваемые вопросы

Почему обычный запрос не работает или возвращает неправильную страницу на Bing?

Bing использует JavaScript для формирования частей страницы результатов, поэтому сырой запрос может вернуться с оболочкой без листингов. Кроме того, он помечает трафик, не похожий на реальный браузер, и может ответить проверкой или верификационной страницей. Получение данных через Crawling API с javascript=true, который отрисовывает страницу с ротируемого резидентного IP, делает запрос похожим на обычного посетителя, так что вы получаете реальную страницу результатов.

Можно ли парсить результаты поиска Bing с помощью Python?

Да. С помощью requests и BeautifulSoup можно получить страницу результатов и извлечь заголовки, ссылки, описания и позиции. Crawling API выступает мостом, который доставляет ваш запрос к Bing с доверенного IP и отрисовывает его, чтобы запросы обрабатывались без блокировок. Для более широкого введения в Python смотрите наше руководство по парсингу сайтов с Python.

Какие поля можно извлечь со страницы результатов Bing?

В этом учебнике извлекаются четыре поля из каждого органического результата: позиция на странице, заголовок, ссылка назначения и отображаемое описание. Заголовок и ссылка берутся из якоря h2 a внутри каждого блока li.b_algo, а описание, из p.b_algoSlug. Оставайтесь в рамках публичных данных результатов поиска и избегайте всего, что находится за авторизацией.

Нужна ли JavaScript-отрисовка для парсинга Bing?

Зачастую да, поскольку Bing заполняет части страницы результатов с помощью скриптов. В примерах здесь передаётся javascript=true в Crawling API, чтобы страница отрисовывалась в реальном браузере перед возвратом, что гарантирует наличие полного листинга. Наше руководство по парсингу JavaScript-страниц с Python объясняет, когда отрисовка необходима.

Как перейти по страницам результатов Bing?

Используйте параметр first, который представляет собой индексируемое с единицы смещение с шагом 10: first=11, вторая страница, first=21, третья и так далее. Создайте URL каждой страницы со смещением, получите его через Crawling API, разберите той же функцией и делайте паузу в несколько секунд между запросами, чтобы задавать темп сканирования, а не обрушиваться на него.

Чем парсинг Bing отличается от парсинга Google?

Подход одинаков, различаются только селекторы и параметры пагинации. Bing использует блоки li.b_algo и смещение first, тогда как Google использует собственные контейнеры результатов и смещение start. Если вы также работаете с Google, смотрите наши руководства по парсингу страниц поиска Google и парсингу результатов поиска Yandex для соответствующих селекторов и шагов.

Начать создавать

Обходите любой сайт в масштабе, без борьбы с инфраструктурой.

Crawlbase берёт на себя прокси, отпечатки и CAPTCHA, чтобы ваша команда выпускала конвейеры данных вместо поддержки обвязки краулинга. 1 000 запросов бесплатно, без карты.

Самообслуживание · Звонок отдела продаж не требуется · Доступны корпоративные объёмы краулинга