¿Por qué Scrape Google Maps Data?
Google Maps contiene la base de datos más completa de negocios locales en el mundo. Con más de 200 millones de empresas enumeradas, incluye nombres, direcciones, números de teléfono, sitios web, calificaciones, reseñas, horas de funcionamiento y fotos — todo estructurado y verificable.
Extracting this data programmatically enables valuable business applications:
- Generación líder: Crear listas específicas de empresas por industria y ubicación
- Análisis competitivo: Mapa ubicaciones de competidores, puntuaciones, y ver el sentimiento
- Investigación del mercado: Comprender densidad de negocio, patrones de precios y cobertura de servicios por área
- Auditoría local SEO: Verifique los listados de su negocio y compare contra los competidores
- Enriquecimiento de datos: Suplemento de datos CRM con información de negocios fresca
Esta guía cubre los enfoques técnicos para extraer los datos de Google Maps usando proxies. Para estrategias más amplias de raspado SERP, vea nuestra completo SERP raspado con guía proxies.
Google Places API vs Scraping
Antes de construir un rascador, considere si la API oficial de Google Places satisface sus necesidades.
| Factor | Lugares API | Scraping |
|---|---|---|
| Costo | 17 dólares por cada 1.000 solicitudes (después de la tarifa gratuita) | Proxy ancho de banda sólo (~$0.10-0.50 por 1.000 páginas) |
| Campos de datos | JSON estructurado, 20+ campos | Todos los datos visibles incluyendo el texto de los comentarios |
| Tasa límite | Límites estrictos por segundo y diario | Limitado por tamaño de la piscina proxy |
| Texto de revisión | Hasta 5 exámenes más relevantes | Todas las opiniones (con paginación) |
| Confiabilidad | Puntos finales oficiales y estables | Requiere mantenimiento de parser |
| Términos de servicio | Totalmente compatible | Revisar ToS y regulaciones locales |
| Escala | Gastos a escala | Costo-eficaz en volúmenes altos |
La API Places es la mejor opción para aplicaciones de pequeña escala y crítica de producción. Scraping es más rentable cuando necesita grandes conjuntos de datos, texto de revisión completa, o cuando los costos de API se vuelven prohibitivos.
Google Maps URL Estructura
Comprender los patrones URL de Google Maps es esencial para construir un rascador. Hay dos puntos de entrada principales:
Resultados de la búsqueda
Los resultados de búsqueda de Google Maps se pueden acceder a través de:
# Browser URL format
https://www.google.com/maps/search/restaurants+near+new+york
# URL parameters for search
https://www.google.com/maps/search/{query}/@{lat},{lng},{zoom}zDetalles del lugar
Las páginas de negocio individuales siguen este patrón:
# Place detail URL
https://www.google.com/maps/place/{business+name}/@{lat},{lng},{zoom}z/data=!{place_id}Construyendo un Google Maps Scraper
Google Maps es una aplicación JavaScript-heavy. A diferencia de la búsqueda regular de Google, las solicitudes HTTP simples a menudo regresan datos incompletos. Hay dos enfoques: analizar los datos JSON incrustados de la fuente de página, o utilizar un navegador sin cabeza.
Enfoque 1: Parsing Embedded JSON (Faster)
Las páginas de Google Maps contienen datos estructurados incrustados en la fuente HTML. Aquí está cómo extraerlo:
import requests
import json
import re
import time
import random
PROXY_URL = "http://USERNAME:PASSWORD@gate.proxyhat.com:8080"
def search_google_maps(query, location="us"):
"""Search Google Maps and extract business listings."""
proxies = {"http": PROXY_URL, "https": PROXY_URL}
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36",
"Accept-Language": "en-US,en;q=0.9",
"Accept": "text/html,application/xhtml+xml",
}
# Use the search URL format
search_url = f"https://www.google.com/maps/search/{query.replace(' ', '+')}"
response = requests.get(
search_url,
headers=headers,
proxies=proxies,
timeout=20,
)
response.raise_for_status()
# Extract embedded JSON data from the page
# Google Maps embeds data in a specific pattern
businesses = []
# Look for business data patterns in the response
# The data is typically in a JavaScript variable
patterns = re.findall(r'\["([^"]+)",null,null,null,null,null,null,null,"([^"]*)"', response.text)
# Alternative: parse the structured search results
# Google Maps returns data in protobuf-like JSON arrays
json_matches = re.findall(r'null,\["([^"]{5,80})"[^]]*?"([^"]*?(?:St|Ave|Rd|Blvd|Dr|Ln)[^"]*?)"', response.text)
for match in json_matches[:20]:
businesses.append({
"name": match[0],
"address": match[1] if len(match) > 1 else "",
})
return businesses
results = search_google_maps("restaurants near Times Square New York")
for b in results:
print(f"{b['name']} - {b['address']}")Enfoque 2: Navegador sin cabeza (Más fiable)
Para una extracción más fiable, utilice un navegador sin cabeza que renderice JavaScript:
from playwright.sync_api import sync_playwright
import json
import time
PROXY_URL = "http://USERNAME:PASSWORD@gate.proxyhat.com:8080"
def scrape_maps_with_browser(query):
"""Use Playwright to scrape Google Maps with full JS rendering."""
with sync_playwright() as p:
browser = p.chromium.launch(
headless=True,
proxy={
"server": "http://gate.proxyhat.com:8080",
"username": "USERNAME",
"password": "PASSWORD",
},
)
page = browser.new_page()
page.set_extra_http_headers({
"Accept-Language": "en-US,en;q=0.9",
})
# Navigate to Google Maps search
search_url = f"https://www.google.com/maps/search/{query.replace(' ', '+')}"
page.goto(search_url, wait_until="networkidle", timeout=30000)
# Wait for results to load
page.wait_for_selector('div[role="feed"]', timeout=10000)
# Scroll to load more results
feed = page.query_selector('div[role="feed"]')
for _ in range(5):
feed.evaluate("el => el.scrollBy(0, 1000)")
time.sleep(1.5)
# Extract business data from the results
businesses = []
items = page.query_selector_all('div[role="feed"] > div > div > a')
for item in items:
name = item.get_attribute("aria-label")
href = item.get_attribute("href")
if name and href:
businesses.append({
"name": name,
"url": href,
})
browser.close()
return businesses
results = scrape_maps_with_browser("coffee shops in San Francisco")
for b in results:
print(f"{b['name']}")
print(f" {b['url'][:80]}...")
print()Extracting Business Details
Una vez que tenga una lista de URLs de negocio, extraiga información detallada de cada listado:
import requests
import re
import json
PROXY_URL = "http://USERNAME:PASSWORD@gate.proxyhat.com:8080"
def extract_business_details(maps_url):
"""Extract detailed business info from a Google Maps place page."""
proxies = {"http": PROXY_URL, "https": PROXY_URL}
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36",
"Accept-Language": "en-US,en;q=0.9",
}
response = requests.get(maps_url, headers=headers, proxies=proxies, timeout=20)
text = response.text
business = {}
# Extract business name
name_match = re.search(r'Estrategia Proxy para Google Maps
Google Maps tiene sus propias protecciones antibot que requieren una estrategia proxy personalizada.
¿Por qué se requieren los proxies residenciales
Google Maps es particularmente agresivo acerca de bloquear IPs de centro de datos. La aplicación carga datos a través de múltiples llamadas API, y Google hace referencias a la IP en todas estas solicitudes. Proxies residenciales de ProxyHat son esenciales porque:
- Pasan cheques de reputación IP que Maps API llama hacer cumplir
- Apoyan el geo-objetivo a nivel de la ciudad para búsquedas específicas de ubicación
- Ellos mantienen el comportamiento de sesión consistente que Maps espera
Gestión del período de sesiones
A diferencia del raspado SERP regular donde gira IPs por solicitud, Google Maps funciona mejor con sesiones pegajosas:
# For Google Maps, use sticky sessions (same IP for a business detail page)
# ProxyHat supports session-based rotation via the proxy URL
# See docs.proxyhat.com for session configuration
# Rotating IP (for search listings)
ROTATING_PROXY = "http://USERNAME:PASSWORD@gate.proxyhat.com:8080"
# Sticky session (for individual place pages)
# Same session ID = same IP for the session duration
STICKY_PROXY = "http://USERNAME-session-maps123:PASSWORD@gate.proxyhat.com:8080"Tasa de limitación
Google Maps es más sensible a las solicitudes rápidas que la búsqueda regular de Google. Siga estas directrices:
- Espera 5-10 segundos entre las páginas de resultados de búsqueda
- Espera 3-5 segundos entre las cargas individuales de la página de lugar
- Limitar las solicitudes simultáneas para evitar patrones de explosión
- Use demoras más largas para la paginación de revisión (8-15 segundos entre páginas)
Node.js Implementation
const axios = require('axios');
const { HttpsProxyAgent } = require('https-proxy-agent');
const agent = new HttpsProxyAgent('http://USERNAME:PASSWORD@gate.proxyhat.com:8080');
async function searchGoogleMaps(query) {
const searchUrl = `https://www.google.com/maps/search/${encodeURIComponent(query)}`;
const { data } = await axios.get(searchUrl, {
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
'Accept-Language': 'en-US,en;q=0.9',
},
httpsAgent: agent,
timeout: 20000,
});
// Extract business names from the response
const businesses = [];
const namePattern = /\["([^"]{3,80})",null,null,null,null,null,null,null/g;
let match;
while ((match = namePattern.exec(data)) !== null) {
businesses.push({ name: match[1] });
}
return businesses;
}
async function main() {
const results = await searchGoogleMaps('plumbers in Chicago');
console.log(`Found ${results.length} businesses:`);
results.forEach((b, i) => console.log(`${i + 1}. ${b.name}`));
}
main().catch(console.error);Exámenes de Extracción en Escala
Las reseñas de Google Maps son uno de los puntos de datos más valiosos. Cada revisión incluye el nombre del revisor, calificación, texto, fecha y a veces fotos.
import requests
import re
import json
import time
import random
PROXY_URL = "http://USERNAME:PASSWORD@gate.proxyhat.com:8080"
def extract_reviews(place_id, num_reviews=50):
"""Extract reviews for a Google Maps place using the internal API."""
proxies = {"http": PROXY_URL, "https": PROXY_URL}
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36",
"Accept-Language": "en-US,en;q=0.9",
}
reviews = []
# Google Maps loads reviews via AJAX with pagination tokens
# The first page is loaded with the place page
maps_url = f"https://www.google.com/maps/place/?q=place_id:{place_id}"
response = requests.get(maps_url, headers=headers, proxies=proxies, timeout=20)
# Extract review data from embedded JSON
# Reviews are typically in arrays with rating, text, and author
review_pattern = re.findall(
r'"(\d)","([^"]{10,500})"[^]]*?"([^"]{2,50})"',
response.text
)
for match in review_pattern[:num_reviews]:
reviews.append({
"rating": int(match[0]),
"text": match[1],
"author": match[2],
})
return reviews
# Example: extract reviews
reviews = extract_reviews("ChIJN1t_tDeuEmsRUsoyG83frY4") # Example place ID
for r in reviews[:5]:
print(f"{'*' * r['rating']} by {r['author']}")
print(f" {r['text'][:100]}...")
print()Data Structuring and Storage
Organize scraped Google Maps data into a structured format for analysis:
import json
import csv
from datetime import datetime
def save_businesses(businesses, output_format="json"):
"""Save scraped business data in structured format."""
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
if output_format == "json":
filename = f"maps_data_{timestamp}.json"
with open(filename, "w") as f:
json.dump(businesses, f, indent=2, ensure_ascii=False)
elif output_format == "csv":
filename = f"maps_data_{timestamp}.csv"
if businesses:
keys = businesses[0].keys()
with open(filename, "w", newline="", encoding="utf-8") as f:
writer = csv.DictWriter(f, fieldnames=keys)
writer.writeheader()
writer.writerows(businesses)
print(f"Saved {len(businesses)} businesses to {filename}")
return filenameConsideraciones jurídicas y éticas
Los datos de Google Maps plantean importantes cuestiones jurídicas y éticas:
- Términos de servicio de Google: El ToS de Google prohíbe el raspado automático. Considere el uso de la API oficial Places para aplicaciones de producción
- Protección de datos: Los datos comerciales como números de teléfono y direcciones pueden estar sujetos a normas de protección de datos en algunas jurisdicciones
- Tasa límite: Incluso con proxies, sean respetuosos con la infraestructura de Google. Excesivo raspado afecta la calidad del servicio
- Frescura de datos: Siempre contemplen sus datos y refresquenlo regularmente, ya que la información de negocios cambia con frecuencia
Para aplicaciones críticas de la misión, considere la posibilidad de combinar la API oficial de Lugares para datos básicos con raspado selectivo para campos complementarios como texto de revisión. Este enfoque híbrido equilibra el cumplimiento de la integridad de los datos.
Para más información sobre las mejores prácticas de la web, vea nuestra guía completa de proxies de raspado web, y aprender sobre evitar bloques en nuestro Guía antibloqueoConsultar Documentación de ProxyHat para detalles de configuración proxy.






