Основы программирования в Python

Алла Тамбовцева, НИУ ВШЭ

Автоматизация работы в браузере: библиотека selenium

Библиотека selenium – набор инструментов для интерактивной работы в браузере средствами Python. Вообще Selenium ‒ это целый проект, в котором есть разные инструменты. Мы рассмотрим один из самых распространенных ‒ Selenium WebDriver, модуль, который позволяется Python встраиваться в браузер и работать в нем как пользователь: кликать на ссылки и кнопки, заполнять формы, выбирать опции в меню и прочее.

Мы будем использовать WebDriver для решения такой задачи. Необходимо выгрузить все адреса участковых избирательных комиссий Ивановской области. Для этого нужно написать код, который будет открывать в окне браузера раздел По номеру избирательного участка, вводить в поле с номером номер участка и выбирать регион из предлагаемого списка. Итак, начнем.

Сначала загрузим веб-драйвер из библиотеки selenium.

In [1]:
from selenium import webdriver as wb

Если Python пишет No module called selenium, убедитесь, что у вас установлена эта библиотека. Самый надежный способ установить ее ‒ найти Anaconda Command Prompt, вписать строку pip install selenium и нажать Enter. Если Anaconda Command Prompt не находится, можно поступить так: запустить Jupyter Notebook, щелкнуть на черное окно консоли, нажать Ctrl+Z (остановить запуск Jupyter), а потом так же ввести в этом окне строку pip install selenium и нажать Enter.

Затем нужно выбрать браузер и открыть новое окно через Python. Для этого нужно вызвать функцию, которая отвечает за открытие браузера. Мы будем вызывать Chrome.

In [ ]:
br = wb.Chrome()

Если код выше не исполняется, скачайте файл с веб-драйвером отсюда, распакуйте архив и пропишите путь к файлу в круглых скобках (в примере файл с расширением exe на Windows).

In [ ]:
br = wb.Chrome('C:/Users/student/Desktop/chromewebdriver/chromedriver.exe')
In [2]:
br = wb.Chrome("/Users/allat/Downloads/chromedriver")
In [3]:
br.get("http://www.cikrf.ru/services/lk_address/?do=find_by_uik")

Ура, страница открылась. Что на этой странице есть интересного? Два поля: ввод номера участка и регион. Сохраним номер участка в переменную n_uik, а регион ‒ в reg.

In [4]:
n_uik = 244
reg = "Ивановская область"

Вопрос: как эти два поля заполнить? Нужно найти их на странице, открытой в браузере, и вписать туда нужные строки. Только сделать это нужно через Python. Воспользуемся инструментом CSS Selector (установить расширение для Chrome можно здесь). Для этого нужно открыть страницу в обычном браузере и кликнуть на расширение в правом углу.

Теперь, когда мы будем наводить курсор мыши на объект на странице в таком режиме и кликать, внизу будет отображаться его название в css.

Теперь осталось зафиксировать поле с таким названием и ввести туда номер УИКа.

In [5]:
# находим поле с #uik и сохраняем
uik_field = br.find_element_by_css_selector("#uik")

# вводим номер УИКа в поле - метод send_keys
uik_field.send_keys(n_uik)

Ура, получилось. А как быть с регионом? Там же не поле ввода, а целое выпадающее меню с опциями... Действовать можно аналогичным образом.

In [6]:
# region_field - поле для выбора региона, нашли по названию
region_field = br.find_element_by_name("subject")
region_field.send_keys(reg)

Осталось только кликнуть на кнопку Отправить запрос. Сначала найдем ее с помощью CSS Selector, а потом кликнем по ней ‒ воспользуемся методом .click():

In [7]:
button = br.find_element_by_link_text("Отправить запрос")
button.click()

В браузере открылась страница с адресом избирательного участка.

Осталось подгрузить re и найти на странице адрес участка с помощью регулярных выражений.

In [8]:
import re
In [9]:
p = re.search(r"Адрес помещения для голосования: ([^<]+)", br.page_source)
p
Out[9]:
<_sre.SRE_Match object; span=(1909, 2087), match='Адрес помещения для голосования: 155800, Ивановск>
In [10]:
p.group(1) # текст адреса
Out[10]:
'155800, Ивановская область, городской округ Кинешма, город Кинешма, улица Григория Королева, дом 10, здание "Кинешемский политехнический колледж"'

Получилось! Единственное, хорошо бы учесть случаи, когда адреса участка в таком виде на странице нет (такие случаи бывают: иногда страница создана не по шаблону, иногда указан адрес территориальной комиссии). Для этого нам понадобится условие. Добавим «развилку»: пусть Python пробует найти адрес через указанное регулярное выражение, а если не найдет, то ищет его с помощью другого регулярного выражения.

In [11]:
if p is None:
    p = re.search(r"Адрес: ([^<]+)", br.page_source)
    addr = p.group(1)

Теперь у нас есть универсальный код, который позволяет найти адрес избирательного участка по номеру. В следующий раз мы оформим этот код в функцию, чтобы можно было подставлять в нее любой номер и регион, и применять ее в цикле, итерируя по номерам участков.