Время прочтения: 4 мин.

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

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

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

Алгоритм работы.
1) Перейти на сайт

2) Ввести кадастровый номер в поле поиска, нажать Enter;

3) В появившемся ниже поле определить проверяемый объект и нажать кнопку «выбрать»;

4) На странице объекта идентифицировать информацию (в нашем случае это тип, кадастровый номер, и адрес объекта недвижимости);

5) Сохранить результат.

Для реализации инструмента нам необходим Python, библиотеки Selenium, Pandas, а также Google Chrome, ChromeDriver и базовые навыки HTML.

  1. Входные данные.


Кадастровые номера объектов находятся в таблице в формате Excel.
Импортируем электронную таблицу, получаем список из кадастровых номеров.

import pandas as pd
import numpy as np

adres=pd.read_excel('kad.xlsx',header=None)
llist=adres[]

2. Создадим функции.

startChrome — функция запуска браузера.

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.support import expected_conditions as EC

def startChrome():
    chrome_options = Options()
    driver = webdriver.Chrome(options=chrome_options)
    driver.set_page_load_timeout(30)
    WebDriverWait(driver, 2)
    return driver

wait_element и wait_element_text — функции обращения к веб-элементам:

  • основаны на явном ожидании (explicit waits) элементов, данная реализация позволяет избежать использования таймера, что ускоряет работу кода;
  • обращаются к элементу через XPath (язык запросов для извлечения элементов в XML документе).
def wait_element (path):
    try:
        WebDriverWait(driver, 30).until(
        EC.presence_of_element_located((By.XPATH, path)))
    except:
        driver.refresh()
    return driver.find_element_by_xpath(path)

def wait_element_text (path):    
    try:
        element = WebDriverWait(driver, 30).until(
        EC.presence_of_element_located((By.XPATH, path)))
    except:
        aaa=np.nan
    else:
        aaa=driver.find_element_by_xpath(path).text
    return aaa

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

Нажать правой кнопкой на интересующий веб-элемент в окне браузера -> «Просмотр кода элемента».

В появившейся справа консоли кликнуть правой кнопкой мыши по выбранному элементу -> выбрать «copy XPath».

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

3. Запуск скрипта.

Алгоритм приведенного скрипта работает в однопоточном режиме, извлекая информацию о каждом объекте недвижимости по кадастровому номеру, находящегося в исходной таблице kad.xlsx.

#создаем пустые таблицы
df=df_temp=pd.DataFrame() 

#запускаем браузер
driver = startChrome() 
#переходим на веб-страницу ранее упомняутого сервиса
driver.get('https://rosreestr.net/proverit-kvartiru') 
#циклически извлекаем кадастровые номера объектов недвижимости из списка
for i in list(range(0,len(llist))): 
    #присваиваем пустые знаечния переменным
    a0=a1=a2=np.nan     
    #вводим кадастровый номер в поле поиска и нажимаем Enter
    wait_element('//*[@id="search_main"]').send_keys(str(llist[i]),Keys.RETURN) 
    #используем функцию ожидания до тех пор пока не исчезнет таймер поиска
    while driver.find_element_by_xpath('//*[@id="table_search_timer"]').is_displayed():
            time.sleep(1) 
    else: 
        #если совпадений не найдено, вывести сообщение
        if driver.find_element_by_xpath('//div[@class="table_search_not-title"]').text \
        =='Совпадений не найдено... Что делать?':
            print('table_search_not')         
        #иначе
        else: 
            print('table_search')
            try:
                #нажать на кнопку выбрать у проверяемого объекта
                wait_element('//a[contains(@href,"/kadastr/")] \
                             /div[@class="table__btn"]').click() 
                #задать переменной тип объекта
                a0=wait_element_text('//div[@class="test__data"] \
                /div[contains(text(),"Тип")]/strong') 
                #задать переменной кадастрвый номер объекта
                a1=wait_element_text('//div[@class="test__data"] \
                /div[contains(text(),"Кадастровый номер")]/strong') 
                #задать переменной адрес объекта
                a2=wait_element_text('//div[@class="test__data"] \ 
                /div[contains(text(),"Адрес полный")]/strong') 
                print(i,a0,a1,a2)
            except:
                print('no buton')
            #создать временную таблицу из набора переменных
            df_temp=pd.DataFrame([llist[i],a0,a1,a2]).transpose() 
            #добавить временную таблицу в основную таблицу
            df=df.append(df_temp) 
#по завершению цикла закрыть браузер
driver.close() 
#сохранит результат в электронную таблицу 
df.to_excel('result.xlsx', index=None)

Результат в виде наборов параметров (тип, кадастровый номер, и адрес объекта недвижимости) сохраняется в таблицу result.xlsx.

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