CoderCastrov logo
CoderCastrov
Веб-разработка

Парсинг веб-сайта недвижимости для сбора набора данных

Парсинг веб-сайта недвижимости для сбора набора данных
просмотров
3 мин чтение
#Веб-разработка
Table Of Content

    Поиск подходящих данных для обучения моделей машинного обучения часто является настоящей проблемой. Несмотря на то, что существует множество веб-сайтов, пытающихся решить эту проблему, таких как Kaggle и Google Dataset Search, для большинства моих собственных идей по машинному обучению требуются дополнительные данные. В этом руководстве я покажу, как парсить веб-сайт недвижимости с использованием Ruby для сбора исторических данных о проданных объектах недвижимости.

    Конечная цель - иметь достаточное количество данных, чтобы иметь возможность отвечать на интересующие вопросы о шведском рынке недвижимости. Поскольку крупнейший сайт недвижимости в Швеции, hemnet.se, не предлагает общедоступного API, мы собираемся парсить HTML напрямую. Все проданные объекты на веб-сайте доступны в списках, где элементы списка указывают на страницу с подробной информацией.

    Используя библиотеки Ruby Rest-Client и Nokogiri, мы можем получить и выбрать нужные данные со страниц веб-сайта. Каждая веб-страница, содержащая списки проданных объектов недвижимости, доступна по следующей структуре URL:

    https://www.hemnet.se/salda/bostader?page=#{index}&sold_age=all

    Поскольку у Hemet в настоящее время 122 239 страниц с списками проданных объектов недвижимости, индекс в URL представляет собой диапазон от 1 до 122 239.

    number_of_pages = (1..12239)number_of_pages.each do |index|  link = “https://www.hemnet.se/salda/bostader?page=#{index}&sold_age=all"  scrape_page(link)end

    Приведенный выше код перебирает диапазон страниц, чтобы создать все необходимые ссылки и передает их в метод #scrape_page.

    def scrape_page(link)  css = "li.sold-results__normal-hit div.sold-property-listing    a.item-link-container"  webpage_data = data_from_link(link, css)  webpage_data.each do |data|    sold_propety_link = data.attr("href").split("/maklare/salda/")[0]    parse_sold_property_data(sold_propety_link)  end enddef data_from_link(link, css_input)  response_string = RestClient.get(link)  webpage = Nokogiri::HTML(response_string)  webpage_data = webpage.css(css_input)end

    Давайте пройдемся по этому коду.

    1. Метод #data_from_link использует Rest-Client для получения HTML и Nokogiri для выбора нужного тега a.

    2. Мы можем получить URL страницы с подробным просмотром значений проданных объектов, перебирая данные веб-страницы. Чтобы удалить добавленное по умолчанию окончание "/maklare/salda/XXXX", мы используем метод #split и оставляем только первый элемент массива.

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

    def parse_sold_property_data(link)  proprety_details_css = "div.sold-property__details dl dd.sold- property__attribute-value"
      sold_price_css = "span.sold-property__price-value"
      title_css = "h1.sold-property__address"
      sold_date_css = "p.sold-property__metadata time"  details_data = data_from_link(link, proprety_details_css)
      sold_price_data = data_from_link(link, sold_price_css)
      title_data = data_from_link(link, title_css)
      sold_date = data_from_link(link, sold_date_css)  titel = title_data[0].text.split("\n").last
      sold_price = sold_price_data[0].text.split(" kr")[0]
      sold_date = sold_date[0].values[0]  organize_and_store_data(details_data, titel, sold_price, sold_date)end

    Приведенный выше метод #parse_sold_property_data использует ту же технику парсинга CSS, но здесь мы извлекаем данные, заголовок, цену и дату. Метод #organize_and_store_data затем использует эти значения для создания хэша для этой недвижимости, как показано ниже.

    [@data](http://twitter.com/data) = []
    [@values](http://twitter.com/values) = {starting_price: "kr", price_per_square_meters: "kr/m²", number_of_rooms: "rum", living_are_square_meters: "m²", cost_per_month: "kr/mån"}def organize_and_store_data(data, title, sold_price, sold_date)current_hash = {title => {}}current_hash[title][:sold_price] = sold_price
    current_hash[title][:sold_date] = sold_datedata.each do |row|
        [@values](http://twitter.com/values).each do |key, unit|
          if !row.text.include?("%")
            if row.text.split(" ").include?(unit)
              current_hash[title][key] = row.text
            elsif (1700..2019).include?(row.text.to_i)
              current_hash[title][:construction_year] = row.text
            end
          end
        end
      end[@data](http://twitter.com/data) << current_hashend

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

    Красные рамки иллюстрируют уникальные единицы измерения

    Используя хэш с названием values, мы можем проверить, содержат ли какие-либо теги подробного просмотра эти конкретные единицы измерения. Обратите внимание, что для года постройки, который не имеет конкретной единицы измерения, мы проверяем, включен ли он в диапазон от 1700 до 2019. Также мы убеждаемся, что значения не содержат знак процента, поскольку мы не хотим сохранять изменение от начальной цены по сравнению с конечной ценой в нашем JSON-файле, так как его легко можно рассчитать по другим значениям. Наконец, мы создаем JSON-файл и сохраняем его в локальной директории с помощью метода #save_json_to_file ниже.

    def save_json_to_file(data)
      json_file = File.new('hemnet_json.json', 'w')
      json_file.write(data.to_json)
      json_file.close
    end

    Et voilà! Теперь у нас есть данные о более чем 600 000 проданных объектах недвижимости в нашем JSON-файле.

    Небольшой образец JSON-файла.

    Простой способ создать модель машинного обучения из этих данных можно выполнить с помощью фреймворка Create ML от Apple в Swift playground. Для надежного руководства по Create ML прочтите этот учебник от Appcoda.

    Весь код проекта доступен на GitHub в этом репозитории.

    (Обратите внимание, что целью этой статьи является исключительно академическая.)