Одной из наиболее сложных задач при просмотре веб-страниц является работа с иерархическими данными. То есть данные, которые живут на разных страницах.
Если вы ищете простой способ получить данные с каждой страницы, не просматривая их вручную, не ищите дальше. Для этого мы будем использовать две популярные библиотеки Python:
- Запросы
- КрасивыйСуп
В этом примере мы будем использовать 250 лучших фильмов IMDb. Вы можете следить в этой тетради kaggle!
Получение названия каждого фильма
Мы быстро перейдем к получению основной информации, так как это относительно просто. Если вам нужны подробности, я рассказал об этом в предыдущей статье на Medium.
Мы видим, что вся информация о фильме находится в теле основной таблицы:
У каждого фильма есть строка в этой таблице. Внутри этих строк есть столбцы. Столбец, содержащий название фильма, имеет класс titleColumn:
Отсюда легко получить название фильма. Мы можем просто использовать библиотеку запросов, чтобы получить страницу и выполнить итерацию по строкам. Для каждой строки мы можем перейти к столбцу title и получить название фильма внутри тега <a>
:
Точно так же мы можем получить год выпуска в том же столбце, который находится внутри тега <span>
:
Погружение глубже
Допустим, нам нужна информация о каждом фильме, которого нет на странице списка 250 лучших. Мы хотим добавить жанр фильма, который можно найти на отдельной странице фильма:
В левом нижнем углу скриншота указаны жанровые категории, к которым относится фильм. Поэтому нам нужно перейти на каждую отдельную страницу фильма, чтобы получить эту информацию.
К счастью, ссылка на эту страницу находится прямо на главной странице топ-250. Щелкнув по названию фильма, мы отправимся сюда. Если мы откроем DevTools (нажмите F12 в браузере), мы увидим, что эта ссылка находится внутри тега <a>
, который мы использовали для получения названия фильма:
Ссылка находится в части «href» тега <a>
. К счастью, BeautifulSoup дает нам только инструмент для захвата этой части тега:
link = item.find('a')['href']
Это очень похоже на нотацию, используемую для нарезки строк или списков. В этом случае мы можем получить данные из разных элементов внутри тега.
Запрос страницы каждого фильма
В нашем случае нам нужно будет получить это для каждого из фильмов в списке, что будет означать повторение строк, которые мы создали ранее:
for row in rows: link = column.a['href']
И мы можем распечатать ссылки на каждый из фильмов:
Ссылки не имеют длинной строки запроса, которую мы видели в 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.
Конечно, мы знаем, что в фильме их может быть несколько, что показано на скриншотах «Крестного отца» выше. Итак, нам нужно перебирать жанры. Мы можем сделать это с помощью метода «find_all» и некоторого понимания списка:
И, наконец, мы можем привязать его к основным названиям фильмов и датам выхода:
Это настолько глубоко, насколько мы пойдем в этом примере, но вы можете углубиться в иерархию более чем на два уровня, используя этот метод.
Заключение
Это охватило довольно много, теперь вы должны быть в состоянии:
- Запрос веб-страницы
- Извлечь информацию с этой страницы
- Найдите другие веб-страницы, содержащие нужную вам информацию
- Соберите информацию с этих страниц
Практически на любом сайте. Дайте мне знать, если у вас есть какие-либо вопросы в комментариях!
Если вам это помогло, подпишитесь на меня в Twitter, чтобы получать больше ежедневных советов и статей по программированию.