CoderCastrov logo
CoderCastrov
Парсинг

Парсинг данных отелей и количества свободных номеров отелей на сайте Pegi-Pegi с использованием BeautifulSoup

Парсинг данных отелей и количества свободных номеров отелей на сайте Pegi-Pegi с использованием BeautifulSoup
просмотров
4 мин чтение
#Парсинг
Table Of Content

    В настоящее время существует множество сайтов для поиска отелей, таких как Traveloka и Pegi-Pegi. Оба сайта предоставляют возможность бронирования отелей напрямую, без необходимости посещения отеля лично. Но когда-нибудь вы задумывались о том, сколько свободных номеров в отелях, представленных на этих сайтах. Обычно эти сайты показывают только доступные для бронирования номера, не указывая общее количество доступных номеров. Поэтому в этом примере я собираюсь спарсить данные об отелях в Йогякарте и подсчитать количество свободных номеров для каждого отеля.

    Этот проект также доступен на моем GitHub scraping_tripadvisor/scraping_pegi.py at main · rshby/scraping_tripadvisor (github.com)

    Когда мы открываем сайт Pegi-Pegi и выбираем город Йогякарта, нам сразу предлагается выбор отелей, которые мы можем забронировать. Внешний вид доступных отелей можно увидеть на следующем изображении.

    Страница выбора отелей

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

    Внешний вид типов номеров

    Наша задача - спарсить данные для получения всех данных об отелях и количестве доступных номеров. Библиотеки, которые мы будем использовать для парсинга данных, - это BeautifulSoup и requests. Результаты парсинга данных будут сохранены в формате csv-файла.

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

    import requests from bs4 import BeautifulSoup import csv from requests.api import request

    Затем мы создаем пустую переменную с именем data_pegi, которая будет использоваться для хранения результатов парсинга данных.

    data_pegi = []

    Затем мы видим, что максимальное количество страниц пагинации составляет 39 страниц, и мы видим, что в URL есть шаблон, соответствующий страницам, если страница 1, то /1, а если страница 39, то /39. Затем мы создаем цикл for для каждой страницы.

    for i in range(1, 39):

    Внутри этого цикла мы указываем URL страницы, переменные req и soup, а также переменную link_hotel для хранения URL каждого отеля. Синтаксис можно увидеть ниже.

    url = "https://www.pegipegi.com/hotel/jogja/"+str(i)+".html"
    req = requests.get(url)
    soup = BeautifulSoup(req.text, "html.parser")
    link_hotel = soup.findAll("a", {"itemprop": "url"}, href=True)

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

    for hotel in link_hotel:

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

    tersedia_kamar = 0
    url_hotel = hotel["href"]
    req_hotel = requests.get(url_hotel)
    soup1 = BeautifulSoup(req_hotel.text, "html.parser")
    nama_hotel = soup1.find("h1", {"itemprop": "name"}).text.strip().replace("/n", "")
    try: alamat = soup1.find("span", {"itemprop": "address"})
    except: alamat = "" # если адрес отеля не найден

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

    try: kamar = soup1.findAll("img", {"class": "slideShowRoom gm-img-center"})
    except: kamar = "0"

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

    jumlh_kamar = 0
    for item in kamar:
    jumlh_kamar += 1

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

    Информация о количестве доступных номеров

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

    for ktersedia in soup1.findAll("div", {"class": "listContentRoom"}):

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

    kmr_tsd = soup1.find("div", {"class": "note"}).text.replace("Tersedia", "").replace("kamar lagi !", "").strip()
    kmr_tsd = 0 _if_ kmr_tsd == "Kamar terbatas !" _else_ kmr_tsd
    tersedia_kamar += int(kmr_tsd)

    В коде выше, если в одном из типов номеров есть текст "Kamar Terbatas", я предполагаю, что для этого типа есть только один свободный номер, и этот подсчет уже учтен в цикле для переменной kamar, поэтому я устанавливаю значение 0 для переменной kmr_std, если это условие выполняется. Затем переменная tersedia_kamar будет содержать общее количество свободных номеров для всех типов номеров.

    total_kamar = jumlh_kamar+tersedia_kamar data_pegi.append([nama_hotel, alamat, jumlh_kamar, total_kamar])

    Код выше используется для сохранения общего количества доступных номеров, которое является результатом количества свободных типов номеров, плюс общее количество свободных номеров (без учета типов). Затем все полученные данные добавляются в переменную data_pegi. Затем, после завершения всех процессов парсинга и сохранения данных в переменной data_pegi, мы можем сохранить результаты парсинга в csv-файл с помощью следующего кода.

    kolom=["nama_hotel","alamat_hotel","jenis_kamar","total_kamar_tersedia"] writer = csv.writer(open("hotel_pegi_2.csv", "w", newline="")) writer.writerow(kolom)

    Мы создаем переменную kolom, чтобы определить, какие имена столбцов будут сохранены, создаем переменную writer и указываем имя файла csv, в котором будут сохранены данные.

    for d in data_pegi: writer.writerow(d)

    Затем мы создаем цикл для доступа к каждому элементу данных и вставляем эти данные в созданный csv-файл. Результаты csv-файла можно увидеть на следующем изображении, данные парсинга содержат информацию о 1177 отелях в Йогякарте.

    Результаты парсинга