#!/usr/bin/env python # coding: utf-8 # # Python для анализа данных # # *Алла Тамбовцева, НИУ ВШЭ* # # ### Работа с `selenium`: продолжение # Сегодня мы продолжим работать над задачей, поставленной на прошлом занятии ‒ выгрузка адресов всех участковых избирательных комиссий Ивановской области. Сначала загрузим все необходимые для работы библиотеки: # # * `selenium` ‒ для автоматизации работы в браузере # * `re` ‒ для поиска адреса на странице с помощью регулярных выражений # * `time` ‒ для добавления задержки # * `pandas` ‒ для сохранения результатов в датафрейм # In[2]: from selenium import webdriver as wb br = wb.Chrome("/Users/allat/Downloads/chromedriver") br.implicitly_wait(2) # In[3]: import re from time import sleep import pandas as pd # Теперь напишем функцию `get_uik_address()`, которая принимает на вход два аргумента, номер участка и регион, и возвращает строку с адресом. Для этого в тело функции скопируем код с прошлого занятия: # In[7]: def get_uik_address(n_uik, reg): br.get("http://www.cikrf.ru/services/lk_address/?do=find_by_uik") uik_field = br.find_element_by_css_selector("#uik") uik_field.send_keys(n_uik) region_field = br.find_element_by_name("subject") region_field.send_keys(reg) sleep(1.5) # еще добавим задержку в 1.5 секунды button = br.find_element_by_link_text("Отправить запрос") button.click() sleep(1.5) # еще добавим задержку в 1.5 секунды p = re.search(r"Адрес помещения для голосования: ([^<]+)", br.page_source) if p is None: p = re.search(r"Адрес: ([^<]+)", br.page_source) addr = p.group(1) return addr # Теперь попробуем взять несколько номеров участков и посмотреть, что получается в цикле. Только давайте перестрахуемся ‒ напишем выражение с исключением, чтобы в случае, если страница не содержит адреса или загружается некорректно, наш код не ломался и не происходило выхода из цикла. В случае, если все хорошо (адрес есть), Python будет его сохранять («ветка» c `try`), в случае, если все плохо (адреса нет ни в каком виде), Python будет записывать вместо него пустую строку (ветка с `except`) и двигаться дальше. # In[8]: uiks = range(240, 245) # In[9]: addresses = [] for u in uiks: try: address = get_uik_address(u, "Ивановская область") except: address = "" addresses.append(address) print(u, address) # Работает! Создадим список со всеми номерами избирательных участков Ивановской области: # In[6]: ivanovo = range(1, 777) # вроде все, см здесь новый список - http://www.ivanovo.izbirkom.ru/docs/4272/ # **Внимание:** исполнение следующей ячейки займет много времени (примерно полтора часа). Если просто хотите посмотреть, как это работает (не выгружая информацию по всем участкам), уменьшите правое значение в `range()` в строчке выше. # In[7]: ivanovo_addr = [] for i in ivanovo: try: address = get_uik_address(i, "Ивановская область") except: address = "" ivanovo_addr.append(address) # **Важно:** периодически открывайте окно браузера, в котором Python ищет избирательные участки! Это не только приятно (смотреть, как в полях для поиска все заполняется без нашего участия), но и полезно: так можно заметить, если что-то пошло не так. История из жизни: опечаталась в букве внутри цикла, Python 777 раз открыл страницу с избирательным участком 244 и сохранил одинаковые адреса. # Создадим датафрейм из словаря, ключами которого служат названия столбцов таблицы, а значениями – списки элементов этих столбцов. # In[9]: df = pd.DataFrame({'uik': ivanovo, 'address': ivanovo_addr}) # In[10]: df.head() # In[13]: list(df.address)[0:10] # Сохраним таблицу в csv-файл: # In[14]: df.to_csv('Ivanovo.csv')