Зачем парсить данные Google Maps?
Google Maps содержит самую полную базу данных местных компаний в мире. С более чем 200 миллионами предприятий в базе, она включает названия, адреса, номера телефонов, веб-сайты, рейтинги, отзывы, часы работы и фотографии — всё структурировано и доступно для поиска.
Программное извлечение этих данных открывает ценные бизнес-применения:
- Лидогенерация: создание целевых списков компаний по отрасли и местоположению
- Конкурентный анализ: картирование локаций конкурентов, рейтингов и тональности отзывов
- Маркетинговые исследования: анализ плотности бизнесов, ценовых паттернов и покрытия услуг по районам
- Аудит локального SEO: проверка ваших бизнес-листингов и сравнение с конкурентами
- Обогащение данных: дополнение CRM-данных актуальной информацией о компаниях
Это руководство охватывает технические подходы к извлечению данных Google Maps с использованием прокси. Более широкие стратегии парсинга SERP описаны в нашем полном руководстве по парсингу SERP с прокси.
Google Places API vs парсинг
Прежде чем создавать парсер, оцените, подходит ли вам официальный Google Places API.
| Фактор | Places API | Парсинг |
|---|---|---|
| Стоимость | $17 за 1 000 запросов (сверх бесплатного лимита) | Только трафик прокси (~$0,10-0,50 за 1 000 страниц) |
| Поля данных | Структурированный JSON, 20+ полей | Все видимые данные, включая текст отзывов |
| Лимиты | Строгие посекундные и дневные ограничения | Ограничены только размером пула прокси |
| Текст отзывов | До 5 наиболее релевантных отзывов | Все отзывы (с пагинацией) |
| Надёжность | Официальные стабильные эндпоинты | Требует поддержки парсера |
| Условия использования | Полностью соответствует | Проверьте ToS и местное законодательство |
| Масштаб | Дорого при масштабировании | Экономично при больших объёмах |
Places API — лучший выбор для небольших критически важных приложений. Парсинг более экономичен при работе с большими датасетами, полными текстами отзывов или когда затраты на API становятся запретительными.
Структура URL Google Maps
Понимание паттернов URL Google Maps необходимо для создания парсера. Основные точки входа:
Результаты поиска
Результаты поиска Google Maps доступны по:
# 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}z
Детали объекта
Страницы отдельных компаний следуют паттерну:
# Place detail URL
https://www.google.com/maps/place/{business+name}/@{lat},{lng},{zoom}z/data=!{place_id}
Создание парсера Google Maps
Google Maps — приложение с интенсивным использованием JavaScript. В отличие от обычного поиска Google, простые HTTP-запросы часто возвращают неполные данные. Есть два подхода: парсинг встроенных JSON-данных из исходного кода страницы или использование headless-браузера.
Подход 1: Парсинг встроенного JSON (быстрее)
Страницы Google Maps содержат структурированные данные, встроенные в HTML-источник:
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']}")
Подход 2: Headless-браузер (надёжнее)
Для более надёжного извлечения используйте headless-браузер с рендерингом 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()
Извлечение деталей бизнеса
Получив список URL бизнесов, извлекайте подробную информацию из каждого листинга:
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'
Стратегия прокси для Google Maps
Google Maps имеет собственные антибот-защиты, требующие специализированной стратегии прокси.
Почему нужны резидентские прокси
Google Maps особенно агрессивно блокирует IP дата-центров. Приложение загружает данные через множественные API-вызовы, и Google перекрёстно проверяет IP по всем запросам. Резидентские прокси от ProxyHat необходимы, потому что:
- Они проходят проверки репутации IP, которые применяют API-вызовы Maps
- Поддерживают геотаргетинг на уровне города для локальных поисков
- Обеспечивают согласованное поведение сессии, которое ожидает Maps
Управление сессиями
В отличие от обычного парсинга SERP, где IP меняется с каждым запросом, Google Maps лучше работает с липкими сессиями:
# 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"
Ограничение скорости
Google Maps более чувствителен к быстрым запросам, чем обычный поиск Google. Рекомендации:
- Ожидайте 5-10 секунд между страницами результатов поиска
- Ожидайте 3-5 секунд между загрузками отдельных страниц
- Ограничивайте параллельные запросы для избежания пиковых паттернов
- Используйте большие задержки для пагинации отзывов (8-15 секунд между страницами)
Реализация на Node.js
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);
Извлечение отзывов в масштабе
Отзывы Google Maps — одни из наиболее ценных данных. Каждый отзыв включает имя автора, рейтинг, текст, дату и иногда фотографии.
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()
Структурирование и хранение данных
Организуйте собранные данные Google Maps в структурированный формат для анализа:
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 filename
Правовые и этические вопросы
Парсинг данных Google Maps поднимает важные правовые и этические вопросы:
- Условия использования Google: ToS Google запрещают автоматический парсинг. Для production-приложений рассмотрите использование официального Places API
- Защита данных: данные о бизнесах, такие как телефоны и адреса, могут подпадать под законы о защите данных
- Ограничение скорости: даже с прокси, будьте уважительны к инфраструктуре Google
- Актуальность данных: всегда помечайте данные временной меткой и регулярно обновляйте их
Для критически важных приложений рассмотрите комбинацию официального Places API для основных данных и точечного парсинга для дополнительных полей вроде текста отзывов. Такой гибридный подход балансирует соответствие правилам с полнотой данных.
Подробнее о лучших практиках веб-скрапинга читайте в нашем полном руководстве по прокси для веб-скрапинга и в руководстве по защите от блокировок. Настройку прокси смотрите в документации ProxyHat.






