Voltar ao blog
Guias e Tutoriais2026-02-12·7 min de leitura

Como Scrapear Avaliações do Google Usando Python — Guia Completo de 2025

Por Ibrahim DemolCEO IBLeadAtualizado em 26 de março de 2026

Avaliações do Google são uma mina de ouro de feedback dos clientes, mas coletar milhares delas manualmente? Isso é ineficiente e impraticável.

Com Python, você pode automatizar todo o processo de extração e reunir milhares de avaliações em poucas horas. Este guia o orienta em tudo — desde a configuração básica até scrapers prontos para produção que lidam com as defesas anti-scraping do Google.

Ao final, você entenderá como construir scrapers de avaliações confiáveis, evitar detecções e extrair insights acionáveis dos clientes em grande escala.


O que é Scraping de Avaliações do Google?

Scraping de avaliações do Google é a extração automatizada de dados de feedback dos clientes a partir do Google Maps e perfis do Google Business usando scripts em Python.

Quando você scrapeia avaliações do Google, você captura:

  • Avaliações em estrelas (1–5 estrelas)
  • Texto da avaliação (comentários completos dos clientes)
  • Nomes e perfis dos avaliadores
  • Datas e horários das avaliações
  • Respostas das empresas (se o proprietário respondeu)
  • Contagem de votos úteis

Diferente da API oficial do Google — que é cara e possui limites severos — o scraping lhe dá acesso a todas as avaliações disponíveis sem cotas ou restrições.

Por que Scrapear em vez de Usar a API do Google?

A API oficial do Google Places para avaliações tem limitações sérias:

Recurso API Oficial Web Scraping
Avaliações por solicitação ~10 (apenas recentes) Todas disponíveis
Custo $7 por 1.000 solicitações Gratuito a baixo custo
Limites de taxa 100 solicitações/segundo no máximo Configurável
Avaliações de concorrentes ❌ Não ✅ Sim
Complexidade de configuração Moderada (autenticação) Maior (técnica)

Para análise competitiva, pesquisa de mercado ou coleta de dados em grande escala, o scraping é a escolha prática.


Por que Python é a Melhor Linguagem para Esta Tarefa

Python domina o web scraping por três razões principais:

1. Ecossistema de Scraping Rico

Python possui bibliotecas específicas para web scraping:

  • Playwright — Automação de navegador moderna e rápida
  • Selenium — Testado em batalha, máxima compatibilidade
  • BeautifulSoup — Análise leve de HTML
  • Scrapy — Framework de scraping de nível empresarial
  • Pandas — Manipulação e exportação de dados

Você pode passar de HTML bruto para CSV limpo em um único script.

2. Execução de JavaScript

Avaliações do Google carregam dinamicamente através de JavaScript, não no HTML inicial. As ferramentas de automação de navegador do Python (Playwright, Selenium) executam JavaScript como um navegador real, permitindo que você:

  • Acione o scroll infinito
  • Clique em botões "Mostrar mais"
  • Espere o conteúdo aparecer
  • Interaja com elementos da página

3. Recursos Anti-Detecção Integrados

Bibliotecas modernas do Python vêm com capacidades de stealth prontas para uso:

# Ocultar indicadores de automação
options.add_argument("--disable-blink-features=AutomationControlled")
options.add_experimental_option("excludeSwitches", ["enable-automation"])

Essas flags impedem que o Google detecte seu script como um bot.

4. Pipeline de Processamento de Dados Sem Costura

Com Python, você scrapeia → limpa → analisa → exporta tudo em um único script. Nenhuma troca de ferramentas é necessária.


O Desafio: Por que o Google Torna o Scraping Difícil

O Google emprega múltiplas camadas anti-scraping. Compreender isso ajuda você a construir scrapers resilientes.

1. Carregamento de Conteúdo Dinâmico

Avaliações do Google não carregam todas de uma vez. Em vez disso:

  • O carregamento inicial da página mostra 10–20 avaliações
  • Avaliações adicionais carregam via AJAX conforme você rola
  • Cada lote requer solicitações de rede separadas
  • O mecanismo muda frequentemente

Solução: Use automação de navegador (Playwright/Selenium) que executa JavaScript e simula o scroll.

2. Detecção de Bots Sofisticada

O Google analisa:

  • Impressão digital do navegador — Resolução de tela, fontes instaladas, fuso horário
  • Padrões comportamentais — Movimentos do mouse, velocidade de rolagem, tempo de clique
  • Frequência de solicitações — Detectando padrões de solicitações não humanas
  • Reputação do IP — Marcando endereços suspeitos

Solução: Rotacione proxies, adicione atrasos aleatórios, use agentes de usuário realistas.

3. Limite de Taxas e CAPTCHAs

Se você pressionar o Google com muita força, enfrentará:

  • Bloqueios temporários de IP (24–48 horas)
  • Desafios CAPTCHA
  • Negação total de acesso
  • Throttling progressivo

Solução: Implemente throttling de solicitações (atrasos de 1–3 segundos entre ações).

4. Estrutura HTML em Evolução Constante

O Google atualiza regularmente a estrutura de suas páginas, quebrando seletores CSS da noite para o dia.

Solução: Use múltiplos seletores de fallback e consultas baseadas em atributos em vez de nomes de classes frágeis.


Método 1: Playwright — A Abordagem Moderna

Playwright é a escolha recomendada para 2025. É mais rápido que o Selenium, possui melhores recursos anti-detecção e lida facilmente com sites modernos pesados em JavaScript.

Configurando o Playwright

Primeiro, crie um ambiente virtual e instale as dependências:

# Criar ambiente virtual
python -m venv google_scraper
source google_scraper/bin/activate  # No Windows: google_scraper\Scripts\activate

# Instalar pacotes necessários
pip install playwright pandas beautifulsoup4 lxml emoji

# Instalar navegador
playwright install chromium

Código Completo do Scraper Playwright

Aqui está um scraper pronto para produção que lida com as complexidades das avaliações do Google:

from playwright.sync_api import sync_playwright
import pandas as pd
import re
import emoji
import logging
import time
import random
from datetime import datetime

# Configurar logging
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)

class GoogleReviewsScraper:
    def __init__(self, headless=True):
        self.headless = headless
        self.reviews_data = []

    def clean_text(self, text):
        """Remove emojis e normaliza o texto"""
        if not text:
            return ""
        text = emoji.replace_emoji(text, replace='')
        text = re.sub(r'\s+', ' ', text).strip()
        return text

    def random_delay(self, min_delay=1, max_delay=3):
        """Adiciona atrasos aleatórios para imitar o comportamento humano"""
        delay = random.uniform(min_delay, max_delay)
        time.sleep(delay)

    def initialize_browser(self):
        """Inicializa o Playwright com configurações stealth"""
        playwright = sync_playwright().start()
        browser = playwright.chromium.launch(
            headless=self.headless,
            args=[
                '--disable-blink-features=AutomationControlled',
                '--disable-extensions',
                '--no-sandbox',
                '--disable-dev-shm-usage',
                '--disable-gpu'
            ]
        )

        context = browser.new_context(
            user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
            viewport={'width': 1366, 'height': 768}
        )

        page = context.new_page()

        # Ocultar propriedade do webdriver
        page.add_init_script("""
            Object.defineProperty(navigator, 'webdriver', {
                get: () => undefined,
            });
        """)

        return playwright, browser, page

    def search_business(self, page, business_name):
        """Busca por uma empresa no Google Maps"""
        try:
            page.goto("https://www.google.com/maps", wait_until="networkidle")
            self.random_delay(2, 4)

            # Encontrar caixa de pesquisa e inserir nome da empresa
            search_box = page.locator("input[id='searchboxinput']")
            search_box.fill(business_name)
            search_box.press("Enter")

            # Aguardar resultados carregarem
            page.wait_for_timeout(5000)
            logger.info(f"Buscou por: {business_name}")
            return True

        except Exception as e:
            logger.error(f"Erro ao buscar empresa: {e}")
            return False

    def navigate_to_reviews(self, page):
        """Navega até a seção de avaliações"""
        try:
            # Procurar aba de avaliações
            reviews_tab = page.get_by_role("tab", name=re.compile("Avaliações|avaliações", re.IGNORECASE))
            if reviews_tab.is_visible():
                reviews_tab.click()
                page.wait_for_timeout(3000)
                logger.info("Navegado para a seção de avaliações")
                return True
            else:
                logger.warning("Aba de avaliações não encontrada")
                return False

        except Exception as e:
            logger.error(f"Erro ao navegar para avaliações: {e}")
            return False

    def scroll_and_load_reviews(self, page, max_reviews=100):
        """Rola para carregar mais avaliações dinamicamente"""
        loaded_reviews = 0
        scroll_attempts = 0
        max_scroll_attempts = 20

        while loaded_reviews < max_reviews and scroll_attempts < max_scroll_attempts:
            try:
                # Rolar até o fundo
                page.evaluate("window.scrollTo(0, document.body.scrollHeight)")
                self.random_delay(2, 4)

                # Contar avaliações atuais
                current_reviews = page.locator('[data-review-id]').count()

                if current_reviews > loaded_reviews:
                    loaded_reviews = current_reviews
                    logger.info(f"Carregado {loaded_reviews} avaliações...")
                    scroll_attempts = 0  # Reiniciar contador
                else:
                    scroll_attempts += 1

                # Tentar clicar no botão "Mais avaliações" se disponível
                try:
                    more_button = page.locator("button:has-text('Mais'), button:has-text('mais')")
                    if more_button.is_visible():
                        more_button.click()
                        self.random_delay(2, 3)
                except:
                    pass

            except Exception as e:
                logger.error(f"Erro durante a rolagem: {e}")
                break

        logger.info(f"Carregamento finalizado. Total de avaliações: {loaded_reviews}")
        return loaded_reviews

    def extract_review_data(self, page):
        """Extrai dados individuais de avaliações da página carregada"""
        reviews = []

        try:
            review_elements = page.locator('[data-review-id]').all()

            for element in review_elements:
                try:
                    review_data = {}

                    # Extrair nome do avaliador
                    try:
                        name_element = element.locator('div[class*="name"] span').first
                        review_data['reviewer_name'] = name_element.inner_text() if name_element.is_visible() else "Anônimo"
                    except:
                        review_data['reviewer_name'] = "Anônimo"

                    # Extrair avaliação
                    try:
                        rating_element = element.locator('[role="img"][aria-label*="star"]').first
                        if rating_element.is_visible():
                            rating_text = rating_element.get_attribute('aria-label')
                            rating_match = re.search(r'(\d+)', rating_text)
                            review_data['rating'] = int(rating_match.group(1)) if rating_match else None
                        else:
                            review_data['rating'] = None
                    except:
                        review_data['rating'] = None

                    # Extrair texto da avaliação
                    try:
                        text_elements = element.locator('span[class*="review-text"], div[class*="review-text"]').all()
                        review_text = ""
                        for text_elem in text_elements:
                            if text_elem.is_visible():
                                review_text += text_elem.inner_text() + " "
                        review_data['review_text'] = self.clean_text(review_text.strip())
                    except:
                        review_data['review_text'] = ""

                    # Extrair data
                    try:
                        date_element = element.locator('span[class*="date"], div[class*="date"]').first
                        review_data['review_date'] = date_element.inner_text() if date_element.is_visible() else "Desconhecido"
                    except:
                        review_data['review_date'] = "Desconhecido"

                    # Extrair contagem de úteis
                    try:
                        helpful_element = element.locator('[aria-label*="útil"], [aria-label*="Útil"]').first
                        if helpful_element.is_visible():
                            helpful_text = helpful_element.get_attribute('aria-label')
                            helpful_match = re.search(r'(\d+)', helpful_text)
                            review_data['helpful_count'] = int(helpful_match.group(1)) if helpful_match else 0
                        else:
                            review_data['helpful_count'] = 0
                    except:
                        review_data['helpful_count'] = 0

                    # Apenas adicionar avaliações com conteúdo de texto real
                    if review_data['review_text']:
                        reviews.append(review_data)

                except Exception as e:
                    logger.warning(f"Erro ao extrair avaliação individual: {e}")
                    continue

            logger.info(f"Extraído com sucesso {len(reviews)} avaliações")
            return reviews

        except Exception as e:
            logger.error(f"Erro ao extrair avaliações: {e}")
            return []

    def scrape_reviews(self, business_name, max_reviews=100):
        """Método principal de scraping"""
        playwright, browser, page = self.initialize_browser()

        try:
            # Buscar empresa
            if not self.search_business(page, business_name):
                return []

            # Navegar até aba de avaliações
            if not self.navigate_to_reviews(page):
                return []

            # Carregar avaliações rolando
            self.scroll_and_load_reviews(page, max_reviews)

            # Extrair dados das avaliações
            reviews = self.extract_review_data(page)
            self.reviews_data = reviews
            return reviews

        except Exception as e:
            logger.error(f"Scraping falhou: {e}")
            return []

        finally:
            browser.close()
            playwright.stop()

    def save_to_csv(self, filename="google_reviews.csv"):
        """Salva avaliações em arquivo CSV"""
        if self.reviews_data:
            df = pd.DataFrame(self.reviews_data)
            df['extraction_date'] = datetime.now().isoformat()
            df.to_csv(filename, index=False, encoding='utf-8')
            logger.info(f"Avaliações salvas em {filename}")
            print(f"✅ Exportado {len(self.reviews_data)} avaliações para {filename}")
        else:
            logger.warning("Nenhuma avaliação para salvar")

# Exemplo de uso
if __name__ == "__main__":
    scraper = GoogleReviewsScraper(headless=False)  # Defina como True para produção

    business_name = "Starbucks Times Square New York"
    reviews = scraper.scrape_reviews(business_name, max_reviews=50)

    if reviews:
        scraper.save_to_csv(f"reviews_{business_name.replace(' ', '_')}.csv")
        print(f"✅ Avaliações {len(reviews)} extraídas com sucesso!")
    else:
        print("❌ Nenhuma avaliação foi extraída.")

Como Este Scraper Funciona

1. Configuração Stealth

O scraper oculta indicadores de automação que o Google usa para detectar bots:

options.add_argument("--disable-blink-features=AutomationControlled")
page.add_init_script("Object.defineProperty(navigator, 'webdriver', {get: () => undefined})")

2. Atrasos Aleatórios

Em vez de disparar solicitações instantaneamente, o scraper espera de 1 a 3 segundos entre as ações para imitar a navegação humana.

3. Rolagem Dinâmica

Ele rola até o fundo da seção de avaliações repetidamente, acionando o mecanismo de scroll infinito do Google para carregar mais avaliações.

4. Tratamento Robusto de Erros

Se um seletor falhar (porque o Google mudou o HTML), o scraper tenta seletores de fallback em vez de travar.

5. Limpeza de Dados

Avaliações são limpas para remover emojis, normalizar espaços em branco e garantir dados de qualidade.


Método 2: Selenium — A Alternativa Testada em Batalha

Enquanto o Playwright é mais rápido, o Selenium continua sendo o padrão ouro para compatibilidade e possui uma comunidade enorme. Use o Selenium se precisar de suporte máximo ao navegador ou se já tiver infraestrutura existente do Selenium.

Instalação do Selenium

pip install selenium webdriver-manager pandas beautifulsoup4

# Baixar ChromeDriver (gerenciado automaticamente pelo webdriver-manager)

Implementação Completa do Selenium

```python from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.chrome.options import Options from selenium.webdriver.common.action_chains import ActionChains from selenium.common.exceptions import TimeoutException, NoSuchElementException import pandas as pd import time import random import re import logging from datetime import datetime

logging.basicConfig(level=logging.INFO) logger = logging.getLogger(name)

class SeleniumGoogleReviewsScraper: def init(self, headless=True): self.headless = headless self.driver = None self.wait = None self.reviews_data = []

def setup_driver(self):
    """Configura e inicializa o driver do Chrome"""
    options = Options()

    if self.headless:
        options.add_argument("--headless")

    # Medidas anti-detecção
    options.add_argument("--disable-blink-features=AutomationControlled")
    options.add_experimental_option("excludeSwitches", ["enable-automation"])
    options.add_experimental_option('useAutomationExtension', False)
    options.add_argument("--disable-extensions")
    options.add_argument("--no-sandbox")
    options.add_argument("--disable-dev-shm-usage")
    options.add_argument("--disable-gpu")
    options.add_argument("--window-size=1366,768")
    options.add_argument("user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36")

    self.driver = webdriver.Chrome(options=options)

    # Ocultar propriedade do webdriver
    self.driver.execute_script("Object.defineProperty(navigator, 'webdriver', {get: () => undefined,});")

    self.wait = WebDriverWait(self.driver, 20)
    logger.info("Driver do Chrome inicializado")

def random_delay(self, min_seconds=1, max_seconds=3):
    """Adiciona atrasos aleatórios entre ações"""
    delay = random.uniform(min_seconds, max_seconds)
    time.sleep(delay)

def search_google_maps(self, business_name):
    """Busca por empresa no Google Maps"""
    try:
        self.

Pronto para começar?

Aceda a todas as empresas do Google Maps, enriquecidas com emails e dados legais.

Experimente o IBLead gratuitamente