Pesquisa de palavras-chave virou um jogo de volume e intenção: uma única semente como “seguro de viagem” pode gerar 300+ variações longtail se você souber onde procurar. Este guia mostra como raspar People Also Ask e Autocomplete do Google com Python, combinando o endpoint público de sugestões, o bloco PAA e Related Searches. Vamos usar httpx para chamadas concorrentes, Playwright para expandir acordeões de PAA e proxies residenciais geo-direcionados para obter sugestões localizadas sem disparar limites de taxa por IP.
As três minas de ouro gratuitas: Autocomplete, PAA e Related Searches
O Google expõe três fontes públicas de intenção de busca, cada uma mapeando para um estágio diferente do funnel de pesquisa:
| Fonte | Endpoint / seletor | Intenção dominante | Volume típico por semente |
|---|---|---|---|
| Autocomplete (Suggest) | suggestqueries.google.com/complete/search?client=chrome&q= | Longtail informacional e transacional | 10 sugestões por letra/modificador |
| People Also Ask | Seletor div.related-question-pair na SERP | Perguntas informacionais (5W1H) | 4-8 iniciais, expansível recursivamente |
| Related Searches | Seletor div.brs-col no fim da SERP | Variações semânticas e comerciais | 8-10 por consulta |
O endpoint de Autocomplete é o mais produtivo em volume: cada letra do alfabeto (a-z) mais modificadores (“como”, “melhor”, “preço”) gera ~10 sugestões, totalizando 260+ variações a partir de uma semente. O PAA é mais rico em intenção pergunta e expande recursivamente — cada pergunta clicada revela 2-3 novas perguntas aninhadas, conforme documentado em estudos de interação com acordeões web. Related Searches fecha o ciclo com variações semânticas que o Google já agrupou como relevantes.
Mapeando cada fonte para intenção de busca
- Autocomplete → longtail de cauda longa, ótimo para páginas de produto e guias de compra.
- PAA → perguntas para FAQ, schema FAQPage e conteúdo de topo de funil.
- Related Searches → variações de cluster temático para silo de conteúdo.
Construindo um expansor semente-para-longtail
A estratégia é simples mas poderosa: pegue uma semente, adicione prefixos alfabéticos (a-z) e modificadores de intenção, consulte o endpoint de autocomplete para cada combinação e dedupe os resultados. Com 26 letras + 5 modificadores = 31 chamadas por semente, gerando ~300 sugestões brutas.
Exemplo 1: Expansor de autocomplete com httpx e ProxyHat
import httpx
import asyncio
import itertools
import json
from urllib.parse import quote
PROXY_URL = "http://user-country-DE-city-berlin:pass@gate.proxyhat.com:8080"
SUGGEST_URL = "https://suggestqueries.google.com/complete/search?client=chrome&q={q}"
async def fetch_suggestions(client: httpx.AsyncClient, query: str) -> list[str]:
url = SUGGEST_URL.format(q=quote(query))
try:
resp = await client.get(url, timeout=10.0)
resp.raise_for_status()
data = resp.json()
# data[1] contém a lista de sugestões
return data[1] if len(data) > 1 else []
except (httpx.HTTPError, json.JSONDecodeError) as exc:
print(f"Erro para '{query}': {exc}")
return []
async def expand_seed(seed: str) -> set[str]:
modifiers = ["", "como ", "melhor ", "preço ", "vs "]
prefixes = list(itertools.chain(modifiers, [chr(c) + " " for c in range(ord("a"), ord("z") + 1)]))
queries = [f"{p}{seed}" for p in prefixes]
async with httpx.AsyncClient(
proxy=PROXY_URL,
headers={"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"},
limits=httpx.Limits(max_connections=5),
) as client:
tasks = [fetch_suggestions(client, q) for q in queries]
results = await asyncio.gather(*tasks)
all_suggestions = set()
for query, suggestions in zip(queries, results):
for s in suggestions:
all_suggestions.add(s)
return all_suggestions
if __name__ == "__main__":
seed = "seguro de viagem"
suggestions = asyncio.run(expand_seed(seed))
print(f"{len(suggestions)} sugestões únicas para '{seed}'")
for s in sorted(suggestions)[:10]:
print(f" - {s}")
Esse script faz 31 chamadas concorrentes (limitadas a 5 conexões simultâneas) via proxy residencial em Berlim, retornando sugestões localizadas para o mercado alemão. Sem geo-targeting, o Google retornaria sugestões baseadas no IP do servidor — provavelmente EUA ou Irlanda se você usa um cloud provider.
Expansão recursiva de PAA com Playwright
O bloco People Also Ask começa com 4-8 perguntas, mas cada acordeão clicado revela mais 2-3 perguntas aninhadas. Expandir recursivamente pode gerar 50-100 perguntas por semente. Como o PAA é renderizado dinamicamente e requer clique, usamos Playwright com proxy.
Exemplo 2: Extrator de PAA com Playwright e proxy SOCKS5
from playwright.async_api import async_playwright
import asyncio
import json
SOCKS5_PROXY = "socks5://user-country-US:pass@gate.proxyhat.com:1080"
async def scrape_paa(seed: str, max_depth: int = 3) -> list[dict]:
questions = []
seen = set()
async with async_playwright() as p:
browser = await p.chromium.launch(
headless=True,
proxy={"server": SOCKS5_PROXY},
)
context = await browser.new_context(
user_agent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36",
viewport={"width": 1280, "height": 800},
)
page = await context.new_page()
await page.goto(f"https://www.google.com/search?q={seed}", wait_until="domcontentloaded")
for depth in range(max_depth):
paa_elements = await page.query_selector_all("div.related-question-pair")
for el in paa_elements:
text = await el.inner_text()
question_text = text.strip().split("\n")[0]
if question_text and question_text not in seen:
seen.add(question_text)
questions.append({
"question": question_text,
"depth": depth,
"seed": seed,
})
# Clica para expandir e revelar perguntas aninhadas
try:
await el.click(timeout=2000)
await page.wait_for_timeout(800)
except Exception:
continue
await browser.close()
return questions
if __name__ == "__main__":
results = asyncio.run(scrape_paa("seguro de viagem europeu"))
print(json.dumps(results[:5], ensure_ascii=False, indent=2))
Exemplo 3: Extraindo fontes citadas nas respostas de PAA
Cada resposta expandida de PAA inclui links de fonte citados pelo Google. Esses domínios são oportunidades de backlink e indicam quais sites o Google considera autoritativos para o tópico.
async def extract_paa_with_sources(page, seed: str) -> list[dict]:
results = []
paa_blocks = await page.query_selector_all("div.related-question-pair")
for block in paa_blocks[:8]:
try:
await block.click(timeout=3000)
await page.wait_for_timeout(1000)
question = (await block.inner_text()).strip().split("\n")[0]
# Extrai links de fonte dentro do bloco expandido
source_links = await block.query_selector_all("a[data-ved]")
sources = []
for link in source_links:
href = await link.get_attribute("href")
text = await link.inner_text()
if href and href.startswith("http"):
sources.append({"url": href, "anchor": text.strip()})
results.append({
"question": question,
"seed": seed,
"sources": sources[:3], # top 3 fontes citadas
})
except Exception as exc:
print(f"Erro ao expandir bloco: {exc}")
continue
return results
Por que chamadas rápidas disparam limites de taxa e viés de localização
O Google aplica dois mecanismos de defesa que afetam scraping de autocomplete e PAA:
- Limite de taxa por IP: chamadas acima de ~100/min do mesmo IP retornam HTTP 429 ou redirecionam para CAPTCHA. O endpoint de autocomplete é mais tolerante que a SERP HTML, mas ainda assim bloqueia IPs datacenter agressivamente.
- Viés de localização: sugestões de autocomplete e resultados de PAA são influenciados pelo país e cidade do IP solicitante. Um request de um IP em Frankfurt retorna sugestões em alemão; o mesmo query de um IP em São Paulo retorna sugestões em português brasileiro.
Proxies datacenter (AWS, DigitalOcean, OVH) são rapidamente identificados pelo Google porque seus ranges de IP são publicamente conhecidos. Proxies residenciais usam IPs atribuídos a dispositivos reais por ISPs, tornando a detecção muito mais difícil. Combine isso com geo-targeting de país e cidade para obter sugestões consistentes para um mercado-alvo.
Exemplo 4: Rotação de sessões sticky por país com ProxyHat
import httpx
import asyncio
import random
import string
BASE_PROXY = "http://gate.proxyhat.com:8080"
def make_proxy_url(country: str, city: str = None) -> str:
session_id = "".join(random.choices(string.ascii_lowercase + string.digits, k=8))
username = f"user-country-{country}-session-{session_id}"
if city:
username = f"user-country-{country}-city-{city}-session-{session_id}"
return f"http://{username}:pass@gate.proxyhat.com:8080"
async def fetch_with_retry(client_factory, url: str, max_retries: int = 3) -> dict:
for attempt in range(max_retries):
proxy_url = make_proxy_url("BR", "saopaulo")
async with httpx.AsyncClient(
proxy=proxy_url,
headers={"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"},
timeout=15.0,
) as client:
try:
resp = await client.get(url)
if resp.status_code == 200:
return resp.json()
elif resp.status_code == 429:
wait = 2 ** attempt + random.uniform(0.5, 1.5)
print(f"429 recebido, esperando {wait:.1f}s")
await asyncio.sleep(wait)
continue
else:
print(f"HTTP {resp.status_code}")
return {}
except httpx.HTTPError as exc:
print(f"Tentativa {attempt+1} falhou: {exc}")
await asyncio.sleep(2 ** attempt)
return {}
async def main():
url = "https://suggestqueries.google.com/complete/search?client=chrome&q=seguro%20viagem"
data = await fetch_with_retry(None, url)
suggestions = data.get("1", []) if isinstance(data, list) and len(data) > 1 else []
print(f"{len(suggestions)} sugestões via proxy BR/São Paulo")
asyncio.run(main())
O parâmetro -session- mantém o mesmo IP residencial por sessão, útil para manter consistência de localização entre chamadas relacionadas. Sem session, cada request recebe um novo IP automaticamente.
Dedup, clusterização por intenção e exportação para CSV
Após coletar sugestões de autocomplete, perguntas de PAA e Related Searches, você terá centenas de termos sobrepostos. O próximo passo é limpar, clusterizar por intenção e exportar para planejamento de conteúdo.
Exemplo 5: Pipeline completo de dedup, clusterização e exportação CSV
import csv
import re
from collections import defaultdict
def normalize_keyword(kw: str) -> str:
return re.sub(r"\s+", " ", kw.strip().lower())
def classify_intent(kw: str) -> str:
informational = ["como", "o que é", "por que", "quando", "qual", "guia", "tutorial"]
commercial = ["melhor", "top", "comparativo", "review", "vs"]
transactional = ["comprar", "preço", "desconto", "barato", "oferta"]
kw_lower = kw.lower()
if any(w in kw_lower for w in transactional):
return "transactional"
if any(w in kw_lower for w in commercial):
return "commercial"
if any(w in kw_lower for w in informational):
return "informational"
return "navigational"
def dedupe_and_cluster(all_keywords: list[str]) -> dict[str, list[str]]:
seen = set()
clusters = defaultdict(list)
for kw in all_keywords:
norm = normalize_keyword(kw)
if norm not in seen and len(norm) > 3:
seen.add(norm)
intent = classify_intent(norm)
clusters[intent].append(norm)
return clusters
def export_to_csv(clusters: dict[str, list[str]], filename: str = "keywords.csv"):
with open(filename, "w", newline="", encoding="utf-8") as f:
writer = csv.writer(f)
writer.writerow(["keyword", "intent", "source"])
for intent, keywords in clusters.items():
for kw in keywords:
writer.writerow([kw, intent, "google-suggest+paa"])
print(f"{sum(len(v) for v in clusters.values())} palavras-chave exportadas para {filename}")
# Uso
if __name__ == "__main__":
raw_keywords = [
"seguro de viagem europeu",
"como funciona seguro de viagem",
"melhor seguro de viagem internacional",
"seguro de viagem preço",
"o que é seguro de viagem",
"comprar seguro de viagem online",
"seguro de viagem vs plano de saúde",
]
clusters = dedupe_and_cluster(raw_keywords)
export_to_csv(clusters)
Esse pipeline normaliza keywords (remove espaços extras, lowercase), classifica intenção usando padrões linguísticos e agrupa em clusters. O CSV resultante alimenta diretamente um calendário editorial: perguntas viram FAQ pages, termos transacionais viram landing pages de produto, e termos informacionais viram artigos de blog.
Configuração do ProxyHat e melhores práticas de produção
Para integrar o ProxyHat no seu pipeline de keyword research, configure o gateway residencial com geo-targeting. A documentação completa está em docs.proxyhat.com.
Configuração recomendada
| Parâmetro | Valor | Quando usar |
|---|---|---|
| Gateway | gate.proxyhat.com:8080 | HTTP/HTTPS (autocomplete, SERP) |
| SOCKS5 | gate.proxyhat.com:1080 | Playwright, navegadores headless |
| Geo-targeting | -country-BR-city-saopaulo | Sugestões localizadas por mercado |
| Session sticky | -session-abc123 | Manter IP consistente entre chamadas |
| Concorrência | 5-10 por IP | Evitar 429 e CAPTCHA |
Exemplo: curl com geo-targeting para validar localização
curl -x "http://user-country-DE-city-berlin:pass@gate.proxyhat.com:8080" \
"https://suggestqueries.google.com/complete/search?client=chrome&q=versicherung" \
-H "User-Agent: Mozilla/5.0" \
--max-time 10
Confira os locais de proxy disponíveis e a página de preços para escolher o plano adequado ao seu volume de scraping.
Erros comuns e casos de borda
- Esquecer headers de navegador: o endpoint de autocomplete retorna JSON mesmo sem headers, mas a SERP HTML requer um User-Agent realista. Sem ele, o Google retorna uma página simplificada sem PAA.
- Concorrência excessiva: mais de 10 conexões simultâneas por IP residencial aumenta drasticamente a taxa de 429. Use
httpx.Limits(max_connections=5)como padrão. - Ignorar parâmetro
client:client=chromeretorna JSON estruturado;client=firefoxretorna formato diferente; semclient, retorna XML. Sempre useclient=chrome. - Não dedupar entre fontes: PAA e Related Searches frequentemente sobrepõem. Normalize e dedupe antes de exportar.
- Parar na primeira camada de PAA: o valor real está na recursão. Cada clique revela 2-3 novas perguntas. Configure
max_depth=3no mínimo.
Ética e considerações legais
Autocomplete, PAA e Related Searches são dados públicos exibidos pelo Google para qualquer usuário. Raspar esses dados para pesquisa de palavras-chave é amplamente aceito, mas há limites:
- Respeite
robots.txt: verifique as regras desuggestqueries.google.com/robots.txtantes de coletar em escala. - Throttle polite: mantenha 1-3 segundos de delay aleatório entre chamadas. Não é apenas ético — reduz bloqueios.
- Prefira APIs oficiais em escala: o Google Custom Search JSON API e o Google Search Console fornecem dados de query oficiais com limites documentados. Para volumes acima de 10.000 queries/dia, migre para APIs oficiais.
- GDPR e dados pessoais: sugestões de autocomplete podem conter nomes de pessoas. Não armazene nem processe dados pessoais sem base legal.
Para casos de uso de scraping web e SERP tracking em produção, consulte nossos guias de web scraping e SERP tracking.
Dica de produção: implemente um circuit breaker que pausa o scraping por 60 segundos após 3 erros 429 consecutivos. Isso evita que o Google marque seu pool de proxies como abusivo e estenda o bloqueio para além do IP individual.
Key Takeaways
- Autocomplete é a fonte de maior volume: 31 combinações (a-z + modificadores) geram ~300 sugestões por semente.
- PAA é a fonte de maior intenção pergunta: expansão recursiva com Playwright revela 50-100 perguntas por semente, com fontes citadas.
- Related Searches fecha o cluster temático: use junto com PAA para mapear o ecossistema semântico de um tópico.
- Proxies residenciais com geo-targeting são obrigatórios: sem country/city targeting, sugestões são enviesadas pelo IP do servidor e chamadas rápidas disparam 429.
- Dedupe e clusterize por intenção antes de exportar: classifica em informational, commercial, transactional e navigational para alimentar um calendário editorial.
- Em escala, prefira APIs oficiais: Google Custom Search API e Search Console são mais sustentáveis acima de 10.000 queries/dia.
FAQ
O que é raspar People Also Ask e Autocomplete do Google?
É o processo de coletar automaticamente sugestões de autocomplete, perguntas do bloco People Also Ask e buscas relacionadas da página de resultados do Google, usando scripts Python e clientes HTTP. Esses dados revelam intenções de busca reais e permitem expandir uma palavra-chave semente em centenas de variações longtail para planejamento de conteúdo e FAQ.
Por que raspar PAA e Autocomplete importa para usuários de proxy?
O Google impõe limites de taxa por IP e aplica viés de localização nas sugestões. Sem proxies residenciais geo-direcionados, chamadas rápidas a endpoints de autocomplete e PAA retornam erros 429, CAPTCHAs ou sugestões enviesadas pelo IP do servidor. Proxies residenciais com country/city targeting permitem obter sugestões limpas e localizadas a escala.
Qual tipo de proxy funciona melhor para raspar PAA e Autocomplete?
Proxies residenciais são os mais adequados porque usam IPs de dispositivos reais atribuídos por ISPs, reduzindo a chance de bloqueio. Para sugestões localizadas, combine geo-targeting de país e cidade no usuário do proxy. Proxies datacenter são mais baratos, mas têm maior taxa de bloqueio em endpoints do Google.
Como evitar bloqueios ao raspar People Also Ask e Autocomplete?
Use proxies residenciais com rotação por requisição, limite a concorrência a 5-10 conexões simultâneas por IP, adicione delays aleatórios de 1-3 segundos entre chamadas, configure headers realistas de navegador e implemente retentativas com backoff exponencial. Em escala, prefira a Official Google Suggest API ou Search Console.





