Парсинг People Also Ask и автодополнения Google — один из самых недооценённых способов собрать реальные поисковые запросы пользователей бесплатно. В отличие от платных инструментов вроде Ahrefs или SEMrush, Google сам предоставляет три источника данных, которые отражают фактический поиск: автодополнение (Autocomplete), блок People Also Ask (PAA) и связанные запросы (Related Searches). В этом руководстве мы разберём, как извлекать эти данные на Python с помощью residential-прокси, чтобы получать чистые локализованные результаты без блокировок.
Парсинг People Also Ask и автодополнения Google: три источника ключевых слов
Google предлагает три публичных источника поисковых подсказок, каждый из которых отражает разный аспект интента пользователя:
| Источник | URL / расположение | Тип интента | Объём данных |
|---|---|---|---|
| Autocomplete (Suggest) | suggestqueries.google.com/complete/search?client=chrome&q=… | Все типы — навигационный, информационный, транзакционный | 10 подсказок на запрос |
| People Also Ask | SERP, блок div[role='treeitem'] | Информационный, вопросный | 4–8 вопросов на SERP, рекурсивно |
| Related Searches | Низ SERP, блок связанных запросов | Смешанный, контекстный | 8–10 запросов |
Автодополнение Google возвращает JSON-ответ с подсказками, основанными на реальном поисковом объёме. Это означает, что каждая подсказка — это запрос, который пользователи реально вводят. Технология автодополнения работает на основе агрегированных данных о поисковых запросах, что делает её надёжным индикатором спроса.
People Also Ask — это блок вопросов, который Google показывает прямо в результатах поиска. Каждый вопрос можно развернуть (кликнуть по аккордеону), и Google подгрузит ответ и новые вложенные вопросы. Это создаёт рекурсивную структуру: из 4 начальных вопросов можно получить десятки вложенных.
Related Searches — самый простой источник: блок внизу страницы результатов с 8–10 связанными запросами. Полезен для быстрого расширения семантического ядра.
Технический контекст: почему Google ограничивает автоматические запросы
Проблема в том, что Google активно защищает свои SERP от автоматизированного скрапинга. Когда вы делаете десятки запросов в секунду с одного IP-адреса, Google срабатывает на несколько уровней защиты:
- Per-IP rate limits — после ~50–100 запросов с одного IP за короткое время Google начинает возвращать CAPTCHA или HTTP 429.
- Locale bias — автодополнение и PAA зависят от геолокации IP. Запрос из немецкого IP вернёт немецкие подсказки, даже если вы передаёте
gl=us. Это критично для локализованного keyword research. - Fingerprinting — Google анализирует заголовки, TLS-отпечаток и поведение, чтобы отличить ботов от реальных браузеров.
Поэтому для парсинга автодополнения и PAA нужны residential-прокси с геотаргетингом. Google документирует FAQ-разметку для валидных PAA-блоков, но не предоставляет публичный API для их извлечения — остаётся только скрапинг.
Настройка ProxyHat: residential-прокси с геотаргетингом
ProxyHat предоставляет residential-прокси с поддержкой country- и city-level геотаргетинга через параметры в username. Это позволяет получать локализованные подсказки из любой страны без VPN.
Базовые параметры подключения:
# HTTP-прокси (порт 8080)
http://user-country-US:pass@gate.proxyhat.com:8080
# HTTP-прокси с городом
http://user-country-DE-city-berlin:pass@gate.proxyhat.com:8080
# SOCKS5-прокси (порт 1080)
socks5://user-country-US:pass@gate.proxyhat.com:1080
# Sticky-сессия (один IP на все запросы)
http://user-session-abc123-country-US:pass@gate.proxyhat.com:8080
Для keyword research обычно нужен rotating-режим (каждый запрос — новый IP), чтобы распределить нагрузку и избежать блокировок. Sticky-сессии полезны, когда нужно сохранить один IP для серии связанных запросов — например, при навигации по SERP в Playwright.
Практическая реализация: парсинг автодополнения через httpx и ProxyHat
Начнём с самого простого источника — endpoint автодополнения. Этот endpoint возвращает JSON, поэтому не нужен браузер — достаточно HTTP-клиента.
Базовый запрос через curl
curl -x http://user-country-US:pass@gate.proxyhat.com:8080 \
"https://suggestqueries.google.com/complete/search?client=chrome&q=python"
Ответ — JSON-массив, где второй элемент содержит список подсказок в формате ["подсказка", объём_поиска].
Python: httpx + ProxyHat для автодополнения
import httpx
import json
from typing import Optional
def fetch_autocomplete(
query: str,
country: str = "US",
proxy_user: str = "user",
proxy_pass: str = "pass"
) -> list[str]:
"""Получить подсказки автодополнения Google через residential-прокси."""
proxy_url = f"http://{proxy_user}-country-{country}:{proxy_pass}@gate.proxyhat.com:8080"
url = "https://suggestqueries.google.com/complete/search"
params = {"client": "chrome", "q": query}
with httpx.Client(proxy=proxy_url, timeout=15) as client:
resp = client.get(url, params=params)
resp.raise_for_status()
data = resp.json()
# data[1] — список подсказок, data[1][i][0] — текст подсказки
suggestions = [item[0] for item in data[1]] if len(data) > 1 else []
return suggestions
# Пример
if __name__ == "__main__":
results = fetch_autocomplete("best python framework", country="US")
for s in results:
print(s)
Этот код делает один запрос через residential-прокси с геотаргетингом США. Подсказки будут отражать реальный американский поиск.
Расширение seed-ключевых слов: от одного запроса к сотням long-tail вариантов
Один seed-запрос даёт ~10 подсказок. Чтобы получить сотни, нужно систематически расширять seed с помощью префиксов и суффиксов. Техника проста: добавляйте буквы a-z и модификаторы к seed-запросу.
import itertools
import asyncio
import httpx
from typing import Optional
MODIFIERS = [
"best", "how to", "what is", "why", "vs", "alternatives",
"free", "near me", "for beginners", "review", "pricing",
"tutorial", "examples", "download", "online"
]
ALPHABET = list("abcdefghijklmnopqrstuvwxyz")
def expand_seed(seed: str) -> list[str]:
"""Превратить один seed-запрос в сотни поисковых подсказок."""
queries = [seed]
# Префикс с каждой буквой алфавита
queries += [f"{seed} {ch}" for ch in ALPHABET]
# Модификатор как префикс
queries += [f"{mod} {seed}" for mod in MODIFIERS]
# Модификатор как суффикс
queries += [f"{seed} {mod}" for mod in MODIFIERS]
return list(set(queries))
async def fetch_suggestions(
query: str,
proxy_url: str,
client: httpx.AsyncClient
) -> list[str]:
url = "https://suggestqueries.google.com/complete/search"
params = {"client": "chrome", "q": query}
try:
resp = await client.get(url, params=params)
resp.raise_for_status()
data = resp.json()
return [item[0] for item in data[1]] if len(data) > 1 else []
except Exception as e:
print(f"Error for '{query}': {e}")
return []
async def batch_expand(
seed: str,
country: str = "US",
max_concurrent: int = 10
) -> dict[str, list[str]]:
"""Асинхронно собрать подсказки для всех расширенных запросов."""
proxy = f"http://user-country-{country}:pass@gate.proxyhat.com:8080"
expanded = expand_seed(seed)
sem = asyncio.Semaphore(max_concurrent)
results = {}
async with httpx.AsyncClient(proxy=proxy, timeout=15) as client:
async def limited_fetch(q):
async with sem:
await asyncio.sleep(1.5) # вежливая задержка
return q, await fetch_suggestions(q, proxy, client)
tasks = [limited_fetch(q) for q in expanded]
done = await asyncio.gather(*tasks)
for q, suggestions in done:
results[q] = suggestions
return results
# Запуск
if __name__ == "__main__":
data = asyncio.run(batch_expand("python framework", country="US"))
total = sum(len(v) for v in data.values())
print(f"Собрано {total} подсказок из {len(data)} запросов")
Из одного seed «python framework» этот код сгенерирует ~67 запросов (1 + 26 букв + 15 префиксов + 15 суффиксов), каждый из которых вернёт до 10 подсказок — итого до 670 уникальных long-tail ключевых слов.
Извлечение People Also Ask с помощью Playwright и ProxyHat
People Also Ask требует рендеринга JavaScript и клика по аккордеонам для раскрытия вложенных вопросов. Это означает, что нужен браузер — мы будем использовать Playwright.
from playwright.async_api import async_playwright
import asyncio
import json
from typing import Optional
PROXY_SERVER = "http://gate.proxyhat.com:8080"
PROXY_USER = "user-country-US"
PROXY_PASS = "pass"
async def scrape_paa(
keyword: str,
max_depth: int = 4,
country: str = "US"
) -> list[dict]:
"""
Извлечь вопросы People Also Ask и источники ответов.
Args:
keyword: поисковый запрос
max_depth: сколько раз кликать по аккордеонам
country: код страны для геотаргетинга прокси
"""
questions = []
seen = set()
async with async_playwright() as p:
browser = await p.chromium.launch(
headless=True,
proxy={
"server": PROXY_SERVER,
"username": f"user-country-{country}",
"password": PROXY_PASS
}
)
page = await browser.new_page()
# Устанавливаем реалистичный User-Agent
await page.set_extra_http_headers({
"Accept-Language": "en-US,en;q=0.9"
})
await page.goto(
f"https://www.google.com/search?q={keyword}&gl={country.lower()}",
wait_until="domcontentloaded"
)
await page.wait_for_timeout(2000)
for depth in range(max_depth):
# Находим все элементы PAA
paa_items = await page.query_selector_all("div[role='treeitem']")
for item in paa_items:
try:
text = await item.inner_text()
lines = text.strip().split("\n")
question_text = lines[0].strip()
if question_text.endswith("?") and question_text not in seen:
seen.add(question_text)
# Кликаем для раскрытия ответа и новых вопросов
await item.click()
await page.wait_for_timeout(1500)
# Пытаемся найти источник ответа
answer_source = ""
try:
source_el = await page.query_selector("div[role='treeitem'] a")
if source_el:
answer_source = await source_el.get_attribute("href") or ""
except Exception:
pass
questions.append({
"question": question_text,
"source": answer_source,
"keyword": keyword,
"depth": depth
})
except Exception as e:
print(f"Error extracting PAA item: {e}")
continue
await browser.close()
return questions
# Запуск
if __name__ == "__main__":
paa_data = asyncio.run(scrape_paa("what is python", max_depth=4))
print(f"Извлечено {len(paa_data)} вопросов PAA")
for q in paa_data[:10]:
print(f" [{q['depth']}] {q['question']}")
Каждый клик по аккордеону раскрывает ответ и добавляет 1–2 новых вопроса. При max_depth=4 из 4 начальных вопросов можно получить 20–40 вложенных вопросов. Поле source содержит URL сайта, который Google цитирует как источник ответа — полезно для анализа конкурентов в контент-маркетинге.
Дедупликация, кластеризация и экспорт в CSV
После сбора данных из автодополнения и PAA нужно объединить, дедуплицировать и кластеризовать по интенту для планирования контента.
import csv
import re
from collections import defaultdict
from typing import Optional
def classify_intent(keyword: str) -> str:
"""Классифицировать поисковый интент по паттернам."""
kw_lower = keyword.lower().strip()
if kw_lower.startswith(("how to", "how do", "how does", "how can")):
return "how-to"
if kw_lower.startswith(("what is", "what are", "what does", "who is", "who are")):
return "informational"
if kw_lower.startswith(("why", "when", "where")):
return "informational"
if kw_lower.startswith(("best", "top", "review", "vs", "vs.", "compare")):
return "commercial"
if kw_lower.startswith(("buy", "price", "pricing", "cost", "cheap", "discount")):
return "transactional"
if "near me" in kw_lower or kw_lower.startswith(("find", "locate")):
return "local"
return "general"
def dedupe_and_export(
autocomplete_results: dict[str, list[str]],
paa_results: list[dict],
output_file: str = "keywords.csv"
) -> dict[str, int]:
"""
Объединить данные из автодополнения и PAA,
дедуплицировать, кластеризовать и экспортировать в CSV.
"""
all_keywords = set()
keyword_meta = {} # keyword -> {source, seed, intent}
# Обработка автодополнения
for seed, suggestions in autocomplete_results.items():
for s in suggestions:
clean = s.strip().lower()
if clean and clean not in all_keywords:
all_keywords.add(clean)
keyword_meta[clean] = {
"source": "autocomplete",
"seed": seed,
"intent": classify_intent(clean)
}
# Обработка PAA
for item in paa_results:
clean = item["question"].strip().lower()
if clean and clean not in all_keywords:
all_keywords.add(clean)
keyword_meta[clean] = {
"source": "paa",
"seed": item["keyword"],
"intent": classify_intent(clean)
}
# Кластеризация по интенту
clusters = defaultdict(list)
for kw in all_keywords:
clusters[keyword_meta[kw]["intent"]].append(kw)
# Экспорт в CSV
with open(output_file, "w", newline="", encoding="utf-8") as f:
writer = csv.writer(f)
writer.writerow(["keyword", "intent", "source", "seed"])
for kw in sorted(all_keywords):
meta = keyword_meta[kw]
writer.writerow([kw, meta["intent"], meta["source"], meta["seed"]])
# Статистика
stats = {intent: len(items) for intent, items in clusters.items()}
print(f"\nЭкспортировано {len(all_keywords)} уникальных ключевых слов в {output_file}")
print("\nКластеры по интенту:")
for intent, count in sorted(stats.items(), key=lambda x: -x[1]):
print(f" {intent}: {count}")
return stats
# Пример использования
if __name__ == "__main__":
# Предполагается, что autocomplete_data и paa_data уже собраны
# stats = dedupe_and_export(autocomplete_data, paa_data, "research_keywords.csv")
На выходе получается CSV-файл с колонками keyword, intent, source и seed. Этот файл可以直接 можно импортировать в Google Sheets, Notion или любой SEO-инструмент для дальнейшего планирования контента.
Распространённые ошибки и граничные случаи
1. Локальный bias автодополнения
Автодополнение Google жёстко привязано к геолокации IP. Если вы парсите из дата-центра в Франкфурте без прокси, вы получите немецкие подсказки даже для английских запросов. Residential-прокси с параметром country-US решают эту проблему — Google видит американский IP и возвращает американские подсказки.
2. Пустые ответы при высоком rate
При превышении ~100 запросов в минуту с одного IP Google начинает возвращать пустые JSON-массивы вместо блокировки. Это легко пропустить: код не падает, но данные пустые. Решение — ограничить concurrency до 10 одновременных запросов и добавить задержку 1–2 секунды между запросами.
3. Изменение структуры SERP
Селекторы PAA (div[role='treeitem']) могут меняться. Google регулярно обновляет DOM-структуру SERP. Рекомендуется периодически проверять селекторы и иметь fallback-логику. Для production-систем лучше использовать несколько альтернативных селекторов.
4. Дубликаты при рекурсивном PAA
При раскрытии аккордеонов Google может показывать одни и те же вопросы на разных уровнях вложенности. Множество seen в коде выше решает эту проблему — дубликаты пропускаются.
Этика: ответственный подход к сбору данных
Автодополнение и PAA — это публичные данные, которые Google показывает каждому пользователю. Однако массовый скрапинг создаёт нагрузку на инфраструктуру Google. Несколько принципов ответственного подхода:
- Соблюдайте robots.txt — проверьте
https://www.google.com/robots.txtперед началом скрапинга. - Троттлинг — держите задержку 1–2 секунды между запросами, не превышайте 10 одновременных соединений.
- Используйте официальные API где возможно — Google Keyword Planner API (через Google Ads) предоставляет данные о поисковом объёме легально и без риска блокировок. Скрапинг оправдан, когда нужен long-tail, который не покрывает Keyword Planner.
- GDPR и CCPA — поисковые подсказки не содержат персональных данных, но если вы собираете данные о конкретных пользователях, учитывайте требования GDPR и CCPA.
Ознакомьтесь с тарифами ProxyHat для выбора подходящего плана residential-прокси, а также со списком доступных геолокаций для точного таргетинга.
Ключевые выводы
Резюме: Парсинг People Also Ask и автодополнения Google — это бесплатный способ собрать сотни реальных поисковых запросов. Три источника (Autocomplete, PAA, Related Searches) покрывают разные типы интента. Residential-прокси с геотаргетингом необходимы для получения локализованных данных без блокировок. Дедупликация и кластеризация по интенту превращают сырые данные в готовый контент-план.
- Автодополнение возвращает ~10 подсказок на запрос; расширение через a-z и модификаторы превращает один seed в 500+ ключевых слов.
- PAA даёт вопросные запросы с источниками ответов — идеально для FAQ-страниц и контент-маркетинга.
- Residential-прокси с country-level геотаргетингом (
user-country-US) решают проблему локального bias и блокировок. - Ограничение concurrency до 10 и задержка 1–2 секунды обеспечивают вежливый скрапинг без CAPTCHA.
- Экспорт в CSV с кластеризацией по интенту создаёт готовый вход для контент-планирования.
Готовы начать? Изучите варианты использования ProxyHat для веб-скрапинга и SERP-трекинга, или посетите документацию ProxyHat для подробной настройки прокси.






