CoderCastrov logo
CoderCastrov
Парсер

Иерархический парсинг веб-страниц с помощью Python

Иерархический парсинг веб-страниц с помощью Python
просмотров
4 мин чтение
#Парсер

Одна из наиболее сложных задач при парсинге веб-страниц - это работа с иерархическими данными. То есть данными, которые находятся на разных страницах.

Если вы ищете простой способ получить данные с каждой страницы без ручной обработки, то не ищите дальше. Мы будем использовать две популярные библиотеки Python для этой цели:

  • Requests
  • BeautifulSoup

В этом примере мы будем использовать Топ-250 фильмов IMDb. Вы можете следовать за нами в этой записной книжке Kaggle!


Получение названия каждого фильма

Мы быстро рассмотрим получение основной информации, так как это относительно просто. Если вам нужны более подробные сведения, я рассмотрел это в предыдущей статье на Medium.

Мы видим, что вся информация о фильмах находится в основном теле таблицы:

Table Body

Каждый фильм имеет строку в этой таблице. Внутри этих строк есть столбцы. Столбец, который содержит название фильма, имеет класс "titleColumn":

Title Column

Теперь получение названия фильма здесь легко. Мы можем просто использовать библиотеку requests для получения страницы и перебирать строки. Для каждой строки мы можем перейти к столбцу с названием и получить название фильма внутри тега <a>:

Movie Titles Printed

Аналогично, мы можем получить год выпуска в том же столбце, который находится внутри тега <span>:

Movie Title and Year

Углубляемся в изучение

Предположим, нам нужна дополнительная информация о каждом фильме, которая не указана на странице списка Топ-250. Мы хотим добавить жанр фильма, который можно найти на странице каждого отдельного фильма:

Movie Genre

В нижнем левом углу скриншота мы видим категории жанров, к которым принадлежит фильм. Поэтому нам нужно перейти на каждую отдельную страницу фильма, чтобы получить эту информацию.

К счастью, ссылка на страницу находится прямо на главной странице Топ-250. Нажатие на название фильма отправит нас сюда. Если мы откроем инструменты разработчика (нажмите F12 в браузере), мы увидим, что эта ссылка находится внутри тега <a>, который мы использовали для получения названия фильма:

Movie Title Link

Ссылка находится в части "href" тега <a>. К счастью, BeautifulSoup предоставляет нам инструмент для извлечения этой части тега:

link = item.find('a')['href']

Это очень похоже на запись, используемую для среза строк или списков. В этом случае мы можем получить данные из разных элементов внутри тега.

Запрос страницы каждого фильма

В нашем случае нам нужно получить это для каждого фильма в списке, что означает, что мы должны перебирать ранее созданные строки:

for row in rows:
    link = column.a['href']

И мы можем вывести ссылки на каждый фильм:

Movie Links

Ссылки не имеют длинной строки запроса, которую мы видели в DevTools, однако они работают так же и перенаправляют нас на правильную страницу.

Теперь нам просто нужно запросить эту страницу, имейте в виду, что это не полная ссылка. Мы должны добавить часть домена:

for row in rows:
    link = column.a['href']
    movie_page = requests.get(f'https://imdb.com/{link}').content

После получения содержимого страницы нам нужно его разобрать, чтобы получить раздел с жанром:

for row in rows:
    link = column.a['href']
    movie_page = requests.get(f'https://imdb.com/{link}').content
    movie_soup = BeautifulSoup(movie_page, 'html.parser')

Поиск жанров фильмов

Теперь нам просто нужно выяснить, где находится название жанра на странице:

Таким образом, каждый жанр находится внутри тега <a> с длинным именем класса. Это можно легко добавить к итерации по строкам:

for row in rows:
    link = column.a['href']
    movie_page = requests.get(f'https://imdb.com/{link}').content
    movie_soup = BeautifulSoup(movie_page, 'html.parser')
    genre = movie_soup.find('span', 'sc-16ede01-3 bYNgQ ipc-chip ipc-chip--on-baseAlt')

Если мы выведем жанр на этом этапе, мы получим неожиданный результат:

Мы выводим только один жанр для каждого фильма. Конкретно, первый жанр в html.

Конечно, мы знаем, что у фильма может быть несколько жанров, что показано на скриншотах The Godfather выше. Поэтому нам нужно пройти по жанрам. Мы можем сделать это, используя метод "find_all" и немного спискового включения:

И, наконец, мы можем присоединить это к основным названиям фильмов и датам выпуска:

Это самый глубокий уровень, на котором мы остановимся в этом примере, но вы можете уйти гораздо глубже, чем на два уровня в иерархии, используя этот метод.

Заключение

В этом руководстве было рассмотрено многое, и теперь вы должны быть в состоянии:

  • Запросить веб-страницу
  • Извлечь информацию с этой страницы
  • Найти другие веб-страницы, содержащие нужную информацию
  • Собрать информацию с этих страниц

На практически любом веб-сайте. Если у вас есть вопросы, пожалуйста, задавайте их в комментариях!


_Если вам это помогло, подумайте о __подписке на мой твиттер _для получения ежедневных советов и статей по программированию.