CoderCastrov logo
CoderCastrov
Идеалиста

Парсинг Idealista

Парсинг Idealista
просмотров
9 мин чтение
#Идеалиста

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

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

Сбор всех ингредиентов в одном месте

Я предполагаю, что вы уже установили Python на своем компьютере. Я буду использовать python 3.x. Для сбора данных нам понадобятся еще две библиотеки.

  • Selenium - он будет использоваться для отображения веб-сайта Idealista.
  • BeautifulSoup - он будет использоваться для создания HTML-дерева для разбора данных.
  • Chromium - это веб-драйвер, который используется Selenium для управления Chrome. Вы можете загрузить его здесь.

Настройка

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

mkdir coding

Внутри этой папки вы можете создать файл с любым именем, которое вам нравится. В этом случае я буду использовать idealista.py. Наконец, мы установим вышеупомянутые библиотеки с помощью pip.

pip install selenium
pip install beautifulsoup4

Selenium - это инструмент для автоматизации браузера, он будет использоваться для загрузки нашего целевого URL в реальном браузере Chrome. BeautifulSoup, также известный как BS4, будет использоваться для извлечения чистых данных из необработанного HTML, возвращаемого selenium.

Мы также можем использовать библиотеку requests здесь, но Idealista любит отправлять капчи, и обычный HTTP GET-запрос может заблокировать ваш запрос и вызвать серьезные нарушения в вашем конвейере данных. Чтобы дать Idealista настоящую атмосферу браузера, мы продолжаем работу с selenium.

Что мы собираемся парсить?

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

Какие данные мы собираемся извлекать?

Лучше решить это заранее, чем принимать решение посередине блога.

Я решил извлечь следующие данные:

  • Заголовок недвижимости
  • Цена недвижимости
  • Площадь
  • Описание недвижимости
  • Ссылка на веб-страницу недвижимости.

Сначала мы соберем всю страницу с помощью Selenium и сохраним исходный код страницы в переменную. Затем мы создадим HTML-дерево с помощью BS4. Наконец, мы будем использовать методы find() и find_all() для извлечения соответствующих данных.

Давайте сначала соберем исходный код страницы

Для этой части мы будем использовать Selenium. Мы будем использовать метод page_source драйвера, который поможет нам получить исходный код текущей страницы или целевой страницы.

from bs4 import BeautifulSoup
from selenium import webdriver
import time
import schedule

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



l=list()
o={}

target_url = "https://www.idealista.com/venta-viviendas/torrelavega/inmobiliaria-barreda/"


driver=webdriver.Chrome(PATH)

driver.get(target_url)


time.sleep(5)
resp = driver.page_source
driver.close()

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

После этого я создал экземпляр Chrome с путем, где загружен драйвер. С помощью этой команды мы можем выполнять несколько тестов в браузере, пока не закроем соединение с помощью метода .close().

Затем я использовал метод .get(), чтобы загрузить веб-сайт. Он не только загружает веб-сайт, но и ожидает завершения рендеринга веб-сайта.

Наконец, мы извлекли данные, используя метод page_source, и закрыли сеанс с помощью метода .close(). .close() отключит связь с браузером. Теперь у нас есть полные данные страницы. Теперь мы можем использовать BS4 для создания супа, через который мы можем извлекать нужные данные с помощью методов .find() и .find_all() BS4.

Парсинг заголовка

Давайте сначала осмотрим и найдем элемент DOM.

Заголовок недвижимости хранится внутри тега a с классом item-link. Этот тег находится внутри тега div с классом item-info-container.

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

allProperties = soup.find_all("div",{"class":"item-info-container"})

После закрытия сеанса веб-драйвера мы создали дерево страницы, из которого будем извлекать текст. Для упрощения мы сохранили все свойства в виде списка внутри переменной allProperties. Теперь извлечение заголовков и других данных станет намного проще.

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

for i in range(0,len(allProperties)):
    o["title"]=allProperties[i].find("a",{"class":"item-link"}).text.strip("\n")

Объект o будет содержать все заголовки всех свойств после завершения цикла for. Давайте спарсим остальные данные.

Парсинг цены недвижимости

Давайте проанализируем и найдем расположение этого элемента внутри DOM.

<Image
  src="/blogs/f8a01098aa.jpg"
  width="700"
  height="154"
  alt=""
  sizes="100vw"
/>

Цена хранится внутри тега span с классом item-price. Мы будем использовать ту же технику, что и для парсинга заголовка. Внутри цикла for мы будем использовать следующий код.

o["price"]=allProperties[i].find("span",{"class":"item-price"}).text.strip("\n")

Это позволит извлечь все цены одну за другой.

Парсинг площади и описания

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

<Image
  src="/blogs/ac25550dd2.jpg"
  width="700"
  height="108"
  alt=""
  sizes="100vw"
/>

Размер площади хранится внутри тега div с классом “item-detail-char”.

o["area-size"]=allProperties[i].find("div",{"class":"item-detail-char"}).text.strip("\n")
<Image
  src="/blogs/50b4fe4b5e.jpg"
  width="700"
  height="109"
  alt=""
  sizes="100vw"
/>

Описание недвижимости можно найти внутри тега div с классом “item-description”.

Посвященный URL-адрес собственности

С помощью той же техники вы можете парсить посвященные ссылки. Давайте найдем их местоположение.

Ссылка хранится внутри тега с атрибутом href. Это не полный URL-адрес, поэтому мы добавим предварительный текст. Здесь мы будем использовать метод .get() из BS4, чтобы получить значение атрибута.

o["property-link"]="https://www.idealista.com"+allProperties[i].find("a",{"class":"item-link"}).get('href')

Здесь мы добавили https://www.idealista.com в качестве предварительного текста, потому что мы не найдем полный URL-адрес внутри тега href.

Мы смогли спарсить все данные, которые нас интересовали.

Полный код

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

from bs4 import BeautifulSoup
from selenium import webdriver
import time


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



l=list()
o={}

target_url = "https://www.idealista.com/venta-viviendas/torrelavega/inmobiliaria-barreda/"


driver=webdriver.Chrome(PATH)

driver.get(target_url)


time.sleep(7)
resp = driver.page_source
driver.close()

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

allProperties = soup.find_all("div",{"class":"item-info-container"})

for i in range(0,len(allProperties)):
    o["title"]=allProperties[i].find("a",{"class":"item-link"}).text.strip("\n")
    o["price"]=allProperties[i].find("span",{"class":"item-price"}).text.strip("\n")
    o["area-size"]=allProperties[i].find("div",{"class":"item-detail-char"}).text.strip("\n")
    o["description"]=allProperties[i].find("div",{"class":"item-description"}).text.strip("\n")
    o["property-link"]="https://www.idealista.com"+allProperties[i].find("a",{"class":"item-link"}).get('href')
    l.append(o)
    o={}

print(l)

После печати ответ будет выглядеть так.

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

Парсинг всех страниц

Вы, наверное, заметили, что на каждой странице есть 30 объектов недвижимости. Исходя из этой информации, можно получить общее количество страниц для каждого местоположения. Конечно, сначала нужно спарсить общее количество объектов недвижимости для каждого местоположения.

На текущей целевой странице 146 объектов недвижимости. Нам нужно спарсить это число, а затем разделить его на 30. Это число будет общим количеством страниц. Давайте сначала спарсим это число.

Как видите, это число находится внутри строки. Мы должны спарсить эту строку, а затем использовать функцию .split() в Python, чтобы разбить строку на список. Затем первый элемент списка будет нашим нужным элементом, потому что 146 - это первый символ в предложении.

Эта строка хранится внутри тега div с классом "listing-title". Давайте извлечем ее.

totalProperties = int(soup.find("div",{"class":"listing-title"}).text.split(" ")[0])
totalPages = round(totalProperties/30)

с помощью метода int() я преобразовал строку в целое число. Затем мы разделили его на 30, чтобы получить общее количество страниц. Теперь давайте проверим, как меняется шаблон URL при изменении номера страницы.

Когда вы нажимаете на вторую страницу, URL будет выглядеть так - https://www.idealista.com/venta-viviendas/torrelavega/inmobiliaria-barreda/pagina-2.htm

Таким образом, при нажатии на вторую страницу добавляется строка "pagina-2.htm". Аналогично, при нажатии на третью страницу вы получаете "pagina-3.htm". Нам просто нужно изменить целевой URL, добавив эту строку в соответствии с номером страницы, на которой мы находимся. Мы будем использовать цикл for для этого.

from bs4 import BeautifulSoup
from selenium import webdriver
import time


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



l=list()
o={}

target_url = "https://www.idealista.com/venta-viviendas/torrelavega/inmobiliaria-barreda/"


driver=webdriver.Chrome(PATH)

driver.get(target_url)


time.sleep(7)
resp = driver.page_source
driver.close()

soup = BeautifulSoup(resp, 'html.parser')
totalProperties = int(soup.find("div",{"class":"listing-title"}).text.split(" ")[0])
totalPages = round(totalProperties/30)
allProperties = soup.find_all("div",{"class":"item-info-container"})

for i in range(0,len(allProperties)):
    o["title"]=allProperties[i].find("a",{"class":"item-link"}).text.strip("\n")
    o["price"]=allProperties[i].find("span",{"class":"item-price"}).text.strip("\n")
    o["area-size"]=allProperties[i].find("div",{"class":"item-detail-char"}).text.strip("\n")
    o["description"]=allProperties[i].find("div",{"class":"item-description"}).text.strip("\n")
    o["property-link"]="https://www.idealista.com"+allProperties[i].find("a",{"class":"item-link"}).get('href')
    l.append(o)
    o={}

for x in range(2,totalPages+1):
    target_url = "https://www.idealista.com/venta-viviendas/torrelavega/inmobiliaria-barreda/pagina-{}.htm".format(x)
    driver=webdriver.Chrome(PATH)

    driver.get(target_url)


    time.sleep(7)
    resp = driver.page_source
    driver.close()

    soup = BeautifulSoup(resp, 'html.parser')
    allProperties = soup.find_all("div",{"class":"item-info-container"})
    for i in range(0,len(allProperties)):
        o["title"]=allProperties[i].find("a",{"class":"item-link"}).text.strip("\n")
        o["price"]=allProperties[i].find("span",{"class":"item-price"}).text.strip("\n")
        o["area-size"]=allProperties[i].find("div",{"class":"item-detail-char"}).text.strip("\n")
        o["description"]=allProperties[i].find("div",{"class":"item-description"}).text.strip("\n")
        o["property-link"]="https://www.idealista.com"+allProperties[i].find("a",{"class":"item-link"}).get('href')
        l.append(o)
        o={}

print(l)

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

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

Позвольте быть очень честным с вами, idealista.com - это хорошо защищенный сайт и его нельзя парсить в большом масштабе. Фактически, после 10 или 20 запросов он сможет обнаружить злоупотребление и заблокирует доступ к сайту. После этого вы будете продолжать получать ошибки 403 при каждом веб-запросе. Как избежать этого? Я бы порекомендовал вам воспользоваться Scrapingdog, который является API парсинга. Scrapingdog использует свой большой пул прокси-серверов, чтобы преодолеть любые проблемы, с которыми вы можете столкнуться при извлечении данных в большом масштабе. Давайте посмотрим, как мы можем использовать Scrapingdog для парсинга idealista.com в большом масштабе.

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

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

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

from bs4 import BeautifulSoup
import requests




l=list()
o={}

target_url = "https://www.idealista.com/venta-viviendas/torrelavega/inmobiliaria-barreda/"


resp = requests.get("https://api.scrapingdog.com/scrape?api_key=Ваш-API-ключ&url={}&dynamic=false".format(target_url))
soup = BeautifulSoup(resp.text, 'html.parser')
totalProperties = int(soup.find("div",{"class":"listing-title"}).text.split(" ")[0])
totalPages = round(totalProperties/30)
allProperties = soup.find_all("div",{"class":"item-info-container"})

for i in range(0,len(allProperties)):
    o["title"]=allProperties[i].find("a",{"class":"item-link"}).text.strip("\n")
    o["price"]=allProperties[i].find("span",{"class":"item-price"}).text.strip("\n")
    o["area-size"]=allProperties[i].find("div",{"class":"item-detail-char"}).text.strip("\n")
    o["description"]=allProperties[i].find("div",{"class":"item-description"}).text.strip("\n")
    o["property-link"]="https://www.idealista.com"+allProperties[i].find("a",{"class":"item-link"}).get('href')
    l.append(o)
    o={}
print(totalPages)
for x in range(2,totalPages+1):
    target_url = "https://www.idealista.com/venta-viviendas/torrelavega/inmobiliaria-barreda/pagina-{}.htm".format(x)

    resp = requests.get("https://api.scrapingdog.com/scrape?api_key=Ваш-API-ключ&url={}&dynamic=false".format(target_url))
    soup = BeautifulSoup(resp.text, 'html.parser')
    allProperties = soup.find_all("div",{"class":"item-info-container"})
    for i in range(0,len(allProperties)):
        o["title"]=allProperties[i].find("a",{"class":"item-link"}).text.strip("\n")
        o["price"]=allProperties[i].find("span",{"class":"item-price"}).text.strip("\n")
        o["area-size"]=allProperties[i].find("div",{"class":"item-detail-char"}).text.strip("\n")
        o["description"]=allProperties[i].find("div",{"class":"item-description"}).text.strip("\n")
        o["property-link"]="https://www.idealista.com"+allProperties[i].find("a",{"class":"item-link"}).get('href')
        l.append(o)
        o={}

print(l)

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

Таким образом, Scrapingdog можно использовать для парсинга любого веб-сайта без блокировки.

Заключение

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

Это самый простой способ парсить Idealista. Мы не использовали правильные техники обработки ошибок, но в реальных примерах вы всегда должны использовать операторы try/except, чтобы избежать сбоев или сбоев.

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

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