{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Python для анализа данных\n", "\n", "*Алла Тамбовцева, НИУ ВШЭ*\n", "\n", "### Работа с `selenium`: продолжение" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Сегодня мы продолжим работать над задачей, поставленной на прошлом занятии ‒ выгрузка адресов всех участковых избирательных комиссий Ивановской области. Сначала загрузим все необходимые для работы библиотеки:\n", "\n", "* `selenium` ‒ для автоматизации работы в браузере\n", "* `re` ‒ для поиска адреса на странице с помощью регулярных выражений \n", "* `time` ‒ для добавления задержки\n", "* `pandas` ‒ для сохранения результатов в датафрейм" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "from selenium import webdriver as wb\n", "br = wb.Chrome(\"/Users/allat/Downloads/chromedriver\")\n", "\n", "br.implicitly_wait(2)" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "import re\n", "from time import sleep\n", "import pandas as pd" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Теперь напишем функцию `get_uik_address()`, которая принимает на вход два аргумента, номер участка и регион, и возвращает строку с адресом. Для этого в тело функции скопируем код с прошлого занятия:" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [], "source": [ "def get_uik_address(n_uik, reg):\n", " \n", " br.get(\"http://www.cikrf.ru/services/lk_address/?do=find_by_uik\")\n", " uik_field = br.find_element_by_css_selector(\"#uik\")\n", " uik_field.send_keys(n_uik)\n", " \n", " region_field = br.find_element_by_name(\"subject\")\n", " region_field.send_keys(reg)\n", " sleep(1.5) # еще добавим задержку в 1.5 секунды\n", " \n", " button = br.find_element_by_link_text(\"Отправить запрос\")\n", " button.click()\n", " sleep(1.5) # еще добавим задержку в 1.5 секунды\n", " \n", " p = re.search(r\"Адрес помещения для голосования: ([^<]+)\", br.page_source)\n", " \n", " if p is None:\n", " \n", " p = re.search(r\"Адрес: ([^<]+)\", br.page_source)\n", " \n", " addr = p.group(1)\n", " \n", " return addr" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Теперь попробуем взять несколько номеров участков и посмотреть, что получается в цикле. Только давайте перестрахуемся ‒ напишем выражение с исключением, чтобы в случае, если страница не содержит адреса или загружается некорректно, наш код не ломался и не происходило выхода из цикла. В случае, если все хорошо (адрес есть), Python будет его сохранять («ветка» c `try`), в случае, если все плохо (адреса нет ни в каком виде), Python будет записывать вместо него пустую строку (ветка с `except`) и двигаться дальше. " ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [], "source": [ "uiks = range(240, 245)" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "240 \n", "241 155330, Ивановская область, городской округ Вичуга, город Вичуга, улица Желябова, дом 6, здание МБОУ ООШ №6\n", "242 155330, Ивановская область, городской округ Вичуга, город Вичуга, улица Ленинская, дом 26, здание МБУК \"Клуб имени Шагова\"\n", "243 155330, Ивановская область, городской округ Вичуга, город Вичуга, улица Ленинская, дом 26, здание МБУК \"Клуб имени Шагова\"\n", "244 155800, Ивановская область, городской округ Кинешма, город Кинешма, улица Григория Королева, дом 10, здание \"Кинешемский политехнический колледж\"\n" ] } ], "source": [ "addresses = []\n", "\n", "for u in uiks:\n", " try:\n", " address = get_uik_address(u, \"Ивановская область\")\n", " except:\n", " address = \"\"\n", " addresses.append(address)\n", " print(u, address)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Работает! Создадим список со всеми номерами избирательных участков Ивановской области:" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "ivanovo = range(1, 777) # вроде все, см здесь новый список - http://www.ivanovo.izbirkom.ru/docs/4272/" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Внимание:** исполнение следующей ячейки займет много времени (примерно полтора часа). Если просто хотите посмотреть, как это работает (не выгружая информацию по всем участкам), уменьшите правое значение в `range()` в строчке выше." ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [], "source": [ "ivanovo_addr = []\n", "\n", "for i in ivanovo:\n", " try:\n", " address = get_uik_address(i, \"Ивановская область\")\n", " except:\n", " address = \"\"\n", " ivanovo_addr.append(address)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Важно:** периодически открывайте окно браузера, в котором Python ищет избирательные участки! Это не только приятно (смотреть, как в полях для поиска все заполняется без нашего участия), но и полезно: так можно заметить, если что-то пошло не так. История из жизни: опечаталась в букве внутри цикла, Python 777 раз открыл страницу с избирательным участком 244 и сохранил одинаковые адреса. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Создадим датафрейм из словаря, ключами которого служат названия столбцов таблицы, а значениями – списки элементов этих столбцов." ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [], "source": [ "df = pd.DataFrame({'uik': ivanovo, 'address': ivanovo_addr})" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
addressuik
0153000, Ивановская область, городской округ Ив...1
1153000, Ивановская область, городской округ Ив...2
2153000, Ивановская область, городской округ Ив...3
3153000, Ивановская область, городской округ Ив...4
4153000, Ивановская область, городской округ Ив...5
\n", "
" ], "text/plain": [ " address uik\n", "0 153000, Ивановская область, городской округ Ив... 1\n", "1 153000, Ивановская область, городской округ Ив... 2\n", "2 153000, Ивановская область, городской округ Ив... 3\n", "3 153000, Ивановская область, городской округ Ив... 4\n", "4 153000, Ивановская область, городской округ Ив... 5" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.head()" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['153000, Ивановская область, городской округ Иваново, город Иваново, Ленинский район, проспект Шереметевский, дом 8, здание ФГБОУ ВО \"Ивановская государственная медицинская академия\" Министерства здравоохранения Российской Федерации',\n", " '153000, Ивановская область, городской округ Иваново, город Иваново, Ленинский район, проспект Шереметевский, дом 10, здание ФГБОУ ВО \"Ивановский государственный химико-технологический университет\"',\n", " '153000, Ивановская область, городской округ Иваново, город Иваново, Ленинский район, проспект Шереметевский, дом 21, здание Текстильного института ФГБОУ ВО \"Ивановский государственный политехнический университет\"',\n", " '153000, Ивановская область, городской округ Иваново, город Иваново, Ленинский район, улица Арсения, дом 33/16, здание МАОУ лицей № 21',\n", " '153000, Ивановская область, городской округ Иваново, город Иваново, Ленинский район, улица Арсения, дом 33/16, здание МАОУ лицей № 21',\n", " '153000, Ивановская область, городской округ Иваново, город Иваново, Ленинский район, улица Сакко, дом 45, здание Культурно-спортивный центр',\n", " '153000, Ивановская область, городской округ Иваново, город Иваново, Ленинский район, улица Колотилова, дом 43, здание МБУ ДО Дом детского творчества № 3',\n", " '153012, Ивановская область, городской округ Иваново, город Иваново, Ленинский район, улица Суворова, дом 72, здание МБУ ДО \"Центр развития детской одаренности\"',\n", " '153000, Ивановская область, городской округ Иваново, город Иваново, Ленинский район, улица Бубнова, дом 49, здание Центральная городская библиотека им. Я.П. Гарелина',\n", " '153000, Ивановская область, городской округ Иваново, город Иваново, Ленинский район, улица Смирнова, дом 103, здание МБОУ \"Средняя школа № 53\"']" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "list(df.address)[0:10]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Сохраним таблицу в csv-файл:" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [], "source": [ "df.to_csv('Ivanovo.csv')" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.6.5" } }, "nbformat": 4, "nbformat_minor": 2 }