Получение доступа к данным Airbnb является важным этапом при анализе рынка недвижимости. Это необходимо для исследования цен на аренду жилья и их динамики в рамках маркетинговых кампаний, проведения конкурентного анализа, оценки отзывов и рейтингов, и может быть достигнуто путем скрапинга веб-данных. Однако доступ к этим данным может быть ограничен, поскольку скрапинг может нарушать правила использования сайта.
Далее пошагово рассмотрим, как разработать веб-скрапер для извлечения данных из объявлений на Airbnb с помощью Python и Selenium и при этом избежать возможных блокировок и ограничений со стороны платформы.
Первый шаг в создании веб-скрапера — понимание того, как получить доступ к интересующим нас веб-страницам, поскольку структура веб-сайтов может меняться со временем.
Чтобы понять структуру сайта, мы можем использовать инструменты разработчика браузера для изучения HTML веб-страницы. Для доступа к инструментам разработчика вы можете кликнуть правой кнопкой мыши и выбрать пункт “Просмотреть код элемента” или использовать сочетание клавиш:
Обратите внимание, что каждый контейнер с объявлением на Airbnb обернут в элемент “div” с определенным атрибутом класса: class=”g1qv1ctd”.
Для примера, выберем вкладку “location” и введем “London, UK”, таким образом получив доступ к предложениям по размещению в Лондоне. Веб-сайт предложит добавить даты заезда и выезда, что позволяет рассчитать стоимость проживания.
URL для этой страницы будет выглядеть примерно так:
url = "https://www.airbnb.com/s/London--United-Kingdom/homes?tab_id=home_tab&refinement_paths%5B%5D=%2Fhomes&flexible_trip_lengths%5B%5D=one_week&monthly_start_date=2024-01-01&monthly_length=3&price_filter_input_type=0&channel=EXPLORE&query=London%2C%20United%20Kingdom&place_id=ChIJdd4hrwug2EcRmSrV3Vo6llI&date_picker_type=calendar&source=structured_search_input_header&search_type=autocomplete_click"
Исходя из страницы поиска, мы будем извлекать следующие атрибуты данных объявлений:
Прежде чем начать скрапинг, нужно настроить среду разработки. Вот шаги, которые нужно выполнить:
Виртуальные среды в Python — инструмент, который позволяет изолировать пакеты и их зависимости для разных проектов. Использование виртуальной среды помогает избежать конфликтов между библиотеками и обеспечивает наличие всех необходимых зависимостей в рамках конкретного проекта.
Откройте командную строку с правами администратора и выполните следующую команду для создания новой виртуальной среды с именем “venv”:
python -m venv venv
Активируйте виртуальную среду:
venv\Scripts\activate
Откройте терминал и выполните следующую команду для создания новой виртуальной среды с именем “venv”:
sudo python3 -m venv venv
Активируйте виртуальную среду:
source venv/bin/activate
Чтобы деактивировать виртуальную среду, выполните следующую команду:
deactivate
После настройки виртуальной среды можно приступить к установке требуемых библиотек для скрапинга данных.
В активированной виртуальной среде выполните следующую команду:
pip install selenium beautifulsoup4 lxml seleniumwire
Для работы с Selenium необходим специальный драйвер, который будет осуществлять взаимодействие с выбранным браузером. В данном руководстве мы будем использовать браузер Chrome, но важно установить соответствующий WebDriver для выбранного браузера. После загрузки убедитесь, что драйвер расположен в каталоге, который включен в переменную среды PATH вашей операционной системы. Это позволит Selenium автоматически находить драйвер и управлять браузером.
В начале Python-файла импортируйте Seleniumwire и BeautifulSoup, а также другие необходимые библиотеки с помощью следующих команд:
from seleniumwire import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options
from bs4 import BeautifulSoup
import time
import csv
import random
Мы также импортируем библиотеки “random”, “time” и “csv” для различных вспомогательных функций.
Далее мы загружаем список прокси, чтобы избежать блокировки со стороны Airbnb. При попытке отправить запрос без использования приватного прокси пользователь может столкнуться с ответом “Access Denied”.
Настройка прокси выполняется следующим образом:
# Список прокси-серверов
proxies = [
"username:password@Your_proxy_IP_Address:Your_proxy_port1",
"username:password@Your_proxy_IP_Address:Your_proxy_port2",
"username:password@Your_proxy_IP_Address:Your_proxy_port3",
"username:password@Your_proxy_IP_Address:Your_proxy_port4",
"username:password@Your_proxy_IP_Address:Your_proxy_port5",
]
Убедитесь, что заменили “Your_proxy_IP_Address”, “Your_proxy_port”, а также “username” и “password” на актуальные данные.
Ротация прокси — ключевой элемент успешного веб-скрапинга. Веб-сайты часто блокируют доступ, когда замечают множество запросов с одного IP-адреса. Ротация различных прокси позволяет замаскировать активность, имитируя работу множества обычных пользователей и обойти анти-скрапинговые системы безопасности.
Для настройки ротации прокси сначала импортируйте библиотеку “random”. Затем создайте функцию “get_proxy()”, которая будет выбирать прокси из предоставленного списка случайным образом, используя метод “random.choice()”, и возвращать выбранный прокси.
def get_proxy():
return random.choice(proxies)
Далее мы создаем основную функцию под названием “listings()”. В этой функции настраивается "ChromeDriver", также она использует Selenium для навигации по странице с объявлениями о недвижимости, ожидает загрузки страницы и анализирует HTML с помощью Beautiful Soup.
def listings(url):
proxy = get_proxy()
proxy_options = {
"proxy": {
"http": f"http://{proxy}",
"https": f"http://{proxy}",
"no_proxy": "localhost,127.0.0.1",
}
}
chrome_options = Options()
chrome_options.add_argument("--headless")
s = Service(
"C:/Path_To_Your_WebDriver"
) # Замените на ваш путь к ChromeDriver
driver = webdriver.Chrome(
service=s, seleniumwire_options=proxy_options, chrome_options=chrome_options
)
driver.get(url)
time.sleep(8) # Настройте в зависимости от времени загрузки сайта
soup = BeautifulSoup(driver.page_source, "lxml")
driver.quit()
В этой функции сначала выбирается случайный прокси и настраиваются его опции, которые в дальнейшем используются для конфигурации WebDriver. Далее настраиваются опции Chrome, включая аргумент "--headless", что позволяет браузеру работать в фоновом режиме без графического интерфейса.
Затем WebDriver инициализируется с указанными сервисом, опциями seleniumwire и Chrome, что, в свою очередь, используется для перехода по заданному URL. Время ожидания в 8 секунд позволяет странице полностью загрузиться, после чего с помощью Beautiful Soup производится анализ возвращенного HTML. По завершении анализа WebDriver закрывается.
Следующий этап после получения HTML-содержимого страницы включает в себя извлечение данных из каждого объявления. Используя библиотеку BeautifulSoup, мы можем эффективно производить навигацию по структуре HTML и определять элементы, содержащие нужную нам информацию.
Для начала нужно определить все элементы объявления на странице, которые содержат необходимые нам данные: URL объявления, заголовок, описание, рейтинг, цену и другую релевантную информацию.
listing_elements = soup.find_all("div", class_="g1qv1ctd")
for listing_element in listing_elements:
Этот код использует метод “find_all()” библиотеки BeautifulSoup для поиска всех элементов “div” с классом “g1qv1ctd”. Эти элементы представляют собой отдельные объявления на странице Airbnb. Затем скрипт перебирает каждый из этих элементов для извлечения соответствующих данных.
Для каждого найденного элемента объявления производится извлечение URL.
URL_element = soup.find("a", class_="rfexzly")
listing_data["Listing URL"] = (
"https://www.airbnb.com" + URL_element["href"] if URL_element else ""
)
В этом фрагменте кода мы исследуем объект “soup” на предмет наличия тега анкора с классом “rfexzly”. Если такой элемент найден, из него извлекается атрибут “href”, содержащий URL. Этот URL затем добавляется к базовому адресу Airbnb для формирования полного URL объявления. В случае отсутствия элемента присваивается пустая строка, чтобы предотвратить возможные ошибки в выполнении кода.
Сначала мы извлечем URL каждого объявления. Это позволит нам в дальнейшем посетить страницы каждого из этих объявлений, если это будет необходимо.
title_element = listing_element.find("div", class_="t1jojoys")
listing_data["Title"] = (
title_element.get_text(strip=True) if title_element else ""
)
Далее, для извлечения заголовка объявления, мы обращаемся к элементу “div” с классом “t1jojoys”. Из этого элемента извлекается текстовое содержимое, при этом удаляются все начальные и конечные пробелы для чистоты данных. В случае отсутствия такого элемента в объявлении сохраняется пустая строка, чтобы избежать ошибок при обработке данных.
Description_element = listing_element.find("span", class_="t6mzqp7")
listing_data["Description"] = (
Description_element.get_text(strip=True) if Description_element else ""
)
Так же, как и при извлечении заголовка, этот код находит элемент “” с классом “t6mzqp7”. Затем из этого элемента извлекается и очищается текстовое содержимое, которое представляет собой краткое описание объявления.
rating_element = listing_element.find("span", class_="ru0q88m")
listing_data["Rating"] = (
rating_element.get_text(strip=True) if rating_element else ""
)
Как видно из кода выше, элемент “span” с классом “ru0q88m” содержит значение рейтинга. Мы извлекаем это значение, убедившись, что лишние пробелы удалены.
Наконец, мы извлекаем цену объявления.
price_element = listing_element.select_one("._1y74zjx")
listing_data["Price"] = (
f"{price_element.get_text(strip=True)} per night" if price_element else ""
)
Этот код находит элемент с классом “._1y74zjx” в текущем элементе объявления. Если этот элемент, который обычно содержит информацию о цене, найден, его текстовое содержимое извлекается, очищается и дополняется фразой “per night”, формируя таким образом более информативную строку с ценой.
Некоторые объявления могут содержать дополнительную информацию, которую мы можем извлечь.
listing_info_element = listing_element.find("span", {"aria-hidden": "true"})
listing_data["Additional Listing information"] = (
listing_info_element.get_text(strip=True) if listing_info_element else ""
)
Мы ищем элемент “” с атрибутом aria-hidden=”true” для поиска дополнительной информации об объявлении. После того как все релевантные данные из каждого элемента объявления извлечены, мы добавляем собранные данные в список объявлений.
listings.append(listing_data)
Как только все объявления обработаны, мы возвращаем список объявлений, где каждое объявление представлено в виде словаря, содержащего извлеченные данные.
return listings
После успешного сбора данных со страниц объявлений Airbnb следующим важным шагом является сохранение этой информации для будущего анализа и справки. Для этой задачи мы используем библиотеку csv. Сначала открываем файл CSV в режиме записи и создаём объект csv.DictWriter. Затем мы записываем заголовок и данные в файл.
airbnb_listings = listings(url)
csv_file_path = "proxy_web_listings_output.csv"
with open(csv_file_path, "w", encoding="utf-8", newline="") as csv_file:
fieldnames = [
"Listing URL",
"Title",
"Description",
"Rating",
"Price",
"Additional Listing information",
]
writer = csv.DictWriter(csv_file, fieldnames=fieldnames)
writer.writeheader()
for listing in airbnb_listings:
writer.writerow(listing)
print(f"Data has been exported to {csv_file_path}")
Ниже представлена полная версия кода, используемого в ходе данного туториала:
from seleniumwire import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options
from bs4 import BeautifulSoup
import time
import csv
import random
# Список прокси-серверов
proxies = [
"username:password@Your_proxy_IP_Address:Your_proxy_port1",
"username:password@Your_proxy_IP_Address:Your_proxy_port2",
"username:password@Your_proxy_IP_Address:Your_proxy_port3",
"username:password@Your_proxy_IP_Address:Your_proxy_port4",
"username:password@Your_proxy_IP_Address:Your_proxy_port5",
]
def get_proxy():
return random.choice(proxies)
def listings(url):
proxy = get_proxy()
proxy_options = {
"proxy": {
"http": f"http://{proxy}",
"https": f"http://{proxy}",
"no_proxy": "localhost,127.0.0.1",
}
}
chrome_options = Options()
chrome_options.add_argument("--headless")
s = Service(
"C:/Path_To_Your_WebDriver"
) # Замените на ваш путь к ChromeDriver
driver = webdriver.Chrome(
service=s, seleniumwire_options=proxy_options, chrome_options=chrome_options
)
driver.get(url)
time.sleep(8) # Настройте в зависимости от времени загрузки сайта
soup = BeautifulSoup(driver.page_source, "lxml")
driver.quit()
listings = []
# Найдите все элементы объявлений на странице
listing_elements = soup.find_all("div", class_="g1qv1ctd")
for listing_element in listing_elements:
# Извлеките данные из каждого элемента объявления
listing_data = {}
# URL объявления
URL_element = soup.find("a", class_="rfexzly")
listing_data["Listing URL"] = (
"https://www.airbnb.com" + URL_element["href"] if URL_element else ""
)
# Заголовок
title_element = listing_element.find("div", class_="t1jojoys")
listing_data["Title"] = (
title_element.get_text(strip=True) if title_element else ""
)
# Описание
Description_element = listing_element.find("span", class_="t6mzqp7")
listing_data["Description"] = (
Description_element.get_text(strip=True) if Description_element else ""
)
# Рейтинг
rating_element = listing_element.find("span", class_="ru0q88m")
listing_data["Rating"] = (
rating_element.get_text(strip=True) if rating_element else ""
)
# Цена
price_element = listing_element.select_one("._1y74zjx")
listing_data["Price"] = (
f"{price_element.get_text(strip=True)} per night" if price_element else ""
)
# Дополнительная информация объявления
listing_info_element = listing_element.find("span", {"aria-hidden": "true"})
listing_data["Additional Listing information"] = (
listing_info_element.get_text(strip=True) if listing_info_element else ""
)
# Добавьте данные объявления в список
listings.append(listing_data)
return listings
url = "https://www.airbnb.com/s/London--United-Kingdom/homes?tab_id=home_tab&refinement_paths%5B%5D=%2Fhomes&flexible_trip_lengths%5B%5D=one_week&monthly_start_date=2024-01-01&monthly_length=3&price_filter_input_type=0&channel=EXPLORE&query=London%2C%20United%20Kingdom&place_id=ChIJdd4hrwug2EcRmSrV3Vo6llI&date_picker_type=calendar&source=structured_search_input_header&search_type=autocomplete_click"
airbnb_listings = listings(url)
csv_file_path = "proxy_web_listings_output.csv"
with open(csv_file_path, "w", encoding="utf-8", newline="") as csv_file:
fieldnames = [
"Listing URL",
"Title",
"Description",
"Rating",
"Price",
"Additional Listing information",
]
writer = csv.DictWriter(csv_file, fieldnames=fieldnames)
writer.writeheader()
for listing in airbnb_listings:
writer.writerow(listing)
print(f"Data has been exported to {csv_file_path}")
Эта часть кода обеспечивает сохранение собранных данных в файл CSV под названием “proxy_web_listings_output.csv”.
Результаты работы нашего скрапера сохраняются в файл CSV в формате показанном ниже на скриншоте.
Данная инструкция эффективна для извлечения данных из объявлений Airbnb с помощью Python и позволяет собирать важную информацию о недвижимости, включая цены, доступность и отзывы. Использование прокси и настройка их ротации — важный шаг, чтобы избежать блокировки со стороны механизмов защиты Airbnb от ботов.
Мы получили вашу заявку!
Ответ будет отправлен на почту в ближайшее время.
С уважением proxy-seller.ru!
Комментарии: 0