Использование парсинга для извлечения данных с веб-страниц
Table Of Content
- **Вызовы парсинга в большом масштабе**
- **Библиотеки в Python**
- Пример использования библиотеки requestsimport requestsr = requests.get(“[https://www.wp.pl](https://www.wp.pl)") # Получение содержимого сайта в HTML
- **Пример скрипта**
- источник данных
- запрос к веб-странице и получение результата в виде HTML-кода и присваивание его переменной "объект"
- разбор HTML с помощью BeautifulSoup и присваивание его переменной "soup"
- проверка наличия данных в таблице
- подсчет количества строк в таблице, но пропуск первой строки в качестве заголовка, результат должен быть 20
- создание списка и добавление заголовка для нашей таблицы
- цикл для просмотра всей таблицы
- создание файла CSV и запись строк в выходной файл
Парсинг данных с веб-страниц - это процесс извлечения данных с веб-страниц. Цели парсинга могут быть разными:
- Недвижимость - предложения о домах или квартирах
- Маркетинг и продажи
- Сравнение цен на товары
- Мониторинг цен на авиабилеты
Вызовы парсинга в большом масштабе
Вы должны парсить 100-150 веб-страниц ежедневно. С какими вызовами вы столкнетесь?
- Динамическое содержимое на основе JavaScript. Страницы, основанные на JavaScript и AJAX, сложны для парсинга. Один из способов решить эту проблему - использовать PhantomJS.
- Качество данных. Если вы хотите обрабатывать данные сразу после их получения, например, с использованием алгоритмов машинного обучения или искусственного интеллекта, вам нужно обратить внимание на качество данных. Пустые записи, ненужные пробелы или специальные символы не приветствуются в нашей базе данных.
- Капча. Мы все знаем, о чем речь, чтобы предотвратить спам роботов. Парсинг данных с сайтов, использующих капчу, сложно, но не невозможно. С использованием промежуточного программного обеспечения, которое перехватывает капчу, вы можете продолжить путешествие робота по конкретному сайту.
- Постоянное развитие вашего приложения. Маловероятно, что один раз написанный код будет служить вам надолго. С течением времени вы увеличите масштаб, количество веб-страниц, которые нужно парсить. Это также приводит к использованию дополнительных технологий, таких как контейнеры.
- Изменение содержимого сайта (например, изменение имени div). Время от времени мы видим обновление сайтов. Изменение пользовательского интерфейса, часто полное изменение шаблона. Это вызывает определенные сложности в нашем скрипте, так как мы должны потратить дополнительное время на проверку новой структуры страницы. Профессиональный совет: если вы не хотите случайно узнать, что данная страница изменила пользовательский интерфейс, постарайтесь создать тест в приложении для непрерывной интеграции, которое будет обнаруживать такие изменения.
- Хранение данных. Вы, вероятно, не хотите хранить данные в файлах .txt или .csv. Подумайте о базе данных для вашего приложения, например, воспользуйтесь бесплатным уровнем на AWS.
- Технологии, предотвращающие парсинг. Эта тема часто встречается на больших сайтах. Частые запросы к серверу могут привести к блокировке вашего IP-адреса. В этом случае вы можете использовать прокси-сервер, который будет использовать несколько IP-адресов. Scrapy позволяет реализовать такое решение. Также помните об этических вопросах - вы можете дополнительно прочитать об этом в статье "Парсинг данных - как начать?".
Библиотеки в Python
Почему Python? Это связано с его популярностью в этой области, поэтому в приведенном ниже списке и других примерах, которые я буду упоминать, основаны на коде Python. Существует разные подходы к парсингу веб-страниц, ниже вы узнаете о нескольких библиотеках, которые вы можете использовать.
Requests HTTP — Если вы хотите спарсить конкретную подстраницу, сначала вам нужно получить ее HTML-содержимое. Лучше всего сделать это, сохраняя ответ запроса в объекте. Сама библиотека легка в использовании. Ниже приведен краткий пример, а документацию вы найдете по ссылке выше.
# Пример использования библиотеки requestsimport requestsr = requests.get(“[https://www.wp.pl](https://www.wp.pl)") # Получение содержимого сайта в HTML
BeautifulSoup — У нас уже есть загруженные данные с конкретного сайта, но теперь наступает следующий этап - извлечение того, что нас больше всего интересует. BeautifulSoup - очень полезная библиотека Python, которая используется для извлечения данных со веб-страницы. Исходя из того, что у нас есть, мы используем библиотеку requests для загрузки данных с HTML-страницы, а затем используем BeautifulSoup для разбора страницы. В приведенном ниже примере вы можете увидеть, как использовать две библиотеки.
from bs4 import BeautifulSoupimport requestsr = requests.get(“[https://stooq.pl](https://stooq.pl)") # Загрузка содержимогоsoup = BeautifulSoup(r.text, “html.parser”) # Разбор страницыprint(soup.find_all(‘a’)) # Вывод всех элементов, являющихся ссылками
Scrapy — Еще одна замечательная библиотека для парсинга. В этом случае у нас есть фреймворк, который позволяет делать больше. Предыдущая библиотека BeautifulSoup позволяет разбирать страницу, а в этом случае мы можем написать комплексный инструмент, который в качестве веб-робота будет искать по веб-страницам и извлекать то, что нас интересует.
Рекомендую пройти учебник на https://docs.scrapy.org/en/latest/intro/tutorial.html, который проведет вас через несколько шагов, от создания первого бота до добавления дополнительных аргументов.
Пример скрипта
В качестве примера рассмотрим построение основного скрипта, который:
- Получает таблицу с компаниями из индекса WIG20 на сайте Stooq.pl
Чтобы понять, как к этому подойти, сначала изучим структуру страницы. Чтобы проверить это, щелкните правой кнопкой мыши и выберите опцию "Исследовать элемент/Проверить".
В таблице хранятся данные, которые мы будем захватывать и обрабатывать. Каждый из элементов, который нас интересует, представляет собой строку в таблице <tr>
. Давайте перейдем к самому коду. Первым шагом является импорт библиотек, которые мы будем использовать для нашего парсера. Мы будем использовать BeautifulSoup для разбора HTML, urllib для подключения к веб-странице и библиотеку csv, которая позволит сохранить выходные данные в файле в этом формате.
from bs4 import BeautifulSoup
import urllib.request
import csv
Следующим шагом является определение URL-адреса, который будет использоваться в качестве источника данных.
# источник данных
web_page = 'https://stooq.pl/t/?i=532'
Хорошо, у нас есть два основных элемента - импорт библиотек и указание источника данных. На этом этапе проверьте, есть ли все необходимые библиотеки в вашей среде разработки, и запустите код для тестирования. Конечно, этот фрагмент не отобразит никаких подробностей. Главное, чтобы он выполнился без ошибок.
Если вы уже справились с этим, мы можем перейти к разбору HTML с помощью BeautifulSoup, объект будет храниться в переменной "soup".
# запрос к веб-странице и получение результата в виде HTML-кода и присваивание его переменной "объект"
object = urllib.request.urlopen(web_page)
# разбор HTML с помощью BeautifulSoup и присваивание его переменной "soup"
soup = BeautifulSoup(object, 'html.parser')
Для тестирования запустите скрипт и проверьте, выполняется ли он без ошибок. Если все в порядке, вы можете добавить в код следующую строку:
print(soup)
В результате скрипт должен вывести HTML-код. Затем мы переходим к поиску указанной таблицы. В нашем случае это таблица с именем "fth1" (щелкните правой кнопкой мыши на таблице и выберите опцию "Исследовать элемент/Проверить").
# проверка наличия данных в таблице
table = soup.find('table', attrs={'class': 'fth1'})
row_count = table.find_all('tr')
# подсчет количества строк в таблице, но пропуск первой строки в качестве заголовка, результат должен быть 20
print('Количество компаний:', len(row_count)-1)
Результатом будет: Количество компаний: 20
Хорошо, что дальше...
Мы сосредоточимся на создании списка и заполнении его заголовками столбцов.
# создание списка и добавление заголовка для нашей таблицы
rows = []
rows.append(['Символ', 'Название', 'Курс', 'Изменение', 'Изменение', 'Объем', 'Дата'])
print(rows)
Вышеприведенный фрагмент создаст список и выведет первую строку.
Теперь у нас уже есть база, и мы можем пройти по всей таблице в цикле, чтобы извлечь нужные нам данные. Для этого используется следующий фрагмент кода. Обратите внимание на комментарии, добавленные к коду.
# цикл для просмотра всей таблицы
for row in row_count:
data = row.find_all('td')
# проверить, содержат ли столбцы данные
if len(data) == 0:
continue
# записать содержимое столбца в переменные
symbol = data[0].getText()
name = data[1].getText()
price = data[2].getText()
change1 = data[3].getText()
change2 = data[4].getText()
volume = data[5].getText()
date = data[6].getText()
# добавить результат в список
rows.append([symbol, name, price, change1, change2, volume, date])
print(rows)
К счастью, в этом месте нет необходимости выполнять дальнейшую обработку данных, такую как удаление нежелательных символов или других сюрпризов, которые могут затруднить их чтение.
В последней части нашего скрипта мы хотим сохранить результат нашей работы в файле .csv.
# создание файла CSV и запись строк в выходной файл
with open('wig20.csv', 'w', newline='') as output_file:
csv_output = csv.writer(output_file)
csv_output.writerows(rows)
Вышеуказанный текст также можно найти на блоге iLoveData.pl, автором которого являюсь.