CoderCastrov logo
CoderCastrov
Парсер

Парсинг Expedia с помощью Python

Парсинг Expedia с помощью Python
просмотров
8 мин чтение
#Парсер

Как вы знаете, Expedia - это крупное онлайн-туристическое агентство, через которое можно бронировать отели, авиабилеты, путевки и т. д. Ежедневно на сайт Expedia заходит огромное количество пользователей. Но зачем парсить Expedia? Парсинг Expedia позволяет собирать и сравнивать цены на авиабилеты, отели, аренду автомобилей и другие туристические услуги.

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

В этом руководстве мы собираемся парсить цены на отели с помощью Python и Selenium.


Настройка предварительных требований для парсинга Expedia

В этом руководстве мы будем использовать Python 3.x. Надеюсь, у вас уже установлена Python на вашем компьютере. Если нет, то вы можете скачать его здесь.

Затем создайте папку, в которой будете хранить скрипт на Python. Затем создайте файл на Python, в котором будете писать код.

mkdir Expedia

Затем внутри этой папки создайте файл на Python, который будет использоваться для написания кода на Python для парсинга Expedia.

Установка

Для парсинга Expedia мы будем использовать некоторые сторонние библиотеки.

pip install selenium
  1. [BeautifulSoup](https://www.crummy.com/software/BeautifulSoup/bs4/doc/) - Он будет использоваться для разбора сырого HTML. Вы можете установить его следующим образом.
pip install beautifulsoup4
  1. Нам также нужен веб-драйвер Chromium, чтобы отображать Expedia. Вы можете установить Chromium отсюда. Помните, что версия веб-драйвера Chromium и вашего браузера Chrome должны быть одинаковыми, иначе будет постоянно возникать ошибка.

Вы можете скачать его здесь.

Настройка и тестирование

Давайте сначала создадим небольшую настройку и отобразим веб-сайт. Это просто для того, чтобы убедиться, что позже у нас все работает нормально. Целевым URL для этого руководства будет страница отеля на Expedia.

from bs4 import BeautifulSoup
from selenium import webdriver
import time


PATH = 'C:\Program Files (x86)\chromedriver.exe'



l=list()
o={}

target_url = "https://www.expedia.com/Cansaulim-Hotels-Heritage-Village-Resort-Spa-Goa.h2185154.Hotel-Information?=one-key-onboarding-dialog&chkin=2023-05-13&chkout=2023-05-14&destType=MARKET&destination=Goa%2C%20India%20%28GOI-Dabolim%29&latLong=15.383019%2C73.838253&regionId=6028089&rm1=a2"

driver=webdriver.Chrome(PATH)

driver.get(target_url)


time.sleep(5)

resp = driver.page_source
driver.close()
print(resp)

Код довольно простой, но позвольте мне разобрать его для вас.

  • Первые три строки импортируют необходимые модули, включая BeautifulSoup для парсинга HTML-документов, Selenium WebDriver для автоматизации веб-браузеров и time для приостановки выполнения программы на определенное время.
  • Следующая строка устанавливает путь к исполняемому файлу Chrome WebDriver. WebDriver необходим для запуска браузера Chrome для парсинга веб-страниц.
  • Следующие две строки определяют пустой список l и пустой словарь o, которые будут использоваться позже в программе для хранения полученных данных.
  • Переменная target_url содержит URL целевой страницы Expedia, которую мы хотим спарсить. Она включает даты заезда и отъезда, пункт назначения и другие параметры, необходимые для выполнения поиска отелей.
  • Строка webdriver.Chrome(PATH) запускает браузер Chrome с помощью исполняемого файла Chrome WebDriver. Переменная PATH указывает расположение исполняемого файла Chrome WebDriver.
  • Строка driver.get(target_url) загружает целевой URL в браузер Chrome.
  • Строка time.sleep(5) приостанавливает выполнение программы на 5 секунд, чтобы веб-страница успела загрузиться и отобразиться.
  • Строка driver.page_source получает HTML-код загруженной веб-страницы.
  • Строка driver.close() закрывает браузер Chrome.
  • Наконец, строка print(resp) выводит полученный HTML-код в консольный вывод.

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

hotel_page

Как вы можете видеть, вверху есть название отеля, а внизу вы можете найти несколько типов номеров и их цены. Теперь давайте запустим наш код и посмотрим, что появится на экране.

rendered_page

Это появится на вашем экране Chrome Webdriver после запуска кода. Заметили разницу? Цены не видны, когда мы запускаем код. Почему так? Причина в HTTP-заголовках. При парсинге Expedia нам нужно передавать несколько заголовков, таких как User-Agent, Accept, Accept-Encoding, Referer и т. д.

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

Итак, внесем изменения в код, а затем запустим его.

from bs4 import BeautifulSoup
from selenium import webdriver
import time


PATH = 'C:\Program Files (x86)\chromedriver.exe'



options = webdriver.ChromeOptions()

options.add_argument('user-agent=Mozilla/5.0 (Linux; Android 11; SM-G991B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Mobile Safari/537.36')
options.add_argument('accept-encoding=gzip, deflate, br')
options.add_argument('accept=text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7')
options.add_argument('referer=https://www.expedia.com/')
options.add_argument('upgrade-insecure-requests=1')



l=list()
o={}

target_url = "https://www.expedia.com/Cansaulim-Hotels-Heritage-Village-Resort-Spa-Goa.h2185154.Hotel-Information?=one-key-onboarding-dialog&chkin=2023-05-13&chkout=2023-05-14&destType=MARKET&destination=Goa%2C%20India%20%28GOI-Dabolim%29&latLong=15.383019%2C73.838253&regionId=6028089"

driver=webdriver.Chrome(PATH,options=options)

driver.get(target_url)

# driver.maximize_window()
time.sleep(5)

resp = driver.page_source
driver.close()
print(resp)

Мы создали новый экземпляр webdriver.ChromeOptions(), который является классом, позволяющим настраивать параметры для браузера Chrome. Затем мы добавили пять заголовков с помощью метода add_argument(). add_argument() помогает нам добавить аргументы командной строки в параметры.

chrome_options

Как вы можете видеть, мы смогли отобразить полную страницу Expedia, добавив пользовательские заголовки. Теперь давайте решим, что именно мы хотим спарсить.

Что именно мы собираем из Expedia?

Всегда лучше заранее решить, какие данные вы хотите извлечь из исходных данных.

Для этого учебника мы собираем:

  • Название отеля
  • Тип номера
  • Цена до налогов
  • Цена после налогов

Я выделил эти данные на приведенном выше изображении. Если у вас возникнут какие-либо вопросы, обратитесь к нему.

Парсинг Expedia.com

Прежде чем мы будем парсить текст, нам нужно определить их позицию внутри DOM. Продолжая с предыдущего кода, мы сначала найдем местоположение каждого элемента, а затем извлечем их с помощью BS4. Мы будем использовать методы .find() и .find_all(), предоставляемые BS4. Если вы хотите узнать больше о BS4, вы можете обратиться к Руководству по BeautifulSoup.

Начнем с названия.

Таким образом, название хранится внутри тега h1. Парсить это будет очень просто.

soup=BeautifulSoup(resp,'html.parser')

try:
    o["hotel"]=soup.find("h1").text
except:
    o["hotel"]=None
  • Здесь мы создали объект BeautifulSoup. Результирующий объект soup - это экземпляр класса BeautifulSoup, который предоставляет несколько методов для поиска и манипулирования разобранным HTML-документом.
  • Затем, используя метод .find() BS4, мы извлекаем текст.

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

Как вы можете видеть, этот полный раздел комнат находится внутри тега div с атрибутом data-stid, значение которого - section-room-list.

allOffers = soup.find("div",{"data-stid":"section-room-list"})

Внутри этого вы заметите, что все эти отдельные детали комнат хранятся внутри тега div с классом uitk-layout-grid-item.

Offers = allOffers.find_all("div",{"class":"uitk-layout-grid-item"})

Теперь будет намного проще спарсить текст типа комнаты.

Вы заметите, что каждый текст типа комнаты хранится внутри тега div с class uitk-spacing-padding-small-blockend-half, и этот элемент находится внутри тега div с классом uitk-spacing-padding-blockstart-three.

Поскольку комнаты могут быть несколько, нам нужно запустить цикл for, чтобы получить доступ ко всем деталям комнаты. Все, что нам нужно сделать, это запустить цикл for, который будет перебирать список Offers.

for Offer in Offers:
    try:
        o["room-type"]=Offer.find("div",{"class":"uitk-spacing-padding-blockstart-three"}).find("div",{"class":"uitk-spacing-padding-small-blockend-half"}).text
    except:
        o["room-type"]=None

Теперь оба ценника хранятся внутри тега div с атрибутом data-test-id, значение которого - price-summary-message-line. Мы просто должны найти все такие элементы внутри каждого блока комнаты. Для этого я буду использовать метод find_all() внутри цикла.

price_arr=Offer.find_all("div",{"data-test-id":"price-summary-message-line"})

try:
        o["price_before_tax"]=price_arr[0].find("span").text
except:
        o["price_before_tax"]=None


try:
        o["price_after_tax"]=price_arr[1].text.replace(" total","")
except:
        o["price_after_tax"]=None


l.append(o)

o={}

Наконец, мы смогли спарсить все данные из Expedia.


Полный код

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

from bs4 import BeautifulSoup
from selenium import webdriver
import time


PATH = 'C:\Program Files (x86)\chromedriver.exe'



options = webdriver.ChromeOptions()

options.add_argument('user-agent=Mozilla/5.0 (Linux; Android 11; SM-G991B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Mobile Safari/537.36')
options.add_argument('accept-encoding=gzip, deflate, br')
options.add_argument('accept=text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7')
options.add_argument('referer=https://www.expedia.com/')
options.add_argument('upgrade-insecure-requests=1')



l=list()
o={}

target_url = "https://www.expedia.com/Cansaulim-Hotels-Heritage-Village-Resort-Spa-Goa.h2185154.Hotel-Information?=one-key-onboarding-dialog&chkin=2023-05-13&chkout=2023-05-14&destType=MARKET&destination=Goa%2C%20India%20%28GOI-Dabolim%29&latLong=15.383019%2C73.838253&regionId=6028089"

driver=webdriver.Chrome(PATH,options=options)

driver.get(target_url)

# driver.maximize_window()
time.sleep(5)

resp = driver.page_source
driver.close()

soup=BeautifulSoup(resp,'html.parser')

allOffers = soup.find("div",{"data-stid":"section-room-list"})

Offers = allOffers.find_all("div",{"class":"uitk-layout-grid-item"})

try:
    o["hotel"]=soup.find("h1").text
except:
    o["hotel"]=None
l.append(o)
o={}
for Offer in Offers:
    price_arr=Offer.find_all("div",{"data-test-id":"price-summary-message-line"})
    try:
        o["room-type"]=Offer.find("div",{"class":"uitk-spacing-padding-blockstart-three"}).find("div",{"class":"uitk-spacing-padding-small-blockend-half"}).text
    except:
        o["room-type"]=None




    try:
        o["price_before_tax"]=price_arr[0].find("span").text
    except:
        o["price_before_tax"]=None


    try:
        o["price_after_tax"]=price_arr[1].text.replace(" total","")
    except:
        o["price_after_tax"]=None

    l.append(o)

    o={}

print(l)

После запуска этого кода вы получите следующий результат в консоли.

Использование Scrapingdog для парсинга Expedia

Преимущества использования API Scrapingdog для парсинга веб-страниц следующие:

  • Вам больше не нужно управлять заголовками.
  • Каждый запрос будет проходить через новый IP-адрес. Это обеспечивает анонимность вашего IP.
  • Наше API автоматически повторит запрос, если первый не удался.
  • Scrapingdog использует резиденциальные прокси для парсинга Expedia. Это увеличивает успешность парсинга Expedia или любого другого подобного веб-сайта.

Вам нужно зарегистрироваться для бесплатного аккаунта, чтобы начать использовать его. Вам потребуется всего 10 секунд, чтобы начать работу с Scrapingdog.

После регистрации вы будете перенаправлены на свою панель управления. Панель управления будет выглядеть примерно так.

Вам нужно использовать свой собственный API-ключ.

Теперь вы можете вставить ссылку на страницу Expedia слева, а затем выбрать JS Rendering как Yes. После этого нажмите на Copy Code справа. Теперь используйте этот API в своем скрипте для парсинга Expedia.

from bs4 import BeautifulSoup
import requests

l=list()
o={}

resp=requests.get('https://api.scrapingdog.com/scrape?api_key=xxxxxxxxxxxxxxxxxxxxxxxxxx&url=https://www.expedia.com/Cansaulim-Hotels-Heritage-Village-Resort-Spa-Goa.h2185154.Hotel-Information?=one-key-onboarding-dialog&chkin=2023-05-13&chkout=2023-05-14&destType=MARKET&destination=Goa%2C%20India%20%28GOI-Dabolim%29&latLong=15.383019%2C73.838253&regionId=6028089')

soup=BeautifulSoup(resp.text,'html.parser')

allOffers = soup.find("div",{"data-stid":"section-room-list"})

Offers = allOffers.find_all("div",{"class":"uitk-layout-grid-item"})

try:
    o["hotel"]=soup.find("h1").text
except:
    o["hotel"]=None
l.append(o)
o={}
for Offer in Offers:
    price_arr=Offer.find_all("div",{"data-test-id":"price-summary-message-line"})
    try:
        o["room-type"]=Offer.find("div",{"class":"uitk-spacing-padding-blockstart-three"}).find("div",{"class":"uitk-spacing-padding-small-blockend-half"}).text
    except:
        o["room-type"]=None

    try:
        o["price_before_tax"]=price_arr[0].find("span").text
    except:
        o["price_before_tax"]=None

    try:
        o["price_after_tax"]=price_arr[1].text.replace(" total","")
    except:
        o["price_after_tax"]=None

    l.append(o)
    o={}

print(l)

С помощью Scrapingdog вам не нужно беспокоиться о драйверах Chrome. Все это будет автоматически обработано для вас. Вам просто нужно сделать обычный GET-запрос к API.

С помощью Scrapingdog вы сможете парсить Expedia с невероятной скоростью без блокировки.

Заключение

В этом руководстве мы увидели, какую важную роль играют заголовки при парсинге веб-сайтов, таких как сам Expedia. Используя Python и Selenium, мы смогли загрузить полный HTML-код, а затем, используя BS4, мы смогли разобрать данные.

Вы можете использовать Makcorps Hotel API, чтобы получить цены на отели более чем в 200 OTA (включая Expedia).

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

Дополнительные ресурсы

Вот несколько дополнительных ресурсов, которые могут быть полезными во время вашего путешествия по парсингу веб-сайтов: