Парсинг данных Google Maps: бизнес-листинги и отзывы

Узнайте, как парсить Google Maps для получения бизнес-данных: названий, адресов, рейтингов и отзывов. Сравнение API и парсинга, стратегии прокси и примеры кода на Python и Node.js.

Парсинг данных Google Maps: бизнес-листинги и отзывы

Зачем парсить данные 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.

Готовы начать?

Доступ к более чем 50 млн резидентных IP в 148+ странах с AI-фильтрацией.

Смотреть ценыРезидентные прокси
← Вернуться в Блог