Время прочтения: 4 мин.
В своей работе мы нередко встречаемся с необходимостью получить недостающую/обновить существующую информацию об исследуемом объекте. При условии, что нужная нам информация находится в открытых источниках, мы можем извлечь ее с помощью такого инструмента как парсер – программа для сканирования веб-страниц, извлечения неструктурированной информации и преобразования в структурированный формат.
Цель настоящей статьи привести практический пример как это было реализовано в нашем проекте на примере сервиса Росреестра. В связи с большим количеством информации о технологии парсинга на портале, сделаем акцент на практической реализации программного кода.
Итак, нам необходимо получить информацию об адресе и типе объекта недвижимости, но известен только кадастровый номер. Необходимая информация содержится на сервисе ROSREESTR.NET.
Алгоритм работы.
1) Перейти на сайт
2) Ввести кадастровый номер в поле поиска, нажать Enter;
3) В появившемся ниже поле определить проверяемый объект и нажать кнопку «выбрать»;
4) На странице объекта идентифицировать информацию (в нашем случае это тип, кадастровый номер, и адрес объекта недвижимости);
5) Сохранить результат.
Для реализации инструмента нам необходим Python, библиотеки Selenium, Pandas, а также Google Chrome, ChromeDriver и базовые навыки HTML.
- Входные данные.
Кадастровые номера объектов находятся в таблице в формате 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.
Использование парсера позволяет наполнить базу данных свежими данными из открытых источников, автоматизировать рутинную работу, которую ранее выполняли в ручном режиме.