вступление

В этом сообщении блога мы рассмотрим процесс извлечения данных из результатов Google Maps Locals с использованием Python. Вы можете посмотреть полный код в онлайн-IDE (Replit).

Если вы предпочитаете формат видео, у нас есть специальное видео, в котором показано, как это сделать: Скрапинг локальных результатов Google Maps с помощью Python и SerpApi.

Что будет очищено

Зачем использовать API?

Есть несколько причин, по которым может использоваться API, в частности наша:

  • Нет необходимости создавать парсер с нуля и поддерживать его.
  • Обходите блокировки от Google: разгадывайте CAPTCHA или разгадывайте IP-блокировки.
  • Платите за прокси и решатели CAPTCHA.
  • Не нужно использовать автоматизацию браузера.

SerpApi обрабатывает все на бэкэнде с быстрым временем отклика менее ~ 2,5 секунд (~ 1,2 секунды со скоростью Ludicrous) на запрос и без автоматизации браузера, что становится намного быстрее. Время отклика и показатели статуса отображаются на странице Статус SerpApi.

Полный код

Если вам просто нужно извлечь все доступные данные о месте, то мы можем создать пустой list и затем extend извлечь данные к нему:

from serpapi import GoogleSearch
from urllib.parse import urlsplit, parse_qsl
import os, json

params = {
    # https://docs.python.org/3/library/os.html#os.getenv
    'api_key': os.getenv('API_KEY'),        # your serpapi api
    'engine': 'google_maps',                # SerpApi search engine 
    'q': 'coffee',                          # query
    'll': '@40.7455096,-74.0083012,15.1z',  # GPS coordinates
    'type': 'search',                       # list of results for the query
    'hl': 'en',                             # language
    'start': 0,                             # pagination
}

search = GoogleSearch(params)               # where data extraction happens on the backend

local_results = []

# pagination
while True:
    results = search.get_dict()             # JSON -> Python dict

    # title = results['local_results']['title']

    if 'next' in results.get('serpapi_pagination', {}):
        search.params_dict.update(dict(parse_qsl(urlsplit(results.get('serpapi_pagination', {}).get('next')).query)))
    else:
        break

    local_results.extend(results['local_results'])

print(json.dumps(local_results, indent=2, ensure_ascii=False))

Подготовка

Установить библиотеку:

pip install google-search-results

google-search-results — это пакет API SerpApi.

Код Пояснение

Импортировать библиотеки:

from serpapi import GoogleSearch
from urllib.parse import urlsplit, parse_qsl
import os, json
  • GoogleSearchдля парсинга и парсинга результатов Google с помощью библиотеки веб-парсинга SerpApi.
  • urlsplitthis обычно следует использовать вместо urlparse(), если требуется более новый синтаксис URL, позволяющий применять параметры к каждому сегменту части пути URL (см. RFC 2396).
  • parse_qslдля разбора строки запроса, заданной в качестве строкового аргумента.
  • osчтобы вернуть значение переменной среды (ключ SerpApi API).
  • jsonдля преобразования извлеченных данных в объект JSON.

В начале кода определяются параметры для генерации URL. Если вы хотите передать URL-адресу другие параметры, вы можете сделать это с помощью словаря params:

params = {
    # https://docs.python.org/3/library/os.html#os.getenv
    'api_key': os.getenv('API_KEY'),        # your serpapi api
    'engine': 'google_maps',                # SerpApi search engine 
    'q': 'coffee',                          # query
    'll': '@40.7455096,-74.0083012,15.1z',  # GPS coordinates
    'type': 'search',                       # list of results for the query
    'hl': 'en',                             # language
    'start': 0,                             # pagination
}
  • api_keyParameter определяет используемый закрытый ключ SerpApi.
  • engineУстановите для параметра значение google_maps, чтобы использовать механизм Google Maps API.
  • qПараметр определяет запрос, который вы хотите найти. Вы можете использовать все, что вы использовали бы в обычном поиске Google Maps.
  • Параметр ll определяет GPS-координаты места, где вы хотите применить ваш q (запрос).
  • Параметр type определяет тип поиска, который вы хотите произвести. search - возвращает список результатов для заданного параметра q.
  • hlПараметр определяет язык, используемый для поиска Google Maps. Это двухбуквенный код языка. (например, en для английского, es для испанского или fr для французского). Перейдите на страницу языков Google для получения полного списка поддерживаемых языков Google.
  • startParameter определяет смещение результата. Он пропускает заданное количество результатов. Он используется для разбиения на страницы. (например, 0 (по умолчанию) — первая страница результатов, 20 — вторая страница результатов, 40 — третья страница результатов и т. д.).

📌Примечание: параметры q и ll необходимы только в том случае, если type установлено на search.

Дополнительно хочу рассказать о значении, которое записывается в параметр ll. Значение должно быть построено в следующей последовательности:

@ + latitude + , + longitude + , + zoom

Это сформирует строку, которая выглядит следующим образом:

@40.7455096,-74.0083012,15.1z

Параметр zoom является необязательным, но рекомендуется для более высокой точности (он варьируется от 3z, карта полностью уменьшена до 21z, карта полностью увеличена).

Вы можете найти значение параметра ll в URL нужных вам локальных результатов: https://www.google.com/maps/search/coffee/@40.7455096,-74.0083012,15z?hl=en

Затем мы создаем объект search, в котором данные извлекаются из серверной части SerpApi:

search = GoogleSearch(params)   # where data extraction happens on the backend

Объявление списка local_results, куда будут добавлены извлеченные данные:

local_results = []

Необходимо извлечь все локальные результаты с учетом разбиения на страницы.

В цикле while мы получаем данные из JSON и записываем их в словарь results:

while True:
    results = search.get_dict()     # JSON -> Python dict

Затем мы проверяем, существует ли следующая страница. Если это так, то мы обновляем данные JSON в объекте search для следующей страницы. В противном случае мы break цикл:

if 'next' in results.get('serpapi_pagination', {}):
    search.params_dict.update(dict(parse_qsl(urlsplit(results.get('serpapi_pagination', {}).get('next')).query)))
else:
    break

Расширение списка local_results новыми данными с этой страницы:

local_results.extend(results['local_results'])

После получения всех данных они выводятся в формате JSON:

print(json.dumps(local_results, indent=2, ensure_ascii=False))

Выход

[
  {
    "position": 1,
    "title": "Stumptown Coffee Roasters",
    "place_id": "ChIJT2h1HKZZwokR0kgzEtsa03k",
    "data_id": "0x89c259a61c75684f:0x79d31adb123348d2",
    "data_cid": "8778389626880739538",
    "reviews_link": "https://serpapi.com/search.json?data_id=0x89c259a61c75684f%3A0x79d31adb123348d2&engine=google_maps_reviews&hl=en",
    "photos_link": "https://serpapi.com/search.json?data_id=0x89c259a61c75684f%3A0x79d31adb123348d2&engine=google_maps_photos&hl=en",
    "gps_coordinates": {
      "latitude": 40.7457399,
      "longitude": -73.9882272
    },
    "place_id_search": "https://serpapi.com/search.json?data=%214m5%213m4%211s0x89c259a61c75684f%3A0x79d31adb123348d2%218m2%213d40.7457399%214d-73.9882272&engine=google_maps&google_domain=google.com&hl=en&start=0&type=place",
    "rating": 4.5,
    "reviews": 1371,
    "price": "$$",
    "type": "Coffee shop",
    "address": "18 W 29th St, New York, NY 10001",
    "open_state": "Closed ⋅ Opens 6:30AM Fri",
    "hours": "Closed ⋅ Opens 6:30AM Fri",
    "operating_hours": {
      "thursday": "7AM–2PM",
      "friday": "6:30AM–5PM",
      "saturday": "7AM–5PM",
      "sunday": "7AM–5PM",
      "monday": "6:30AM–5PM",
      "tuesday": "6:30AM–5PM",
      "wednesday": "6:30AM–5PM"
    },
    "phone": "(855) 711-3385",
    "website": "https://www.stumptowntogo.com/",
    "description": "Coffee bar serving direct-trade java. Coffee bar chain offering house-roasted direct-trade coffee, along with brewing gear & whole beans",
    "service_options": {
      "dine_in": true,
      "takeout": true,
      "delivery": false
    },
    "thumbnail": "https://lh5.googleusercontent.com/p/AF1QipMg90Zc0FekBv9vaTYG4nVOf_RoSYAhVklxGxmg=w80-h106-k-no"
  },
  ... other local results
]

📌Примечание: вы можете просмотреть детскую площадку или проверить вывод. Таким образом, вы сможете понять, какие ключи вы можете использовать в этой структуре JSON, чтобы получить нужные вам данные.

Ссылки

Первоначально опубликовано на SerpApi: https://serpapi.com/blog/using-google-maps-local-results-from-serpapi/

Присоединяйтесь к нам в Твиттере | "YouTube"

Добавьте Запрос функции💫 или Ошибку🐞