10000 кадастровых номеров, 30000 записей, источник — веб-сайт, дедлайн — конец рабочего дня. Как выгрузить такой объем данных?В своей работе мы нередко встречаемся с необходимостью получить недостающую/обновить существующую информацию об исследуемом объекте. При условии, что нужная нам информация находится в открытых источниках, мы можем извлечь ее с помощью программы для сканирования веб-страниц (парсера).Рассмотрим пример парсинга сервиса Росреестра. В связи с большим количеством информации о технологии парсинга в сети интернет, сделаем акцент на практической реализации программного кода.Итак, нам необходимо получить информацию об адресе и типе объекта недвижимости, но известен только кадастровый номер. Необходимая информация содержится на сервисе 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 driverwait_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 aaaXPath можно написать вручную, предварительно ознакомившись с синтаксисом или воспользоваться встроенным в браузер решением.Нажать правой кнопкой на интересующий веб-элемент в окне браузера -> «Просмотр кода элемента».В появившейся справа консоли кликнуть правой кнопкой мыши по выбранному элементу -> выбрать «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.Использование парсера позволяет наполнить базу данных свежими данными из открытых источников, автоматизировать рутинную работу, которую ранее выполняли в ручном режиме.