Как вы знаете, Expedia — это большое туристическое онлайн-агентство, через которое вы можете бронировать отели, авиабилеты, туристические пакеты и т. д. Ежедневно оно получает очень большой объем трафика. Но зачем копать Expedia? С помощью парсинга Expedia вы можете собирать и сравнивать цены на авиабилеты, отели, аренду автомобилей и другие туристические услуги.
Сбор данных с Expedia.com может предоставить большие объемы структурированных и неструктурированных данных, которые можно анализировать с помощью методов обработки данных, чтобы получить представление о поведении, предпочтениях и моделях клиентов. Эти данные можно использовать для улучшения маркетинговых стратегий, ориентации на клиентов и общей эффективности бизнеса.
В этом уроке мы собираемся извлечь цены на отели из Expedia, используя Python и Selenium.
Настройка предварительных условий для парсинга Expedia
В этом уроке мы будем использовать Python 3.x
. Надеюсь, вы уже установили Python на свой компьютер. Если нет, то вы можете скачать его здесь.
Затем создайте папку, в которой вы будете хранить скрипт Python. Затем создайте файл Python, в котором вы будете писать код.
mkdir Expedia
Затем внутри этой папки создайте файл Python, который будет использоваться для написания кода Python для парсинга Expedia.
Монтаж
Для парсинга Expedia мы возьмем поддержку некоторых сторонних библиотек.
Selenium
- Selenium — это популярный инструмент веб-скрейпинга для автоматизации веб-браузеров. Он часто используется для взаимодействия с динамическими веб-сайтами, где содержимое веб-сайта изменяется в зависимости от взаимодействия с пользователем или других событий. Вы можете установить его так.
pip install selenium
2. BeautifulSoup
- Будет использоваться для разбора необработанного HTML. Вы можете установить его так.
pip install beautifulsoup4
3. Нам также нужен Chromium
веб-драйвер для рендеринга Expedia. Вы можете установить хром отсюда. Не забудьте сохранить одну и ту же версию веб-драйвера 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®ionId=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 для просмотра веб-страниц.
- Следующие две строки определяют пустые
list l
и пустыеdictionary 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 на вывод консоли.
Надеюсь, теперь у вас есть идея. Прежде чем мы запустим этот код, давайте посмотрим, как на самом деле выглядит страница в нашем браузере.
Как видите, вверху указано название отеля, а внизу вы можете найти несколько типов номеров и их цены. Теперь давайте запустим наш код и посмотрим, что появится на нашем экране.
Это появится на экране 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®ionId=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()
помогает нам добавлять аргументы командной строки к параметрам
Как видите, нам удалось отобразить полную страницу Expedia, добавив пользовательские заголовки. Теперь давайте определимся, что именно мы хотим парсить
Что именно мы собираемся извлечь из Expedia?
Всегда лучше заранее решить, какие данные вы хотите проанализировать из необработанных данных.
Для этого урока мы собираемся очистить:
- Название отеля
- Тип номера
- Цена до налогообложения
- Цена после уплаты налогов
Я выделил эти точки данных на изображении выше. Пожалуйста, обратитесь к этому, если у вас возникнет путаница.
Очистить Expedia.com
Прежде чем мы очистим какой-либо текст, мы должны определить его позицию внутри DOM. Продолжая приведенный выше код, мы сначала найдем расположение каждого элемента, а затем извлечем их с помощью BS4. Мы будем использовать методы .find()
и .find_all()
, предоставляемые BS4. Если вы хотите узнать больше о BS4, вам следует обратиться к Учебнику BeautifulSoup.
Начнем сначала с названия.
Итак, имя хранится внутри файла h1 tag
. Соскоблить это было бы очень просто.
soup=BeautifulSoup(resp,'html.parser') try: o["hotel"]=soup.find("h1").text except: o["hotel"]=None
- Здесь мы создали объект BeautifulSoup. Результирующий
soup
объект является экземпляром классаBeautifulSoup
, который предоставляет ряд методов для поиска и обработки проанализированного HTML-документа. - Затем, используя метод
.find()
BS4, мы извлекаем текст.
Теперь давайте очистим данные о типе комнаты. Но перед этим давайте посмотрим, где расположены эти комнатные блоки.
Как видите, этот полный раздел комнат расположен внутри div tag
с attribute data-stid
, значение которого равно section-room-list
.
allOffers = soup.find("div",{"data-stid":"section-room-list"})
Внутри этого вы заметите, что все эти детали отдельных комнат хранятся внутри div tag
с классом uitk-layout-grid-item
.
Offers = allOffers.find_all("div",{"class":"uitk-layout-grid-item"})
Теперь будет намного проще парсить текст комнатного типа.
Вы заметите, что текст каждого типа комнаты хранится внутри div tag
с class uitk-spacing-padding-small-blockend-half
, а этот элемент находится внутри div tag
с классом uitk-spacing-padding-blockstart-three
.
Поскольку есть несколько комнат, нам нужно запустить цикл for
, чтобы получить доступ ко всем деталям комнаты. Все, что нам нужно сделать, это запустить цикл for
, который будет перебирать Offers list
.
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®ionId=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
Преимущество использования Scrapingdog Web Scraping API:
- Вам больше не придется управлять заголовками.
- Каждый запрос будет проходить через новый IP. Это сохраняет ваш IP анонимным.
- Наш API автоматически повторит попытку, если первое попадание окажется неудачным.
- Scrapingdog использует резидентные прокси для парсинга Expedia. Это увеличивает вероятность успешного парсинга Expedia или любого другого подобного веб-сайта.
Вы должны зарегистрироваться в бесплатной учетной записи, чтобы начать ее использовать. Вам понадобится всего 10 секунд, чтобы начать работу со Scrapingdog.
После того, как вы зарегистрируетесь, вы будете перенаправлены на вашу панель управления. Приборная панель будет выглядеть примерно так.
Вы должны использовать свой собственный ключ API.
Теперь вы можете вставить ссылку на свою страницу Expedia слева, а затем выбрать JS Rendering как Да. После этого нажмите Копировать код справа. Теперь используйте этот 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®ionId=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).
Надеюсь, вам понравился этот небольшой урок, и если да, то не забудьте поделиться им с друзьями и в социальных сетях.
Дополнительные ресурсы
Вот несколько дополнительных ресурсов, которые могут оказаться полезными во время изучения веб-страниц: