Сегодня мы продолжим работать над задачей, поставленной ранее — выгрузка адресов всех участковых избирательных комиссий Ивановской области. Сначала загрузим все необходимые для работы библиотеки и функции:
selenium
— для автоматизации работы в браузере;BeautifulSoup
— для поиска по html-коду;time
— для добавления задержки;pandas
— для сохранения результатов в датафрейм.from time import sleep
from bs4 import BeautifulSoup
import pandas as pd
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
) и двигаться дальше.
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
Теперь попробуем взять несколько номеров участков и посмотреть, что получается в цикле.
uiks = range(200, 216)
addresses = []
for u in uiks:
addresses.append(get_uik_address(u, "Ивановская область"))
print(u)
sleep(1.5)
200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215
Работает! Создадим список со всеми номерами избирательных участков Ивановской области:
ivanovo = range(1, 777) # вроде все, см здесь новый список - http://www.ivanovo.izbirkom.ru/docs/4272/
Внимание: исполнение следующей ячейки займет много времени (час-полтора часа). Если просто хотите посмотреть, как это работает (не выгружая информацию по всем участкам), уменьшите правое значение в range()
в ячейке выше.
ivanovo_addr = []
for i in ivanovo:
ivanovo_addr.append(get_uik_address(i, "Ивановская область"))
#print(i)
sleep(1.5)
Важно: периодически открывайте окно браузера, в котором Python ищет избирательные участки! Это не только приятно (смотреть, как в полях для поиска все заполняется без нашего участия), но и полезно: так можно заметить, если что-то пошло не так. История из жизни: опечаталась в букве внутри цикла, Python 777 раз открыл страницу с избирательным участком 244 и сохранил одинаковые адреса.
Создадим датафрейм из списка выше.
df = pd.DataFrame(ivanovo_addr)
df.head()
0 | 1 | |
---|---|---|
0 | 1 | Адрес помещения для голосования: 153012, Ивано... |
1 | 2 | Адрес помещения для голосования: 153012, Ивано... |
2 | 3 | Адрес помещения для голосования: 153000, Ивано... |
3 | 4 | Адрес помещения для голосования: 153012, Ивано... |
4 | 5 | Адрес помещения для голосования: 153012, Ивано... |
Сохраним таблицу в Excel-файл:
df.to_csv('Ivanovo.xlsx')