Realtor.com — один из самых популярных веб-сайтов по продаже недвижимости, содержащий данные о миллионах объектов недвижимости, выставленных на продажу и в аренду, по всей территории Соединенных Штатов. Для специалистов в сфере недвижимости, инвесторов и специалистов по обработке данных информация на сайте Realtor.com является ценным ресурсом. Однако ручной поиск и агрегирование данных с сайта может занять чрезвычайно много времени.
В этом подробном руководстве мы рассмотрим процесс программного сбора данных с сайта Realtor.com с использованием Python и Selenium. Мы также увидим, как использовать сервис ScrapingBee для решения CAPTCHA и расширить ваши усилия по очистке сайта Realtor.com. В результате у вас будет полнофункциональный парсер Realtor.com, который вы сможете адаптировать под свои нужды в данных.
Настройка среды Python
Прежде чем мы начнем писать код, вам необходимо убедиться, что у вас установлен Python и несколько ключевых библиотек. В этом руководстве предполагается, что вы используете Python 3.6+. Если у вас еще нет Python, вы можете загрузить установщик для Windows, macOS или Linux по адресу python.org.
Когда Python готов к работе, создайте новую папку для вашего проекта очистки. Внутри этой папки создайте новый файл Python, например realtor_scraper.py
.
Теперь откройте терминал или командную строку, перейдите в папку вашего проекта и выполните следующие команды, чтобы установить необходимые пакеты Python:
pip install selenium
pip install undetected-chromedriver
Это установит:
- Selenium — набор инструментов для автоматизации браузера, который мы будем использовать для взаимодействия с Realtor.com.
- undetected-chromedriver — оптимизированная версия ChromeDriver от Selenium, которая помогает избежать обнаружения ботов.
Получение страниц Realtor.com с помощью Selenium
Selenium позволяет нам запускать браузер и управлять им с помощью кода. В этом руководстве мы будем использовать Google Chrome. Добавьте следующий код в ваш файл Python:
import undetected_chromedriver as uc
driver = uc.Chrome()
driver.get("https://www.realtor.com/realestateandhomes-search/Miami_FL")
Этот код запускает Chrome (используя undetected_chromedriver, чтобы замаскировать тот факт, что мы автоматизируем браузер) и переходит на страницу результатов поиска Realtor.com для Майами, Флорида.
Вы можете изменить URL-адрес, чтобы загружать результаты для любого местоположения. Просто замените Miami_FL
с желаемым сокращением города и штата, например New-York_NY
or Chicago_IL
.
Запустив этот код, вы должны увидеть открытое окно Chrome и загрузить страницу списков недвижимости Realtor.com в Майами.
Анализ структуры страницы Realtor.com
Чтобы извлечь данные со страницы, нам необходимо определить соответствующие элементы HTML и способы их уникального расположения. Инструменты разработчика браузера упрощают эту задачу.
В Chrome щелкните правой кнопкой мыши любой список на странице и выберите «Проверить», чтобы открыть инструменты разработчика. На панели «Элементы» вы можете увидеть HTML-структуру страницы.
<img src="/blog/web-scraping-realtor/listing-inspect.png" alt="Inspecting listing HTML">
Исследуя HTML, мы видим, что каждый листинг содержится в li
элемент с атрибутом data-testid="result-card"
, Внутри этих li
s, различные точки данных, которые мы хотим извлечь (цена, кровати, ванны и т. д.), содержатся в элементах с data-label
атрибутов.
Например, цена указана в span
data-label="pc-price"
, хотя адрес находится в div
data-label="pc-address"
.
Извлечение данных листинга с помощью Selenium
Вооружившись этой информацией о структуре страницы, мы можем использовать селекторы Selenium и CSS для поиска и извлечения нужных нам данных.
Во-первых, давайте возьмем все отдельные списки на странице:
from selenium.webdriver.common.by import By
listings = driver.find_elements(By.CSS_SELECTOR, ‘li[data-testid="result-card"]‘)
find_elements()
возвращает список всех элементов, соответствующих данному селектору. Здесь мы используем селектор атрибутов CSS, чтобы найти все li
элементы с data-testid
of "result-card"
, которые соответствуют отдельным спискам.
Теперь давайте пройдемся по спискам и извлечем нужные атрибуты:
data = []
for listing in listings:
datum = {}
# Price
price = listing.find_element(By.CSS_SELECTOR, ‘span[data-label="pc-price"]‘).text
datum[‘price‘] = price
# Address
address = listing.find_element(By.CSS_SELECTOR, ‘div[data-label="pc-address"]‘).text
datum[‘address‘] = address
# Beds
try:
beds = listing.find_element(By.CSS_SELECTOR, ‘li[data-label="pc-meta-beds"]‘).text
datum[‘beds‘] = beds
except:
datum[‘beds‘] = None
# Baths
try:
baths = listing.find_element(By.CSS_SELECTOR, ‘li[data-label="pc-meta-baths"]‘).text
datum[‘baths‘] = baths
except:
datum[‘baths‘] = None
# Square Feet
try:
sqft = listing.find_element(By.CSS_SELECTOR, ‘li[data-label="pc-meta-sqft"]‘).text
datum[‘sqft‘] = sqft
except:
datum[‘sqft‘] = None
data.append(datum)
Для каждого объявления li
, мы используем find_element()
чтобы найти дочерние элементы, содержащие целевые точки данных, по их data-label
атрибуты. Мы извлекаем текст этих элементов и сохраняем его в словаре, который добавляется к текущему файлу. data
.
Обратите внимание try/except
блоки при извлечении кроватей, ванн и кв. В некоторых списках эта информация может быть недоступна, поэтому нам необходимо обработать случай, когда соответствующий элемент не найден, чтобы избежать возникновения ошибки.
В конце этого, data
будет список словарей, каждый из которых содержит извлеченные данные для одного листинга:
[
{
‘price‘: ‘$320,000‘,
‘address‘: ‘9273 SW 227th St, Cutler Bay, FL 33190‘,
‘beds‘: ‘3 beds‘,
‘baths‘: ‘2 baths‘,
‘sqft‘: ‘1,441 sqft‘
},
{
‘price‘: ‘$1,150,000‘,
‘address‘: ‘1024 Biscayne Blvd # UPH07, Miami, FL 33132‘,
‘beds‘: ‘1 bed‘,
‘baths‘: ‘2 baths‘,
‘sqft‘: None
},
...
]
Разбивка по страницам всех результатов поиска
Результаты поиска на сайте Realtor.com разбиты на страницы, и на каждой странице отображается ограниченное количество объявлений. Чтобы очистить все результаты, нам нужно перемещаться по страницам нашего скрипта.
К счастью, сайт Realtor.com предоставляет ссылку «Далее» для загрузки следующей страницы результатов. Нажимая на эту ссылку циклически, пока она не перестанет отображаться, мы можем очистить все результаты с разбивкой на страницы.
Вот как мы можем изменить наш скрипт для управления нумерацией страниц:
data = []
while True:
listings = driver.find_elements(By.CSS_SELECTOR, ‘li[data-testid="result-card"]‘)
for listing in listings:
# Extract data from each listing as shown in previous section
...
try:
next_link = driver.find_element(By.XPATH, ‘//a[@aria-label="Go to next page"]‘)
next_link.click()
except:
break
Мы обертываем наш существующий код для извлечения данных из каждого листинга в while True
петля. После обработки списков на текущей странице мы пытаемся найти ссылку «Далее» (определяемую по ее aria-label
атрибут) и щелкните его, чтобы загрузить следующую страницу.
Если ссылка «Далее» не найдена, мы предполагаем, что достигли последней страницы результатов и break
из цикла нумерации страниц.
Благодаря этой модификации наш скрипт теперь будет извлекать данные из всех списков на всех страницах результатов поиска.
Обработка CAPTCHA с помощью ScrapingBee
Если вы запустите парсер Realtor.com достаточно долго, вы, скорее всего, обнаружите страницу CAPTCHA. Это распространенная мера защиты от ботов, используемая веб-сайтами для предотвращения парсинга.
Решение CAPTCHA — сложная тема и зачастую требует платных услуг. Одним из таких сервисов является ScrapingBee, который предоставляет API для взаимодействия с веб-сайтами, включая решение CAPTCHA.
Вот как вы можете перенести сбор данных с сайта Realtor.com на ScrapingBee и избежать CAPTCHA и блокировки IP:
Сначала установите ScrapingBee Python SDK:
pip install scrapingbee
Затем зарегистрируйте учетную запись ScrapingBee на сайте https://app.scrapingbee.com/signup чтобы получить ключ API.
Теперь вы можете использовать ScrapingBee для парсинга сайта Realtor.com следующим образом:
from scrapingbee import ScrapingBeeClient
client = ScrapingBeeClient(api_key=‘YOUR_API_KEY‘)
response = client.get(
‘https://www.realtor.com/realestateandhomes-search/Miami_FL‘,
params = {
‘extract_rules‘: {
‘listings‘: {
‘selector‘: ‘li[data-testid="result-card"]‘,
‘type‘: ‘list‘,
‘output‘: {
‘price‘: ‘span[data-label="pc-price"]‘,
‘address‘: ‘div[data-label="pc-address"]‘,
‘beds‘: ‘li[data-label="pc-meta-beds"]‘,
‘baths‘: ‘li[data-label="pc-meta-baths"]‘,
‘sqft‘: ‘li[data-label="pc-meta-sqft"]‘
}
},
‘next_page‘: {
‘selector‘: ‘//a[@aria-label="Go to next page"]‘,
‘output‘: ‘@href‘
}
},
‘wait_for‘: ‘ul.jsx-4195823979‘,
‘premium_proxy‘: ‘true‘
}
)
data = response.json()
Этот код использует ScrapingBee extract_rules
возможность указать селекторы CSS для данных, которые мы хотим извлечь. ScrapingBee будет обрабатывать JavaScript на странице (через wait_for
параметр), извлеките данные в соответствии с нашими правилами и верните их в виде структурированного JSON.
ScrapingBee также незаметно управляет ротацией прокси и решением CAPTCHA, поэтому нам не нужно беспокоиться о блокировке нашего парсера.
Чтобы получить последующие страницы результатов, вы можете проверить наличие data[‘next_page‘]
и если он существует, сделайте еще один запрос к ScrapingBee с этим URL-адресом, чтобы получить следующую страницу списков.
Масштабирование с помощью Scrapy
Для более сложных проектов парсинга вы можете рассмотреть возможность использования специальной платформы парсинга, такой как Scrapy.
Scrapy — мощная и расширяемая библиотека Python для создания веб-скраперов. Он предоставляет множество полезных функций «из коробки», таких как:
- Встроенная поддержка создания и перехода по ссылкам для сканирования целых сайтов.
- Надежный выбор и извлечение с использованием селекторов CSS и XPath.
- Экспорт каналов для хранения очищенных данных в форматах JSON, CSV, XML и других форматах.
- Регулирование и контроль вежливости, чтобы избежать перегрузки серверов
- Промежуточное программное обеспечение для фильтрации запросов, обработки файлов cookie, аутентификации, сжатия и т. д.
- Расширения для кэширования, сбора статистики, telnet-консолей и т. д.
Преобразование парсера Realtor.com на основе Selenium в Scrapy позволит вам значительно расширить свои усилия по парсингу. Вы можете легко распараллелить очистку, сохранить прогресс для приостановки и возобновления заданий, ротировать пользовательские агенты и IP-адреса и многое другое.
Заключение
В этом руководстве мы увидели, как собирать данные с сайта Realtor.com с помощью Python и Selenium. Ключевые шаги:
- Используйте Selenium для извлечения и рендеринга страниц
- Анализируйте HTML-код страницы, чтобы определить селекторы для целевых точек данных.
- Найдите и извлеките данные с помощью Selenium
find_element(s)
методы - Управляйте нумерацией страниц, находя и нажимая ссылки «Далее».
- Интегрируйте ScrapingBee, чтобы избежать CAPTCHA и блокировки IP-адресов.
- Рассмотрите Scrapy для более масштабных, готовых к производству проектов парсинга.
Хотя парсинг веб-страниц может быть мощным инструментом для сбора данных, важно соблюдать условия обслуживания веб-сайта и быть добросовестным гражданином сети, ограничивая частоту запросов и собирая только общедоступные данные.
Используя описанные здесь методы, вы сможете создать парсер Realtor.com для извлечения необходимых вам данных. Если у вас есть какие-либо вопросы или вы застряли на этом пути, не стесняйтесь обращаться к нам — мы всегда рады помочь с вашими проектами по парсингу веб-страниц!