перейти к содержанию

Как парсить сайт Yelp.com: полное руководство на 3000 слов по извлечению списков компаний, обзоров и других данных

Yelp — одна из крупнейших краудсорсинговых обзорных платформ в Интернете. Имея более 200 миллионов обзоров ресторанов, баров, салонов, магазинов и других предприятий в более чем 30 странах, он содержит кладезь данных для аналитиков, исследователей, предпринимателей и многих других.

Но можно ли извлечь эти данные с помощью веб-скрапинга? Абсолютно!

В этом подробном руководстве, состоящем из более чем 3000 слов, я поделюсь всем, что вам нужно для создания веб-скребка, который сможет извлекать огромные наборы данных из Yelp с помощью Python.

Вот краткий обзор того, что мы рассмотрим:

  • Настройка нашей среды парсинга веб-страниц Python
  • Поиск и извлечение всех компаний, соответствующих поисковому запросу.
  • Извлечение ключевых данных, таких как имя, адрес, номера телефонов, со страниц бизнес-профиля.
  • Извлечение всех отзывов о компании, включая рейтинги, данные пользователей и т. д.
  • Как избежать обнаружения ботов с помощью прокси, задержек и других уловок

Так что пристегнитесь и приступим к чистке!

Настройка среды веб-скрапинга Python

Прежде чем мы сможем очистить Yelp, нам нужно настроить среду Python с необходимыми зависимостями.

Нам нужно установить несколько ключевых пакетов:

Запросы – для отправки HTTP-запросов на серверы Yelp

КрасивыйСуп – для анализа и извлечения данных из HTML-страниц Yelp

Scrapy — (опционально) каркас для построения скребков

Я бы рекомендовал создать виртуальную среду перед установкой:

python -m venv scraping-env
source scraping-env/bin/activate

Теперь мы можем установить пакеты:

pip install requests beautifulsoup4 scrapy

Вот и все, что касается зависимостей. Нам также нужны действительные заголовки, чтобы серверы Yelp думали, что наши запросы поступают от реального браузера:

headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36"
}

Главное — убедительно User-Agent заголовок. Я бы рекомендовал менять несколько пользовательских агентов браузера для дальнейшей имитации реального трафика.

И мы готовы начать скрапинг!

Поиск компаний в Yelp

Наша первая задача — найти URL-адреса бизнес-профилей Yelp, которые можно парсить. Yelp не предоставляет общедоступный API или карту сайта, которую мы могли бы запросить для этого.

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

Давайте проанализируем типичный поисковый запрос:

https://www.yelp.com/search?find_desc=restaurants&find_loc=San+Francisco

В результате будет возвращен набор компаний, соответствующих нашим критериям поиска, с разбивкой на страницы. На каждой странице содержится 10 списков компаний.

Чтобы извлечь ВСЕ подходящие компании, нам необходимо:

  1. Откройте первую страницу, чтобы получить общее количество компаний.
  2. Перебрать все страницы, увеличивая start параметр

Вот как мы можем реализовать эту логику нумерации страниц в Python:

import requests
from urllib.parse import urlencode
from bs4 import BeautifulSoup

search_url = "https://www.yelp.com/search?"

params = {
  "find_desc": "restaurants",
  "find_loc": "San Francisco"  
}

search_url += urlencode(params)

print("Fetching first page")
first_page = requests.get(search_url, headers=headers)
soup = BeautifulSoup(first_page.content, "html.parser")

businesses = soup.select(".businessName") 
total = int(soup.select_one(".pagination-results-window").text.split()[0].replace(‘,‘, ‘‘))
print(f"Found {total} businesses")

# Calculate pages needed to cover all businesses
num_pages = math.ceil(total / 10)

print(f"Scraping {num_pages} pages...")

for page in range(0, num_pages):

  # Update start param 
  params["start"] = page * 10
  page_url = search_url + "&" + urlencode(params)

  # Fetch page
  print(f"Page {page+1}/{num_pages}")
  page = requests.get(page_url, headers=headers)

  # Extract businesses
  page_soup = BeautifulSoup(page.content, "html.parser")
  businesses.extend(page_soup.select(".businessName"))

print(f"Found {len(businesses)} businesses!")

Давайте разберем это:

  • Начнем с базового URL-адреса поиска и параметров поиска.
  • Откройте первую страницу, чтобы получить общее количество компаний.
  • Рассчитайте количество страниц, необходимое для охвата всех предприятий
  • Перебирать страницы, обновляя start остановить
  • На каждой странице извлекайте данные о компаниях и добавляйте их в основной список.

В моем тесте это было извлечено более 6,000 объявлений о ресторанах в Сан-Франциско – неплохо для 30 строк Python!

С некоторыми дополнительными настройками вы можете превратить его в бизнес-скребок Yelp для всего города или страны.

Парсинг страниц бизнес-профиля

Теперь, когда мы можем обнаружить URL-адреса бизнес-профилей, нашим следующим шагом будет посещение каждого из них и извлечение таких ключевых сведений, как:

  • Фамилия
  • Адрес
  • Номер телефона
  • Часы работы
  • Описание
  • Фото
  • И многое другое ...

Бизнес-страницы Yelp визуализируются динамически, но базовый HTML достаточно прост для анализа с помощью BeautifulSoup.

Давайте посмотрим на пример фрагмента:



<p>
  <strong>Phone:</strong> 
  415-387-2147
</p>

<p>
  <strong>Address:</strong>
  1345 9th Ave, San Francisco, CA 94122
</p>

<!-- And so on... -->

Мы можем извлечь каждый бит информации с помощью некоторых удачно расположенных селекторов CSS:

from bs4 import BeautifulSoup
import requests

business_url = "https://www.yelp.com/biz/burma-superstar-san-francisco"

page = requests.get(business_url, headers=headers)
soup = BeautifulSoup(page.content, "html.parser")

name = soup.select_one("h1").text
phone = soup.find("strong", string="Phone:").next_sibling.strip() 
address = soup.find("strong", string="Address:").next_sibling.strip()

hours = {}
for day in soup.select(".day-hours"):
   day_name = day.select_one(".day-name").text
   hours[day_name] = day.select_one(".hours").text

print(name)
print(phone) 
print(address)
print(hours)

# Burma Superstar
# 415-387-2147
# 1345 9th Ave, San Francisco, CA 94122
# {‘Mon‘: ‘11:30am–3pm, 5–9:30pm‘, ‘Tue‘: ‘11:30am–3pm, 5–9:30pm‘...}

Ключевые моменты:

  • Используйте select_one для извлечения отдельных элементов, таких как имя, телефон и т. д.
  • Для вложенных данных, таких как часы, выполните цикл и создайте словарь.
  • Префикс селекторов CSS с тегами и классами для уникальности.

С помощью этих строительных блоков очистки мы можем извлечь десятки полей с каждой страницы профиля в структурированный словарь Python или объект JSON.

Некоторые другие поля, которые вы можете рассмотреть для очистки, включают:

  • Теги категорий, такие как «Мексиканская», «Бранч» и т. д.
  • Теги кухни, такие как «Бургер», «Суши», «Кофе» и т. д.
  • Меры безопасности от COVID
  • Диапазон цен
  • Микрорайон
  • широта Долгота
  • И многое другое ...

Проявив здесь творческий подход, вы сможете создавать обширные наборы данных Yelp с сотнями полей для анализа при необходимости.

Сбор отзывов с бизнес-страниц Yelp

Отзывы — это жемчужина данных Yelp. Они предоставляют невероятную информацию о потребительских настроениях, тенденциях, демографии и многом другом.

К сожалению, отзывы не загружаются непосредственно в HTML. Они извлекаются динамически посредством вызовов JavaScript.

Нам нужно будет перехватить и имитировать эти запросы, чтобы получить данные проверки.

Откроем бизнес-страницу и будем следить за сетевыми запросами в инструментах браузера:

Yelp рассматривает сетевой запрос

Ага, мы видим, что отзывы загружаются по URL-адресу, например:

https://www.yelp.com/biz/{business_id}/reviews

где {business_id} уникален для каждого бизнеса. Мы можем извлечь его из HTML бизнес-страницы.

Отзывы разбиты на страницы с помощью start параметр. Итак, мы будем следовать той же стратегии нумерации страниц:

  1. Откройте первую страницу, чтобы узнать общее количество отзывов.
  2. Перебрать все страницы, увеличивая start

Вот скрипт для извлечения всех отзывов о бизнесе:

import json
import requests 

business_id = "WavvLdfdP6g8aZTtbBQHTw" # Extract this from HTML

review_url = f"https://www.yelp.com/biz/{business_id}/review_feed?rl=en&q=&sort_by=relevance_desc"

print("Fetching first page")
first_page = requests.get(review_url, headers=headers)
data = json.loads(first_page.text)

total = data["pagination"]["totalResults"]
print(f"Found {total} reviews")

reviews = data["reviews"]

for page in range(total//20 + 1): # 20 reviews per page

  print(f"Fetching page {page+1}/{math.ceil(total/20)}")
  next_page = f"{review_url}&start={page*20}"
  page_data = requests.get(next_page, headers=headers).json()

  reviews.extend(page_data["reviews"])

print(f"Scraped {len(reviews)} reviews!")

Бум! Теперь у нас есть полный корпус обзоров для бизнеса с такими данными, как:

{
   "id": "xAG4O7l-t1ubiIsO4cXMYg",
   "rating": 5,
   "user": {
      "id": "rpOyqD_893cqmDAtJLbdog",
      "profile_url": "https://www.yelp.com/user_details?userid=rpOyqD_893cqmDAtJLbdog",
      "name": "Sarah K.",
      "location": "Los Angeles, CA", 
      //...
   },
   "text": "This place is incredible! The sushi melts in your mouth and the...",
    //...
}

Анализ этих данных может дать убедительные сигналы о настроениях клиентов в зависимости от местоположения, демографии, типа кухни и т. д.

Как избежать обнаружения ботов

Теперь, когда мы создали парсеры для бизнеса и отзывов, пришло время собрать все это воедино.

Одна проблема — если мы начнем забрасывать серверы Yelp тысячами запросов, нас быстро заблокируют.

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

  • Ограничения на использование – ограничьте скорость запроса страниц.
  • CAPTCHA – предложите пользователям подтвердить, что они люди.
  • IP-баны – блокируйте неправомерные IP-адреса.

Вот несколько советов, как избежать блоков при очистке Yelp в больших масштабах:

Используйте прокси

Направляя трафик через большой пул частных IP-адресов, мы можем замаскировать скраперы и избежать простых блокировок IP-адресов.

Вот как использовать прокси с модулем Requests:

from proxy_list import proxies 

# Rotate proxy per request
proxy = random.choice(proxies)

requests.get(url, headers=headers, proxies={"http": proxy, "https": proxy}) 

Я бы порекомендовал иметь бассейн из по крайней мере, 10,000 прокси из разных диапазонов IP, чтобы быть в безопасности.

Добавить случайные задержки

Добавление различных задержек между запросами помогает имитировать органическое человеческое поведение:

from random import randint

# Add random delay between 2s and 6s
time.sleep(randint(2, 6))

Стремитесь в среднем к 3-5 секунд между страницами. Любое ускорение вызовет тревожные сигналы.

Используйте безголовый браузер

Для повышения анонимности вы можете использовать автономный браузер, например Selenium, для рендеринга JavaScript и обхода защиты.

Просто обязательно меняйте отпечаток браузера и прокси-сервер для каждого сеанса.

Решайте CAPTCHA с помощью 2Captcha

Если вы все же нажмете CAPTCHA, такие службы, как 2Captcha, могут автоматически решить ее и продолжить очистку.

Большинство сервисов взимают около 2 долларов США за 1000 решенных CAPTCHA, что выгодно для масштабирования крупных парсеров.

Соблюдайте ограничения учетной записи

Следите за страницей состояния вашего аккаунта. Если ваша скорость очистки слишком высока, Yelp может ввести временные ограничения на использование.

Ускоряйте выполнение запросов и отступайте, если ошибки указывают на то, что вы приближаетесь к порогу использования.

Скрапинг Yelp: следующие шаги

И это охватывает основные методы очистки списков компаний, профилей и обзоров Yelp!

Данные, которые вы можете извлечь, открывают массу возможностей:

  • Анализ потребительских настроений среди демографических групп
  • Отслеживайте тенденции и новые виды кухни
  • Создавайте прогнозные модели для факторов успеха бизнеса
  • Оптимизируйте собственное SEO и репутацию
  • Провести широкое исследование рынка
  • Определить рекламные возможности

Просто не забывайте соблюдать Условия обслуживания Yelp, ограничивать объем запросов и избегать извлечения каких-либо личных пользовательских данных.

Надеюсь, вы нашли это руководство полезным! Не стесняйтесь обращаться, если у вас есть еще вопросы.

Удачного соскабливания!

Теги:

Присоединяйтесь к беседе

Ваш электронный адрес не будет опубликован. Обязательные поля помечены * *