CoderCastrov logo
CoderCastrov
Питон

Использование парсинга для извлечения данных с веб-страниц

Использование парсинга для извлечения данных с веб-страниц
просмотров
6 мин чтение
#Питон

Парсинг данных с веб-страниц - это процесс извлечения данных с веб-страниц. Цели парсинга могут быть разными:

  • Недвижимость - предложения о домах или квартирах
  • Маркетинг и продажи
  • Сравнение цен на товары
  • Мониторинг цен на авиабилеты

Вызовы парсинга в большом масштабе

Вы должны парсить 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, который проведет вас через несколько шагов, от создания первого бота до добавления дополнительных аргументов.

Пример скрипта

В качестве примера рассмотрим построение основного скрипта, который:

  1. Получает таблицу с компаниями из индекса WIG20 на сайте Stooq.pl
Stooq.pl, список компаний WIG20

Чтобы понять, как к этому подойти, сначала изучим структуру страницы. Чтобы проверить это, щелкните правой кнопкой мыши и выберите опцию "Исследовать элемент/Проверить".

Исследование элемента

В таблице хранятся данные, которые мы будем захватывать и обрабатывать. Каждый из элементов, который нас интересует, представляет собой строку в таблице <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, автором которого являюсь.