Python для анализа данных

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

Посмотрим на другие примеры использования selenium.

Пример. Зайдем на сайт книжного магазина и найдем все книги про Python. Загрузим библиотеку, веб-драйвер и откроем страницу в браузере через Python.

In [1]:
from selenium import webdriver as wb
br = wb.Chrome("/Users/allat/Downloads/chromedriver")

# открываем страницу в Chrome в автоматическом режиме
br.get("http://www.biblio-globus.ru/")

Найдем с помощью CSS Selector'а (SelectorGadget) поле для ввода названия книги или автора.

In [2]:
field = br.find_element_by_css_selector("input")

Сохраним запрос:

In [3]:
author = "Python"  # переменная author - условность

Введем запрос в поле для поиска (.send_keys) и подождем чуть-чуть:

In [4]:
field.send_keys(author)
br.implicitly_wait(2)  # подождем пару секунд

Теперь найдем кнопку для поиска (значок лупа рядом со строкой поиска) через CSS Selector:

In [5]:
submit = br.find_element_by_css_selector("#search_submit")

Кликнем на нее:

In [6]:
submit.click()

Сохраним первую страницу с результатами в переменную page1.

In [7]:
page1 = br.page_source
In [9]:
page1

Теперь обработаем эту страницу через BeautifulSoup:

In [10]:
from bs4 import BeautifulSoup
In [11]:
soup1 = BeautifulSoup(page1, 'lxml')

Найдем все названия книг на этой странице. По исходному коду можно увидеть, что они имеют тэг a с атрибутом class, равным name:

In [12]:
soup1.find_all('a', {'class':'name'})
Out[12]:
[<a class="name" href="/search/catalog/details/10548788">Python : Карманный справочник</a>,
 <a class="name" href="/search/catalog/details/10557981">Python : создаем программы и игры,</a>,
 <a class="name" href="/search/catalog/details/9635926">Изучаем Python</a>,
 <a class="name" href="/search/catalog/details/10519118">Python 3   Самое необходимое </a>,
 <a class="name" href="/search/catalog/details/10540996">Простой Python просто с нуля</a>,
 <a class="name" href="/search/catalog/details/10545061">Python и машинное обучение: машинное и глубокое обучение с использованием Python, scikit-learn и TenFlow</a>,
 <a class="name" href="/search/catalog/details/10394770">Алгоритмы. Справочник с примерами на C, C++, Java и Python</a>,
 <a class="name" href="/search/catalog/details/10513916">Python 3 и PyQt 5. Разработка приложений</a>,
 <a class="name" href="/search/catalog/details/10551375">Практикум по математической статистике. Проверка гипотез с использованием Excel, MatCalc, R и Python</a>,
 <a class="name" href="/search/catalog/details/10555114">Django 2.1. Практика создания веб-сайтов на Python</a>]

С помощью списковых включений выберем из ссылок с тэгом <a> текст (так мы уже делали, и не раз).

In [13]:
books1 = [b.text for b in soup1.find_all('a', {'class':'name'})]
In [14]:
books1
Out[14]:
['Python : Карманный справочник',
 'Python : создаем программы и игры,',
 'Изучаем Python',
 'Python 3   Самое необходимое ',
 'Простой Python просто с нуля',
 'Python и машинное обучение: машинное и глубокое обучение с использованием Python, scikit-learn и TenFlow',
 'Алгоритмы. Справочник с примерами на C, C++, Java и Python',
 'Python 3 и PyQt 5. Разработка приложений',
 'Практикум по математической статистике. Проверка гипотез с использованием Excel, MatCalc, R и Python',
 'Django 2.1. Практика создания веб-сайтов на Python']

Теперь аналогичным образом сгрузим информацию об авторах:

In [15]:
authors1 = [a.text for a in soup1.find_all('div', {'class': 'author'})]

Сгрузим расположение:

In [16]:
place1 = [p.text for p in soup1.find_all('div', {'class':'placement'})]
In [17]:
place1
Out[17]:
['Расположение в торговом зале: Уровень 1, зал № 07, секция 07, шкаф 72, полка 04',
 'Расположение в торговом зале: Уровень 1, зал № 07, секция 07, шкаф 72, полка 06',
 'Расположение в торговом зале: Уровень 1, зал № 07, секция 07, шкаф 72, полка 05',
 'Расположение в торговом зале: Уровень 1, зал № 07, секция 07, шкаф 72, полка 06',
 'Расположение в торговом зале: Уровень 1, зал № 07, секция 07, шкаф 72, полка 05',
 'Расположение в торговом зале: Уровень 1, зал № 07, секция 06, шкаф 58, полка 01',
 'Расположение в торговом зале: Уровень 1, зал № 07, секция 06, шкаф 60, полка 08',
 'Расположение в торговом зале: Уровень 1, зал № 07, секция 07, шкаф 72, полка 04',
 'Расположение в торговом зале: Уровень 1, зал № 07, секция 07, шкаф 65, полка 06',
 'Расположение в торговом зале: Уровень 1, зал № 07, секция 07, шкаф 72, полка 07']

И, конечно, цену:

In [18]:
price1 = [p.text for p in soup1.find_all('div', 
                                         {'class':'title_data price'})]
In [19]:
price1
Out[19]:
['Цена: 569,00 руб.',
 'Цена: 469,00 руб.',
 'Цена: 3659,00 руб.',
 'Цена: 899,00 руб.',
 'Цена: 819,00 руб.',
 'Цена: 2349,00 руб.',
 'Цена: 1409,00 руб.',
 'Цена: 1239,00 руб.',
 'Цена: 249,00 руб.',
 'Цена: 1109,00 руб.']

Осталось пройтись по всем страницам, которые были выданы в результате поиска. Для примера перейдем на страницу 2 и на этом остановимся.

In [20]:
next_p = br.find_element_by_css_selector('.next_page')
In [21]:
next_p.click()

Проделаем то же самое, что и с первой страницей. По-хорошему нужно написать функцию, которая будет искать на странице названия книг, их расположение и цену. Но оставим это в качестве задания читателю :)

In [22]:
page2 = br.page_source
soup2 = BeautifulSoup(page2, 'lxml')
books2 = [b.text for b in soup2.find_all('a', {'class':'name'})]
author2 = [a.text for a in soup2.find_all('div', {'class': 'author'})]
place2 = [p.text for p in soup2.find_all('div', {'class':'placement'})]
price2 = [p.text for p in soup2.find_all('div', {'class':'title_data price'})]

Расширим списки результатов с первой страницы данными, полученными со второй страницы, используя метод .extend().

In [23]:
books1.extend(books2)
authors1.extend(books2)
place1.extend(place2)
price1.extend(price2)

Осталось импортировать библиотеку pandas и создать датафрейм.

In [24]:
import pandas as pd

Для разнообразия создадим датафрейм не из списка списков, а из словаря. Ключами словаря будут названия столбцов в таблице, а значениями – списки с сохраненной информацией (названия книг, цены и проч.).

In [25]:
df = pd.DataFrame({'book': books1, 'author': authors1,
                   'placement': place1, 'price': price1})
In [26]:
df.head()
Out[26]:
book author placement price
0 Python : Карманный справочник М. Лутц Расположение в торговом зале: Уровень 1, зал №... Цена: 569,00 руб.
1 Python : создаем программы и игры, Д. М. Кольцов Расположение в торговом зале: Уровень 1, зал №... Цена: 469,00 руб.
2 Изучаем Python М. Лутц Расположение в торговом зале: Уровень 1, зал №... Цена: 3659,00 руб.
3 Python 3 Самое необходимое Прохоренок Расположение в торговом зале: Уровень 1, зал №... Цена: 899,00 руб.
4 Простой Python просто с нуля Р. Гаско Расположение в торговом зале: Уровень 1, зал №... Цена: 819,00 руб.

Давайте приведем столбец с ценой к числовому типу. Уберем слова Цена и руб, а потом сконвертируем строки в числа с плавающей точкой. Напишем функцию get_price(),

In [27]:
def get_price(price):
    book_price = price.split(' ')[1]  # разобьем строку по пробелу и возьмем второй элемент
    book_price = book_price.replace(',', '.')  # заменим запятую на точку
    price_num = float(book_price)  # сконвертируем в float
    return price_num
In [29]:
# проверка
get_price(df.price[0])
Out[29]:
569.0

Всё отлично работает! Применим функцию к столбцу price и создадим новый столбец nprice.

In [30]:
df['nprice'] = df.price.apply(get_price)
In [31]:
df.head()
Out[31]:
book author placement price nprice
0 Python : Карманный справочник М. Лутц Расположение в торговом зале: Уровень 1, зал №... Цена: 569,00 руб. 569.0
1 Python : создаем программы и игры, Д. М. Кольцов Расположение в торговом зале: Уровень 1, зал №... Цена: 469,00 руб. 469.0
2 Изучаем Python М. Лутц Расположение в торговом зале: Уровень 1, зал №... Цена: 3659,00 руб. 3659.0
3 Python 3 Самое необходимое Прохоренок Расположение в торговом зале: Уровень 1, зал №... Цена: 899,00 руб. 899.0
4 Простой Python просто с нуля Р. Гаско Расположение в торговом зале: Уровень 1, зал №... Цена: 819,00 руб. 819.0

Теперь можем расположить книги по цене в порядке возрастания:

In [32]:
df.sort_values('nprice')
Out[32]:
book author placement price nprice
8 Практикум по математической статистике. Провер... В. И. Глебов, С. Я. Криволапов Расположение в торговом зале: Уровень 1, зал №... Цена: 249,00 руб. 249.0
1 Python : создаем программы и игры, Д. М. Кольцов Расположение в торговом зале: Уровень 1, зал №... Цена: 469,00 руб. 469.0
0 Python : Карманный справочник М. Лутц Расположение в торговом зале: Уровень 1, зал №... Цена: 569,00 руб. 569.0
4 Простой Python просто с нуля Р. Гаско Расположение в торговом зале: Уровень 1, зал №... Цена: 819,00 руб. 819.0
3 Python 3 Самое необходимое Прохоренок Расположение в торговом зале: Уровень 1, зал №... Цена: 899,00 руб. 899.0
10 Python. Экспресс-курс Python. Экспресс-курс Расположение в торговом зале: Уровень 1, зал №... Цена: 989,00 руб. 989.0
11 Глубокое обучение на Python Глубокое обучение на Python Расположение в торговом зале: Уровень 1, зал №... Цена: 1039,00 руб. 1039.0
9 Django 2.1. Практика создания веб-сайтов на Py... В. А. Дронов Расположение в торговом зале: Уровень 1, зал №... Цена: 1109,00 руб. 1109.0
7 Python 3 и PyQt 5. Разработка приложений Н. А. Прохоренок, В. Дронов Расположение в торговом зале: Уровень 1, зал №... Цена: 1239,00 руб. 1239.0
18 Скрапинг веб-сайтов с помощью Python : сбор да... Скрапинг веб-сайтов с помощью Python : сбор да... Расположение в торговом зале: Уровень 1, зал №... Цена: 1279,00 руб. 1279.0
6 Алгоритмы. Справочник с примерами на C, C++, J... Дж. Хайнеман, Г. Поллис, С. Селков Расположение в торговом зале: Уровень 1, зал №... Цена: 1409,00 руб. 1409.0
15 Искусственный интеллект с примерами на Python Искусственный интеллект с примерами на Python Расположение в торговом зале: Уровень 1, зал №... Цена: 1409,00 руб. 1409.0
19 Python для сложных задач: наука о данных и маш... Python для сложных задач: наука о данных и маш... Расположение в торговом зале: Уровень 1, зал №... Цена: 1409,00 руб. 1409.0
13 Программирование на языке Python Программирование на языке Python Расположение в торговом зале: Уровень 1, зал №... Цена: 1879,00 руб. 1879.0
17 Python. К вершинам мастерства Python. К вершинам мастерства Расположение в торговом зале: Уровень 1, зал №... Цена: 1969,00 руб. 1969.0
16 Программирование на Python 3 Программирование на Python 3 Расположение в торговом зале: Уровень 1, зал №... Цена: 2269,00 руб. 2269.0
5 Python и машинное обучение: машинное и глубоко... С. Рашка, В. Мирджалили Расположение в торговом зале: Уровень 1, зал №... Цена: 2349,00 руб. 2349.0
14 Python. Справочник. Полное описание языка Python. Справочник. Полное описание языка Расположение в торговом зале: Уровень 1, зал №... Цена: 2349,00 руб. 2349.0
12 Программирование на Python. Т. 1 Программирование на Python. Т. 1 Расположение в торговом зале: Уровень 1, зал №... Цена: 2779,00 руб. 2779.0
2 Изучаем Python М. Лутц Расположение в торговом зале: Уровень 1, зал №... Цена: 3659,00 руб. 3659.0

И сохраним всю таблицу в csv-файл:

In [ ]:
df.to_csv("books.csv")