Unlimited Plugins, WordPress themes, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Code
  2. Python
Code

Скрапинг веб-страниц в Python с Beautiful Soup: поиск и модификация DOM

by
Difficulty:IntermediateLength:MediumLanguages:
This post is part of a series called Scraping Webpages in Python with Beautiful Soup.
Scraping Webpages in Python With Beautiful Soup: The Basics

Russian (Pусский) translation by Anna k.Ivanova (you can also view the original English article)

В последнем уроке вы узнали основы библиотеки Beautiful Soup. Помимо навигации по дереву DOM, вы также можете искать элементы с заданным class или id. Вы также можете изменить дерево DOM с помощью этой библиотеки.

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

Фильтры для поиска по дереву

У Beautiful Soup есть много способов поиска в дереве DOM. Эти методы очень похожи и используют фильтры того же типа, что и аргументы. Поэтому имеет смысл правильно понять различные фильтры, прежде чем читать о методах. Я буду использовать тот же метод find_all(), чтобы объяснить разницу между различными фильтрами.

Самый простой фильтр, который вы можете передать любому методу поиска, - это строка. Beautiful Soup будет искать в документе, чтобы найти тег, который точно соответствует строке.

Вы также можете передать объект регулярного выражения методу find_all(). На этот раз Beautiful Soup будет фильтровать дерево, сопоставляя все теги с заданным регулярным выражением.

Код будет искать все теги, начинающиеся с «h», а за ними следует цифра от 1 до 6. Другими словами, он будет искать все теги заголовка в документе.

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

Вы также можете передать True в качестве параметра методу find_all(). Затем код вернет все теги в документе. Выведенный ниже результат означает, что в настоящее время на странице Википедии есть 4 339 тегов, которые мы анализируем.

Если вы все еще не можете найти то, что ищете, с помощью любого из перечисленных выше фильтров, вы можете определить свою собственную функцию, которая принимает элемент в качестве единственного аргумента. Функция также должна вернуть True, если есть совпадение, а False - в противном случае. В зависимости от того, что вам нужно, вы можете сделать эту функцию настолько сложной, насколько это необходимо для выполнения задания. Вот очень простой пример:

Вышеупомянутая функция проходит через ту же страницу на Википедии Python и ищет неупорядоченные списки, в которых более 20 детей.

Поиск дерева DOM с использованием встроенных функций

Одним из самых популярных методов поиска по DOM является find_all(). Он пройдет через всех потомков тега и вернет список всех потомков, соответствующих вашим критериям поиска. Этот метод имеет следующую сигнатуру:

Аргумент name - это имя тега, к которому вы хотите, чтобы эта функция выполнялась при просмотре дерева. Вы можете предоставить строку, список, регулярное выражение, функцию или значение True в качестве имени.

Вы также можете фильтровать элементы в дереве DOM на основе разных атрибутов, таких как id, href и т.д. Вы также можете получить все элементы с определенным атрибутом независимо от его значения, используя attribute=True. Поиск элементов с определенным классом отличается от поиска обычных атрибутов. Поскольку class является зарезервированным ключевым словом в Python, вам придется использовать аргумент ключевого слова class_ при поиске элементов с определенным классом.

Вы можете видеть, что в документе есть 1734 тега с атрибутом class и 425 тегами с атрибутом id. Если вам нужны только первые из этих результатов, вы можете передать число методу в качестве значения limit. Передача этого значения даст указание Beautiful Soup прекратить поиск большего количества элементов, как только он достигнет определенного числа. Вот пример:

Когда вы используете метод find_all(), вы говорите Beautiful Soup, чтобы пройти через всех потомков данного тега, чтобы найти то, что вам нужно. Иногда вы хотите искать элемент только в прямых дочерних элементах в теге. Это может быть достигнуто путем передачи recursive=False методу find_all().

Если вам интересно найти только один результат для определенного поискового запроса, вы можете использовать метод find(), чтобы найти его, а не передавать limit=1 в find_all(). Единственная разница между результатами, возвращаемыми этими двумя методами, заключается в том, что find_all() возвращает список только с одним элементом, а find() просто возвращает результат.

Методы find() и find_all() осуществляют поиск по всем потомкам данного тега для поиска элемента. Есть еще десять очень похожих методов, которые можно использовать для итерации через дерево DOM в разных направлениях.

Методы find_parent() и find_parents() обходят дерево DOM, чтобы найти данный элемент. Методы find_next_sibling() и find_next_siblings() будут перебирать всех братьев и сестер элемента, следующего за текущим. Точно так же методы find_previous_sibling() и find_previous_siblings() будут перебирать всех братьев и сестер элемента, которые идут до текущего.

Методы find_next() и find_all_next() будут перебирать все теги и строки, которые появляются после текущего элемента. Аналогично, методы find_previous() и find_all_previous() будут перебирать все теги и строки, которые предшествуют текущему элементу.

Вы также можете искать элементы с помощью селекторов CSS с помощью метода select(). Вот несколько примеров:

Изменение дерева

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

Продолжая наш последний пример, вы можете заменить содержимое тега на заданную строку, используя атрибут .string. Если вы не хотите заменять содержимое, но добавляете что-то лишнее в конце тега, вы можете использовать метод append().

Аналогично, если вы хотите вставить что-то внутри тега в определенном месте, вы можете использовать метод insert(). Первым параметром для этого метода является позиция или индекс, в который вы хотите вставить содержимое, а второй параметр - это сам контент. Вы можете удалить все содержимое внутри тега, используя метод clear(). Он просто оставит вас с самим тегом и его атрибутами.

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

Теперь исходный заголовок можно выбрать с помощью h3: nth-of-type (2). Если вы полностью хотите удалить элемент или тег и весь контент внутри него из дерева, вы можете использовать метод decompose().

После того, как вы разложили или удалили исходный заголовок, заголовок в третьем месте займет свое место.

Если вы хотите удалить тег и его содержимое из дерева, но не хотите полностью уничтожить тег, вы можете использовать метод extract(). Этот метод вернет тег, который он извлек. Теперь у вас будет два разных дерева, которые вы можете проанализировать. Корнем нового дерева будет тег, который вы только что извлекли.

Вы также можете заменить тег внутри дерева чем-то другим по вашему выбору, используя метод replace_with(). Этот метод вернет тег или строку, которые он заменил. Это может быть полезно, если вы хотите поместить замененное содержимое в другое место в документе.

В приведенном выше коде основной заголовок документа был заменен тегом b. В документе больше нет тега h1, поэтому print(soup.h1) теперь печатает None.

Финальные мысли

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

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

Advertisement
Advertisement
Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.