Алла Тамбовцева, НИУ ВШЭ
selenium
¶Библиотека selenium
– набор инструментов для интерактивной работы в браузере средствами Python. Вообще Selenium ‒ это целый проект, в котором есть разные инструменты. Мы рассмотрим один из самых распространенных – Selenium WebDriver, модуль, который позволяется Python встраиваться в браузер и работать в нем как пользователь: кликать на ссылки и кнопки, заполнять формы, выбирать опции в меню и прочее.
Для начала установим библиотеку:
!pip install selenium
Теперь скачаем драйвер для браузера в виде архива с одного из сайтов: сайт для Chrome, сайт для Mozilla. После скачивания архив необходимо распаковать и запомнить, где лежит файл с драйвером (chromedriver.exe
на Windows, chromedriver
на Mac).
Импортируем из selenium
модуль webdriver
с сокращенным названием:
from selenium import webdriver as wb
Если используете драйвер для Chrome, необходимо прописать путь к файлу с драйвером внутри функции Chrome()
:
# пример для Mac
br = wb.Chrome('/Users/allat/Downloads/chromedriver')
# пример для Windows
br = wb.Chrome(r'C:\\Users\\allat\\Downloads\\chromedriver.exe')
Если используете драйвер для Mozilla, можно ничего не прописывать, функция Firefox()
сама поймет, где найти geckodriver:
br = wb.Firefox()
Если на Mac файл с драйвером упорно не хочет подсоединяться к Python, попробуйте выполнить действия в инструкции на странице курса (это займет некоторое время). После запуска строки кода выше в новом окне браузера открывается пустая страница. На эту страницу мы можем отправить ссылку на сайт и открыть его.
Мы будем использовать Selenium для решения такой задачи. Необходимо выгрузить все адреса участковых избирательных комиссий Ивановской области. Для этого нужно написать код, который будет открывать в окне браузера раздел По номеру избирательного участка, вводить в поле с номером номер участка и выбирать регион из предлагаемого списка. Итак, начнем. Откроем страницу по ссылке в браузере:
br.get('http://cikrf.ru/services/lk_address/?do=find_by_uik')
Ура, страница открылась. Что на этой странице есть интересного? Два поля: ввод номера участка и регион. Как эти два поля заполнить? Нужно найти их на странице, открытой в браузере, и вписать туда нужные строки. Только сделать это нужно через Python. Воспользуемся исходным кодом страницы. В коде видно, что поле для ввода региона имеет тэг input
и id
, равный "uik"
. Выполним поиск элемента по его id и сохраним результат в переменную uik
:
uik = br.find_element_by_id('uik')
Теперь осталось ввести в поле выше номер УИКа. Для этого нам понадобиться метод send_keys()
:
uik.send_keys(201)
Ура, получилось (посмотрите в окно браузера, которое было открыто через Python)! А как быть с регионом? Там же не поле ввода, а целое выпадающее меню с опциями... Но действовать можно аналогичным образом. Найдем выпадающее меню на странице и заметим, что оно имеет атрибут class
, равный "subject"
:
reg = br.find_element_by_name("subject")
reg.send_keys("Ивановская область")
Осталось только кликнуть на кнопку Отправить запрос. Сначала найдем ее по тексту ссылки (ссылка активируется, когда мы кликаем на Отправить запрос), а потом кликнем по ней ‒ воспользуемся методом .click()
:
button = br.find_element_by_link_text("Отправить запрос")
button.click()
В браузере открылась страница с адресом избирательного участка. Теперь можно попробовать извлечь исходный код страницы и с помощью BeautifulSoup
выполнить поиск адреса избирательного участка:
from bs4 import BeautifulSoup
soup = BeautifulSoup(br.page_source)
Соберем весь код с тэгами p
, вытащим оттуда текст и склеим в одну строку:
pars = soup.find_all('p')
text = " ".join([p.text for p in pars])
text
'Уважаемый пользователь! Данные о номере и адресе избирательного участка: Участковая избирательная комиссия №201Номер Территориальной избирательной комиссии: 008 Адрес помещения УИК: 153003, Ивановская область, городской округ Иваново, город Иваново, Фрунзенский район, улица Парижской Коммуны, дом 44, здание МБОУ "Средняя школа № 39" Телефон УИК: 8-(4932)-38-43-66 Адрес помещения для голосования: 153003, Ивановская область, городской округ Иваново, город Иваново, Фрунзенский район, улица Парижской Коммуны, дом 44, здание МБОУ "Средняя школа № 39" Телефон помещения для голосования: 8-(4932)-38-43-66 В случае необходимости получения дополнительной информации, вы можете обратиться в избирательную комиссию субъекта Российской Федерации по месту жительства (адреса избирательных комиссий субъектов Российской Федерации - www.cikrf.ru/sites).'
Теперь можем разбить по подстроке Адрес помещения для голосования, а потом еще по подстроке с телефоном:
addr = text.split('Адрес помещения для голосования: ')[1].split(
'Телефон помещения')[0]
addr
'153003, Ивановская область, городской округ Иваново, город Иваново, Фрунзенский район, улица Парижской Коммуны, дом 44, здание МБОУ "Средняя школа № 39" '
Теперь можно написать функцию для извлечения адреса участка и применить ее к списку номеров участков, который легко создать можно через range()
. Единственное, у нас нет гарантии, что код всегда будет срабатывать без ошибок – на странице может отсутствовать адрес или вообще отсутствовать текст про УИК. Для таких случаев пригодятся исключения – почитать про них можно, например, здесь.