Алла Тамбовцева, НИУ ВШЭ
Посмотрим на другие примеры использования selenium
.
Пример. Зайдем на сайт книжного магазина и найдем все книги про Python. Загрузим библиотеку, веб-драйвер и откроем страницу в браузере через Python.
from selenium import webdriver as wb
br = wb.Chrome("/Users/allat/Downloads/chromedriver")
# открываем страницу в Chrome в автоматическом режиме
br.get("http://www.biblio-globus.ru/")
Найдем с помощью CSS Selector'а (SelectorGadget) поле для ввода названия книги или автора.
field = br.find_element_by_css_selector("input")
Сохраним запрос:
author = "Python" # переменная author - условность
Введем запрос в поле для поиска (.send_keys
) и подождем чуть-чуть:
field.send_keys(author)
br.implicitly_wait(2) # подождем пару секунд
Теперь найдем кнопку для поиска (значок лупа рядом со строкой поиска) через CSS Selector:
submit = br.find_element_by_css_selector("#search_submit")
Кликнем на нее:
submit.click()
Сохраним первую страницу с результатами в переменную page1
.
page1 = br.page_source
page1
Теперь обработаем эту страницу через BeautifulSoup
:
from bs4 import BeautifulSoup
soup1 = BeautifulSoup(page1, 'lxml')
Найдем все названия книг на этой странице. По исходному коду можно увидеть, что они имеют тэг a
с атрибутом class
, равным name
:
soup1.find_all('a', {'class':'name'})
[<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>
текст (так мы уже делали, и не раз).
books1 = [b.text for b in soup1.find_all('a', {'class':'name'})]
books1
['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']
Теперь аналогичным образом сгрузим информацию об авторах:
authors1 = [a.text for a in soup1.find_all('div', {'class': 'author'})]
Сгрузим расположение:
place1 = [p.text for p in soup1.find_all('div', {'class':'placement'})]
place1
['Расположение в торговом зале: Уровень 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']
И, конечно, цену:
price1 = [p.text for p in soup1.find_all('div',
{'class':'title_data price'})]
price1
['Цена: 569,00 руб.', 'Цена: 469,00 руб.', 'Цена: 3659,00 руб.', 'Цена: 899,00 руб.', 'Цена: 819,00 руб.', 'Цена: 2349,00 руб.', 'Цена: 1409,00 руб.', 'Цена: 1239,00 руб.', 'Цена: 249,00 руб.', 'Цена: 1109,00 руб.']
Осталось пройтись по всем страницам, которые были выданы в результате поиска. Для примера перейдем на страницу 2 и на этом остановимся.
next_p = br.find_element_by_css_selector('.next_page')
next_p.click()
Проделаем то же самое, что и с первой страницей. По-хорошему нужно написать функцию, которая будет искать на странице названия книг, их расположение и цену. Но оставим это в качестве задания читателю :)
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()
.
books1.extend(books2)
authors1.extend(books2)
place1.extend(place2)
price1.extend(price2)
Осталось импортировать библиотеку pandas
и создать датафрейм.
import pandas as pd
Для разнообразия создадим датафрейм не из списка списков, а из словаря. Ключами словаря будут названия столбцов в таблице, а значениями – списки с сохраненной информацией (названия книг, цены и проч.).
df = pd.DataFrame({'book': books1, 'author': authors1,
'placement': place1, 'price': price1})
df.head()
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()
,
def get_price(price):
book_price = price.split(' ')[1] # разобьем строку по пробелу и возьмем второй элемент
book_price = book_price.replace(',', '.') # заменим запятую на точку
price_num = float(book_price) # сконвертируем в float
return price_num
# проверка
get_price(df.price[0])
569.0
Всё отлично работает! Применим функцию к столбцу price и создадим новый столбец nprice.
df['nprice'] = df.price.apply(get_price)
df.head()
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 |
Теперь можем расположить книги по цене в порядке возрастания:
df.sort_values('nprice')
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-файл:
df.to_csv("books.csv")