#!/usr/bin/env python # coding: utf-8 # # Python для сбора данных # # *Алла Тамбовцева, НИУ ВШЭ* # # ### Работа с `selenium`: продолжение # Сегодня мы продолжим работать над задачей, поставленной ранее — выгрузка адресов всех участковых избирательных комиссий Ивановской области. Сначала загрузим все необходимые для работы библиотеки и функции: # # * `selenium` — для автоматизации работы в браузере; # * `BeautifulSoup` — для поиска по html-коду; # * `time` — для добавления задержки; # * `pandas` — для сохранения результатов в датафрейм. # In[1]: from time import sleep from bs4 import BeautifulSoup import pandas as pd # In[2]: from selenium import webdriver as wb br = wb.Chrome("/Users/allat/Downloads/chromedriver") br.implicitly_wait(2) # чтобы страница прогрузилась # Теперь напишем функцию `get_uik_address()`, которая принимает на вход два аргумента, номер участка и регион, и возвращает строку с адресом. Для этого в тело функции скопируем код с прошлого занятия. # # Только давайте перестрахуемся — напишем выражение с исключением, чтобы в случае, если страница не содержит адреса или загружается некорректно, наш код не ломался. В случае, если всё хорошо (адрес есть), Python будет его сохранять («ветка» c `try`), в случае, если всё плохо (адреса нет ни в каком виде), Python будет записывать вместо него `None` (ветка с `except`) и двигаться дальше. # In[3]: 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) button = br.find_element_by_link_text("Отправить запрос") button.click() sleep(1) # добавим задержку в 1 секунду soup = BeautifulSoup(br.page_source, 'lxml') texts = [a.text for a in soup.find_all('p')] try: address = list(filter(lambda x: "Адрес помещения для голосования:" in x, texts))[0] except: address = None return n_uik, address # Теперь попробуем взять несколько номеров участков и посмотреть, что получается в цикле. # In[4]: uiks = range(200, 216) # In[5]: addresses = [] for u in uiks: addresses.append(get_uik_address(u, "Ивановская область")) print(u) sleep(1.5) # Работает! Создадим список со всеми номерами избирательных участков Ивановской области: # In[6]: ivanovo = range(1, 777) # вроде все, см здесь новый список - http://www.ivanovo.izbirkom.ru/docs/4272/ # **Внимание:** исполнение следующей ячейки займет много времени (час-полтора часа). Если просто хотите посмотреть, как это работает (не выгружая информацию по всем участкам), уменьшите правое значение в `range()` в ячейке выше. # In[13]: ivanovo_addr = [] for i in ivanovo: ivanovo_addr.append(get_uik_address(i, "Ивановская область")) #print(i) sleep(1.5) # **Важно:** периодически открывайте окно браузера, в котором Python ищет избирательные участки! Это не только приятно (смотреть, как в полях для поиска все заполняется без нашего участия), но и полезно: так можно заметить, если что-то пошло не так. История из жизни: опечаталась в букве внутри цикла, Python 777 раз открыл страницу с избирательным участком 244 и сохранил одинаковые адреса. # Создадим датафрейм из списка выше. # In[14]: df = pd.DataFrame(ivanovo_addr) # In[16]: df.head() # Сохраним таблицу в Excel-файл: # In[17]: df.to_csv('Ivanovo.xlsx')