Результаты поиска Google, это табло для SEO. Позиция страницы по ключевому слову, какие заголовки и сниппеты получают клик, какие вопросы появляются в блоке «People also ask» и какие связанные запросы предлагает Google: каждый из них является публичным сигналом, который можно прочитать прямо со страницы результатов. Собранные по целевым ключевым словам, они показывают, с кем вы конкурируете, где вы находитесь сегодня и какие темы вы ещё не охватили.
В этом руководстве показано, как извлекать и анализировать SEO-данные из Google с помощью Python. Вы создаёте небольшой работоспособный рабочий процесс, который получает отрисованную SERP через Crawling API, парсит поля, важные для SEO, запускает тот же запрос по списку ключевых слов и загружает результат в pandas для поиска позиций ранжирования, пересечений с конкурентами и пробелов в контенте. Весь процесс ограничен публичными данными из результатов поиска, а раздел о законности в конце не является шаблонным, поэтому прочитайте его перед тем, как направлять скрапер на реальные объёмы.
Что вы создадите
Рабочий процесс на Python, который принимает список целевых ключевых слов, получает HTML каждой SERP через Crawling API и извлекает структурированную запись для каждого органического результата, а также SEO-функции страницы. Из каждого поиска извлекаются следующие поля:
- Position органический рейтинг каждого результата, отсчитываемый от верха страницы.
- Title метазаголовок, отображаемый для каждого результата, который влияет на кликабельность.
- Link URL назначения, из которого также выводится домен для анализа конкурентов.
- Snippet мета-описание, отображаемое Google под каждым результатом.
- People also ask вопросы PAA, прикрепляемые Google к запросу, полезные для идей контента.
- Related searches предложения связанных запросов в нижней части страницы, источник длиннохвостых ключевых слов.
Эти поля охватывают SEO-данные, достойные отслеживания в SERP: органические рейтинги, функции SERP вроде PAA, метазаголовки и описания, а также URL и домены страниц, которые обгоняют вас. Объём поиска и CPC отсутствуют на самой странице, поэтому они по-прежнему берутся из инструмента работы с ключевыми словами, такого как Google Keyword Planner, Ahrefs или SEMrush; этот рабочий процесс даёт вам всё, что содержит страница результатов.
Почему обычный запрос не работает с Google
Если вы отправите обычный HTTP-запрос к URL поиска Google из скрипта, вы редко получите чистую SERP, которую видите в своём браузере. Google использует сильные меры против скрапинга. Запросы, не похожие на настоящий браузер, подвергаются проверке CAPTCHA, перенаправляются на промежуточную страницу «sorry» или ограничиваются после нескольких вызовов. IP-адрес дата-центра, делающий быстрые, одинаковые запросы, является наиболее очевидным признаком, и Google быстро его блокирует.
Кроме того, значительная часть современной SERP собирается с помощью JavaScript. Такие функции, как блок PAA, заполняются после загрузки исходного HTML, поэтому даже запрос, который проходит, может вернуться без именно тех данных, за которыми вы пришли. Рабочий скрапер Google SEO поэтому требует двух вещей в одном запросе: IP-адреса, который платформа воспринимает как настоящего пользователя, и браузера, отрисовывающего страницу. Вы можете создать это самостоятельно с headless-браузером и ротируемыми резидентскими прокси, но поддержание этого стека в рабочем состоянии и составляет основную часть работы. Crawling API объединяет оба в один вызов: вы передаёте ему URL, он получает с надёжного IP и отрисовывает при необходимости, а затем возвращает готовый HTML для парсинга.
Защита Google сильно ориентируется на паттерны запросов и репутацию IP. Один адрес дата-центра, перебирающий ключевые слова, быстро превышает лимит. Crawling API ротирует запросы через множество адресов реальных пользователей на стороне сервера и решает CAPTCHA, которые подбрасывает Google, поэтому вам не нужно самостоятельно добывать и поддерживать этот пул. Вы можете начать с 1000 бесплатных запросов, без кредитной карты.
Предварительные требования
Перед написанием кода вам понадобится несколько вещей. Ни одна из них не займёт много времени.
Базовые знания Python. Вы должны уметь писать и запускать скрипты Python и устанавливать пакеты с помощью pip. Если BeautifulSoup для вас нова, наше руководство по использованию BeautifulSoup в Python охватывает основы парсинга, которые предполагает данный учебник, а наше руководство по анализу данных с pandas охватывает сторону DataFrame.
Python версии 3.8 или новее. Проверьте свою версию командой python --version. Если у вас её нет, установите с python.org или через дистрибутив вроде Anaconda.
Аккаунт и токен Crawlbase. Зарегистрируйтесь, откройте панель управления и скопируйте свой токен запроса со страницы документации аккаунта. Первые 1000 запросов бесплатны, и вы платите только за успешные. Относитесь к токену как к паролю: он аутентифицирует ваши запросы, поэтому не добавляйте его в систему контроля версий.
Настройка проекта
Создайте виртуальное окружение, чтобы зависимости проекта оставались изолированными, а затем установите три библиотеки, необходимые рабочему процессу.
python --version python -m venv seo_env source seo_env/bin/activate pip install requests beautifulsoup4 pandas
В Windows активируйте окружение командой seo_env\Scripts\activate вместо строки с source. Три зависимости выполняют основную работу: requests отправляет HTTP-вызов к Crawling API, beautifulsoup4 парсит возвращаемый HTML для извлечения отдельных полей по CSS-селекторам, а pandas хранит собранные данные в DataFrame для анализа в конце.
Шаг 1: Получение SERP через Crawling API
Начните с получения HTML. Напишите небольшую функцию crawl(), которая отправляет ваш целевой URL поиска Google в Crawling API с вашим токеном, проверяет, что базовая страница вернулась со статусом 200, и возвращает тело HTML. Передайте "javascript": "true", чтобы API отрисовал страницу в настоящем браузере перед её возвратом, что и заполняет загружаемые скриптом функции вроде блока PAA. Проверка статуса перед парсингом делает ошибки явными, а не скрытыми.
import json import requests from urllib.parse import quote_plus API_TOKEN = "YOUR_CRAWLBASE_TOKEN" # replace with your token API_ENDPOINT = "https://api.crawlbase.com/" def search_url(keyword): return f"https://www.google.com/search?q={quote_plus(keyword)}&hl=en&gl=us" 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__": html = crawl(search_url("web scraping api")) print(html[:500])
API возвращает JSON-конверт, поэтому вы загружаете ответ с помощью json.loads и читаете два поля: original_status, это статус, который сам Google вернул, а body, отрисованный HTML страницы. Проверка original_status означает, что страница CAPTCHA или блокировка поднимается как исключение, а не передаётся мусором в парсер. Вспомогательный метод search_url() кодирует ключевое слово в URL и фиксирует язык и регион с помощью hl=en и gl=us, поэтому результаты стабильны от запуска к запуску. Запустите скрипт командой python crawling.py, и вы должны увидеть настоящую разметку SERP в первых 500 символах, что подтверждает работу получения до написания первого селектора.
Проверка original_status всегда читает 200, потому что запрос достиг Google как настоящий пользователь, с уже решённой CAPTCHA. Crawling API получает каждую SERP с ротируемого IP, отрисовывает JavaScript, заполняющий блок PAA и связанные поиски, и передаёт вам готовый HTML, поэтому вы не запускаете флот headless-браузеров и не добываете пул резидентских прокси самостоятельно. Сначала направьте его на публичный URL поиска в бесплатном тарифе.
Шаг 2: Парсинг SEO-полей с BeautifulSoup
Получив HTML, загрузите его в BeautifulSoup и извлеките каждый результат по его селектору. Google оборачивает каждый органический результат в контейнер с заголовком в теге h3, целевым URL в якоре вокруг него и сниппетом в блоке описания рядом. Вопросы PAA и связанные поиски располагаются ниже в собственных блоках. Осмотрите живую SERP в DevTools браузера (правой кнопкой мыши, затем «Просмотр кода»), чтобы подтвердить текущие имена классов; приведённые ниже селекторы соответствуют разметке на момент написания.
from urllib.parse import urlparse from bs4 import BeautifulSoup def scrape_serp(html, keyword): soup = BeautifulSoup(html, "html.parser") results = [] for position, block in enumerate(soup.select("div.g"), start=1): heading = block.select_one("h3") link = block.select_one("a[href]") snippet = block.select_one("div.VwiC3b") if not heading or not link: continue url = link["href"] results.append({ "keyword": keyword, "position": position, "title": heading.get_text(strip=True), "url": url, "domain": urlparse(url).netloc, "snippet": snippet.get_text(strip=True) if snippet else None, }) paa = [ q.get_text(strip=True) for q in soup.select("div.related-question-pair") if q.get_text(strip=True) ] related = [ r.get_text(strip=True) for r in soup.select("div.y6Uyqe div.b2Rnsc, a.k8XOCe") if r.get_text(strip=True) ] return { "keyword": keyword, "results": results, "people_also_ask": paa, "related_searches": related, }
Селектор div.g является обёрткой, которую Google использует для каждого органического результата, с заголовком в теге h3, URL назначения в якоре вокруг него и сниппетом в div.VwiC3b. enumerate(..., start=1) даёт вам ранг бесплатно, поэтому позиция берётся из порядка на странице, а не из хрупкого атрибута. urlparse(url).netloc выводит домен из каждой ссылки, ключевое поле для последующего анализа конкурентов. Охранник if not heading or not link: continue не пускает рекламу и посторонние элементы разметки в ваш вывод. Вопросы PAA приходят из div.related-question-pair, а связанные поиски из блока предложений в нижней части страницы.
Google ротирует имена классов контейнеров результатов, такие как VwiC3b и related-question-pair, при повторном развёртывании фронтенда, иногда одновременно тестируя несколько вариантов разметки. Относитесь к приведённым выше селекторам как к стартовому шаблону, а не как к контракту. Когда поле возвращается пустым для каждого результата, повторно осмотрите живую SERP в DevTools браузера и обновите селектор. Периодическое обслуживание селекторов является нормой для любого рабочего скрапера, а не признаком поломки.
Шаг 3: Запуск по ключевым словам
Теперь объедините получение и парсинг в один работоспособный скрипт, который проходит по списку целевых ключевых слов, собирает структурированные SEO-данные для каждого и записывает всё в JSON. Контроль темпа цикла с коротким ожиданием поддерживает здоровье многоключевого запуска, а не отправляет запросы один за другим.
import json import time import requests from urllib.parse import quote_plus, urlparse from bs4 import BeautifulSoup API_TOKEN = "YOUR_CRAWLBASE_TOKEN" API_ENDPOINT = "https://api.crawlbase.com/" KEYWORDS = [ "web scraping api", "how to scrape google", "rotating proxy service", ] def search_url(keyword): return f"https://www.google.com/search?q={quote_plus(keyword)}&hl=en&gl=us" 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_serp(html, keyword): soup = BeautifulSoup(html, "html.parser") results = [] for position, block in enumerate(soup.select("div.g"), start=1): heading = block.select_one("h3") link = block.select_one("a[href]") snippet = block.select_one("div.VwiC3b") if not heading or not link: continue url = link["href"] results.append({ "keyword": keyword, "position": position, "title": heading.get_text(strip=True), "url": url, "domain": urlparse(url).netloc, "snippet": snippet.get_text(strip=True) if snippet else None, }) paa = [q.get_text(strip=True) for q in soup.select("div.related-question-pair") if q.get_text(strip=True)] related = [r.get_text(strip=True) for r in soup.select("div.y6Uyqe div.b2Rnsc, a.k8XOCe") if r.get_text(strip=True)] return {"keyword": keyword, "results": results, "people_also_ask": paa, "related_searches": related} def main(): serps = [] for keyword in KEYWORDS: html = crawl(search_url(keyword)) serps.append(scrape_serp(html, keyword)) print(f"Scraped '{keyword}': {len(serps[-1]['results'])} results") time.sleep(2) with open("google_seo_data.json", "w", encoding="utf-8") as f: json.dump(serps, f, ensure_ascii=False, indent=2) if __name__ == "__main__": main()
Запустите полный скрипт командой python main.py. Он проходит по трём примерным ключевым словам, получает и отрисовывает каждую SERP, извлекает органические результаты плюс блоки PAA и связанных поисков и записывает всё в google_seo_data.json. Подставьте собственные целевые ключевые слова, и те же две функции обработают всё, что придёт в ответ. Для более подробного описания самого скрапинга, включая пагинацию по страницам результатов, см. наше специализированное руководство по скрапингу результатов поиска Google с Python.
Как выглядит результат
Вы получаете один структурированный объект на ключевое слово: органические результаты в порядке ранжирования с выведенными доменами, плюс вопросы PAA и связанные поиски, которые Google прикрепил к запросу.
{ "keyword": "web scraping api", "results": [ { "keyword": "web scraping api", "position": 1, "title": "Crawling API - Crawlbase", "url": "https://crawlbase.com/crawling-api-avoid-captchas-blocks", "domain": "crawlbase.com", "snippet": "Crawl any website with a single API call and skip blocks and CAPTCHAs." }, { "keyword": "web scraping api", "position": 2, "title": "Best Web Scraping APIs Compared", "url": "https://example-blog.com/web-scraping-apis", "domain": "example-blog.com", "snippet": "A side-by-side look at popular scraping APIs and how they handle blocks." } ], "people_also_ask": [ "What is a web scraping API?", "Is using a scraping API legal?" ], "related_searches": [ "free web scraping api", "web scraping api python" ] }
Это исходный материал для каждого SEO-вопроса, который вы хотите задать: рейтинги в поле position, конкурентный ландшафт в domain, сигналы кликабельности в title и snippet, а идеи для контента в people_also_ask и related_searches.
Анализ SEO-данных с pandas
Скрапинг даёт данные; pandas превращает их в выводы. Загрузите плоский список органических результатов в DataFrame и сможете ответить на три вопроса, которые движут большей частью SEO-работы: где я ранжируюсь, с кем конкурирую и что ещё не охватил. Унаследованный подход чтения CSV и подсчёта топ-доменов по-прежнему работает; здесь мы делаем это прямо из собранных объектов.
import json import pandas as pd with open("google_seo_data.json", encoding="utf-8") as f: serps = json.load(f) # Flatten every organic result across all keywords into one table rows = [r for serp in serps for r in serp["results"]] df = pd.DataFrame(rows) # 1. Where do I rank? Find your own domain's position per keyword MY_DOMAIN = "crawlbase.com" mine = df[df["domain"] == MY_DOMAIN][["keyword", "position", "title"]] print("Your rankings:") print(mine.to_string(index=False)) # 2. Who am I competing with? Domains that appear most across SERPs top_domains = df["domain"].value_counts().head(10) print("\nTop competing domains:") print(top_domains) # 3. Content gaps: PAA and related searches you have not covered yet ideas = [] for serp in serps: for q in serp["people_also_ask"] + serp["related_searches"]: ideas.append({"keyword": serp["keyword"], "idea": q}) gaps = pd.DataFrame(ideas).drop_duplicates() print(f"\n{len(gaps)} content ideas from PAA and related searches") print(gaps.head(10).to_string(index=False)) df.to_csv("google_seo_results.csv", index=False)
Из этого извлекаются три анализа. Первый фильтрует таблицу по вашему собственному домену и выводит вашу позицию по каждому ключевому слову, это отслеживание ранжирования. Второй запускает value_counts() по столбцу domain, чтобы выявить сайты, наиболее часто появляющиеся по вашему набору ключевых слов, конкурентов, доминирующих в вашей нише. Третий объединяет все вопросы PAA и связанные поиски в дедуплицированный список идей для контента: реальные запросы пользователей, на которые вы ещё не ответили. Последняя строка записывает плоские результаты в google_seo_results.csv, чтобы вы могли сравнивать рейтинги еженедельно.
Объём поиска, сложность ключевого слова и CPC не отображаются на SERP, поэтому этот рабочий процесс не выдумывает их. Возьмите их из инструмента работы с ключевыми словами, такого как Google Keyword Planner, Ahrefs или SEMrush, а затем объедините с DataFrame по столбцу keyword, чтобы совместить позицию ранжирования с размером возможности. Подробнее о превращении собранных сигналов в стратегию см. наше руководство по использованию данных для улучшения SEO.
Масштабирование на ключевые слова и конкурентов
Три ключевых слова, это демонстрация; реальная задача отслеживает десятки или сотни, иногда также рекламные результаты. Форма остаётся той же: расширьте список KEYWORDS, получайте каждую SERP через Crawling API и парсите той же функцией. Несколько привычек поддерживают работоспособность более крупного запуска.
-
Соблюдайте темп запросов. Оставляйте
time.sleep()между ключевыми словами и избегайте выполнения сотен поисков в плотном цикле. Распределение работы во времени является наиболее значимым фактором для сохранения незаблокированности. - Дёшево повторяйте заблокированные URL. Любой ответ 5XX от API является бесплатным, поэтому повтор ключевого слова, которое вернулось заблокированным или недоступным, ничего не стоит.
- Повторно осматривайте при пустых полях. Google часто меняет разметку. Если столбец возвращается весь с нулевыми значениями, откройте живую SERP в DevTools и обновите селектор.
- Планируйте повторные запуски. Рейтинги меняются, поэтому запускайте тот же набор ключевых слов еженедельно и сохраняйте каждый запуск с колонкой даты для построения графика позиций во времени.
Если вы также хотите изучить платную сторону SERP, тот же паттерн «получить и парсить» применяется к спонсируемым результатам; наше руководство по анализу Google Ads конкурентов описывает это. Более широкое руководство по борьбе с блокировками см. в статье как скрапить сайты, не попадая в блок.
Законно ли скрапить SEO-данные Google?
Допустимость скрапинга Google зависит от условий использования сервиса, вашей юрисдикции и того, что вы делаете с данными. Условия Google ограничивают автоматизированный доступ к своему поисковому сервису, поэтому скрапинг может противоречить им независимо от того, насколько осторожен ваш инструментарий. Ни один из приведённых здесь кодов не меняет этого; он просто заставляет техническую часть работать. Прочтите условия Google и его robots.txt и рассматривайте оба документа как границу того, что вы собираете.
Несколько правил, которых стоит придерживаться. Собирайте только публичные данные из результатов поиска: рейтинги, заголовки, сниппеты, вопросы PAA и связанные поиски, которые любой может видеть на странице результатов без аккаунта. Поддерживайте объём запросов достаточно низким, чтобы не нагружать серверы Google, и контролируйте темп краулинга, а не запускайте его на полной скорости. Заголовки и сниппеты на странице являются рендерингом Google контента других сайтов, поэтому используйте их как аналитические сигналы, а не как медиа для массового переиздания.
Этот рабочий процесс намеренно ограничен публичными данными SERP, поскольку именно это позволяет сохранить работу защищённой. Он не охватывает ничего за логином, данные аккаунтов или персональные данные, а также защищённые авторским правом медиаматериалы с сайтов-ссылок. Для санкционированного высокообъёмного доступа к данным Google, Google предлагает официальные продукты, такие как Custom Search JSON API и, для данных о рекламе, Google Ads API; это правильный путь, когда проект выходит за рамки анализа публичных SERP. Используйте скрапер для чтения того, что есть на странице, а не для достижения того, что за ней.
Ключевые выводы
- SEO живёт в SERP. Рейтинги, заголовки, сниппеты, вопросы PAA и связанные поиски, всё это публично на странице результатов и вместе отображает вашу позицию, конкурентов и пробелы в контенте.
- Обычный запрос блокируется. Google проверяет IP-адреса дата-центров CAPTCHA и отрисовывает функции в JavaScript, поэтому нужен надёжный IP плюс рендеринг, что Crawling API обрабатывает в одном вызове.
-
BeautifulSoup выполняет извлечение. Выбирайте каждый
div.gдля органических результатов, выводите домен из каждого URL и извлекайте PAA и связанные поиски из собственных блоков; ожидайте дрейфа имён классов. -
pandas превращает данные в выводы. Выравнивайте результаты в DataFrame, фильтруйте по своему домену для отслеживания ранжирования, запускайте
value_counts()по доменам для конкурентов и объединяйте PAA и связанные поиски для идей контента. - Держитесь публичных данных. Соблюдайте ToS и robots.txt Google, поддерживайте низкий объём, берите объём и CPC из инструмента ключевых слов и используйте официальные API Google для санкционированного высокообъёмного доступа.
Часто задаваемые вопросы
Какие SEO-данные можно извлечь из результатов поиска Google?
Вы можете извлечь органические позиции в поиске, метазаголовки, мета-описания (сниппеты), URL результатов с их доменами, вопросы «People also ask» и связанные поиски. Это охватывает отслеживание ранжирования, анализ конкурентов и идеи для контента. Объём поиска и CPC не отображаются на странице, поэтому возьмите их из инструмента ключевых слов, такого как Google Keyword Planner, Ahrefs или SEMrush, и объедините с данными.
Как скрапить результаты поиска Google, не попадая в блок?
Google проверяет автоматизированный трафик CAPTCHA и ограничениями частоты, особенно с IP-адресов дата-центров. Ротируйте IP, контролируйте темп запросов, отрисовывайте JavaScript, чтобы загружаемые скриптом функции появлялись, и позвольте управляемому сервису обрабатывать CAPTCHA. Получение через Crawling API, который ротирует IP и решает CAPTCHA на стороне сервера, делает каждый запрос похожим на запрос обычного пользователя, поэтому вы получаете реальную SERP в ответ.
Какие инструменты нужны для извлечения и анализа SEO-данных Google?
Три библиотеки охватывают это: Crawling API для получения и отрисовки каждой SERP без блокировок, BeautifulSoup для парсинга органических результатов и функций SERP из HTML, и pandas для загрузки всего в DataFrame для анализа ранжирования, конкурентов и пробелов в контенте. Инструмент ключевых слов, такой как Ahrefs или SEMrush, заполняет объём и сложность.
Как найти пробелы в контенте из SERP?
Соберите вопросы «People also ask» и связанные поиски для каждого целевого ключевого слова, объедините их в один дедуплицированный список и сравните с темами, которые ваш сайт уже охватывает. Оставшиеся вопросы, это реальные пользовательские запросы, на которые вы ещё не ответили, что и представляет собой возможности для нового контента и получения featured snippets.
Можно ли отслеживать изменения ранжирования со временем?
Да. Запускайте тот же набор ключевых слов по расписанию, обычно еженедельно, и записывайте каждый запуск в CSV с колонкой даты. Фильтрация объединённой таблицы по вашему собственному домену даёт историю позиций по каждому ключевому слову, которую можно построить в виде графика с pandas или в таблице, чтобы увидеть, приносит ли ваша SEO-работа результаты.
Предоставляет ли Google официальный API для этих данных?
Google предоставляет официальные продукты для части из них, такие как Custom Search JSON API для программного поиска и Google Ads API для данных о рекламе. Они являются санкционированным путём для высокообъёмного или коммерческого использования. Для публичных сигналов SERP, которые охватывает это руководство, скрапинг отрисованной страницы результатов через Crawling API является практическим вариантом, пока вы остаётесь в рамках условий Google и придерживаетесь публичных данных.
Обходите любой сайт в масштабе, без борьбы с инфраструктурой.
Crawlbase берёт на себя прокси, отпечатки и CAPTCHA, чтобы ваша команда выпускала конвейеры данных вместо поддержки обвязки краулинга. 1 000 запросов бесплатно, без карты.
