Perché Scrape Google Maps Data?
Google Maps contiene il database più completo delle aziende locali del mondo. Con oltre 200 milioni di aziende quotate, comprende nomi, indirizzi, numeri di telefono, siti web, valutazioni, recensioni, orari operativi e foto — tutte strutturate e ricercabili.
L'estrazione di questi dati consente programmaticamente preziose applicazioni aziendali:
- Generazione di piombo: Costruire elenchi mirati delle imprese per settore e posizione
- Analisi competitiva: Mappa posizioni, valutazioni e recensioni dei concorrenti
- Ricerca di mercato: Comprendere densità di affari, modelli di prezzi e copertura di servizio per area
- Audit SEO locale: Verifica i tuoi annunci di business e confronta contro i concorrenti
- Arricchimento dei dati: Integrare i dati CRM con informazioni aziendali fresche
Questa guida copre gli approcci tecnici per estrarre i dati di Google Maps utilizzando i proxy. Per strategie di raschiamento SERP più ampie, vedere il nostro raschiatura completa SERP con guida proxy.
Google Places API vs Scraping
Prima di costruire un raschietto, considerare se l'API ufficiale di Google Places soddisfa le vostre esigenze.
| Fattore | Luoghi API | Scraping |
|---|---|---|
| Costo | $17 per 1.000 richieste (dopo tier gratuito) | Larghezza di banda proxy solo (~$0.10-0.50 per 1.000 pagine) |
| Campi dati | Strutturato JSON, 20+ campi | Tutti i dati visibili compreso il testo delle recensioni |
| Limiti di tasso | Limiti rigorosi per secondo e giornaliero | Limitato per dimensione del pool proxy |
| Testo della recensione | Fino a 5 recensioni più rilevanti | Tutte le recensioni (con paginazione) |
| Affidabilità | Punti finali ufficiali e stabili | Richiede manutenzione parser |
| Termini di servizio | Completamente conforme | Check ToS e regolamenti locali |
| Scala | Economico in scala | Costo-efficace ad alti volumi |
L'API Places è la scelta migliore per applicazioni di piccole e medie dimensioni. Scraping è più conveniente quando avete bisogno di grandi set di dati, testo di revisione completo, o quando i costi API diventano proibitivi.
Google Maps URL Struttura
La comprensione dei modelli di URL di Google Maps è essenziale per la costruzione di un raschietto. Ci sono due punti di ingresso principali:
Risultati della ricerca
I risultati di ricerca di Google Maps possono essere accessibili tramite:
# 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}zLuogo dettagli
Le singole pagine aziendali seguono questo modello:
# Place detail URL
https://www.google.com/maps/place/{business+name}/@{lat},{lng},{zoom}z/data=!{place_id}Costruire un Google Maps Scraper
Google Maps è un'applicazione JavaScript-heavy. A differenza di Google Search regolare, semplici richieste HTTP spesso restituiscono dati incompleti. Ci sono due approcci: l'analisi dei dati JSON incorporati dalla sorgente di pagina, o l'utilizzo di un browser senza testa.
Approccio 1: Parsing Embedded JSON (Faster)
Le pagine di Google Maps contengono dati strutturati incorporati nella sorgente HTML. Ecco come estrarlo:
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']}")Approccio 2: Browser senza testa (Più affidabile)
Per un'estrazione più affidabile, utilizzare un browser senza testa che rende 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()Estrazione di dettagli aziendali
Una volta che hai un elenco di URL aziendali, estrarre informazioni dettagliate da ogni elenco:
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'Strategia proxy per Google Maps
Google Maps ha le proprie protezioni anti-bot che richiedono una strategia proxy su misura.
Perché i proxy residenziali sono necessari
Google Maps è particolarmente aggressivo nel bloccare gli IP del datacenter. L'applicazione carica i dati attraverso più chiamate API, e Google cross-references l'IP attraverso tutte queste richieste. Processi residenziali da ProxyHat sono essenziali perché:
- Passano i controlli della reputazione IP che le chiamate API Maps fanno rispettare
- Supportano geo-targeting di livello città per ricerche specifiche per la posizione
- Mantengono il comportamento di sessione coerente che Maps si aspetta
Gestione delle sessioni
A differenza della raschiatura SERP regolare in cui si ruotano IP per richiesta, Google Maps funziona meglio con sessioni appiccicose:
# 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"Limitamento del tasso
Google Maps è più sensibile alle richieste rapide che alla ricerca regolare di Google. Seguire queste linee guida:
- Attendere 5-10 secondi tra le pagine dei risultati di ricerca
- Attendere 3-5 secondi tra i singoli carichi di pagina del luogo
- Limitare le richieste concurrent per evitare i modelli di scoppio
- Utilizzare ritardi più lunghi per la paginazione di revisione (8-15 secondi tra pagine)
Node.js Attuazione
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);Estrarre recensioni su Scale
Google Maps recensioni sono tra i punti di dati più preziosi. Ogni recensione include il nome del recensore, la valutazione, il testo, la data e a volte le foto.
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()Struttura e conservazione dei dati
Organizza i dati di Google Maps raschiati in un formato strutturato per l'analisi:
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 filenameConsiderazioni giuridiche ed etiche
Scraping dati Google Maps solleva importanti questioni legali ed etiche:
- Termini di servizio di Google: Google's ToS proibisce la raschiatura automatizzata. Considerare l'utilizzo dell'API di Luoghi ufficiali per le applicazioni di produzione
- Protezione dei dati: Dati aziendali come numeri di telefono e indirizzi possono essere soggetti alle normative sulla protezione dei dati in alcune giurisdizioni
- Tasso di limitazione: Anche con i proxy, essere rispettoso dell'infrastruttura di Google. La raschiatura eccessiva colpisce la qualità del servizio
- Freschezza dei dati: Sempre timestamp i tuoi dati e aggiornarlo regolarmente, in quanto le informazioni aziendali cambiano frequentemente
Per applicazioni mission-critical, prendere in considerazione di combinare l'API di Luoghi ufficiali per i dati di base con la demolizione mirata per campi aggiuntivi come il testo di revisione. Questo approccio ibrido bilancia il rispetto della completezza dei dati.
Per ulteriori informazioni su web scraping best practice, vedere il nostro guida completa ai proxy di raschiamento web, e imparare a evitare blocchi nel nostro guida anti-bloccaggio. Consultare il Documentazione ProxyHat per i dettagli di configurazione del proxy.






