Подробное объяснение BeautifulSoup, общей библиотеки для поисковых роботов Python.

Python HTTPS рептилия регулярное выражение

Это 16-я статья о ежедневном изучении Python.

После изучения предыдущих статей предполагается, что вы уже облазили множество мелких и средних веб-сайтов. Но некоторые люди говорят, что обычные правила впереди трудно выучить. Регуляризация действительно сложна.Некоторые люди говорят, что если одна проблема решается с помощью регуляризации, она превращается в две проблемы. Так что учиться не нормально, не бойтесь, помимо штатной, мы можем использовать еще одну мощную библиотеку для разбора html. Итак, сегодняшняя тема — изучить эту мощную библиотеку —BeautifulSoup, но это все еще требует много практики.


Поскольку это сторонняя библиотека, нам необходимо ее загрузить.Введите следующий код в командной строке для загрузки

pip install beautifulsoup4

Установите сторонние библиотеки парсинга

pip install lxml

pip install html5lib

Если вы не знаете, как его использовать, пожалуйста, прочитайте ниже

1. Введение связанных библиотек синтаксического анализа


Официальной рекомендуемой библиотекой синтаксического анализа здесь является lxml из-за ее высокой эффективности. Все нижеследующие анализируются с использованием библиотеки разбора lxml.

2. Подробное введение в грамматику

Эта статья посвящена анализу домашней страницы Douban Books.book.douban.com/

1) Создайте объект bs

from bs4 import BeautifulSoup
import requests
response = requests.get('https://book.douban.com/').text
# print(response)
# 创建bs对象
soup = BeautifulSoup(response, 'lxml')  # 使用到了lxml解析库

2) Получить связанные теги

Этикетка:

<a data-moreurl-dict='{"from":"top-nav-click-main","uid":"0"}' href="https://www.douban.com" target="_blank">豆瓣</a>

надaЭто имя тега, самое простое — , которое можно просто понять, поскольку первое слово в — это имя тега.


# 获取标签
print(soup.li)  # 这个只是获取第一个li标签
# 结果
<li class="">
<a data-moreurl-dict='{"from":"top-nav-click-main","uid":"0"}' href="https://www.douban.com" target="_blank">豆瓣</a>
</li>

3) Получить имя и содержимое тега

Название и содержание ярлыка:

<a >豆瓣</a>

Как упоминалось выше, a — это имя метки, а содержимое между двумя метками — это то, о чем мы говорим, как указано выше.Дубанэто содержимое тега

# 获取标签名字
print(soup.li.name)
# 获取标签内容
print(soup.li.string)  # 这个只能是这个标签没有子标签才能正确获取,否则会返回None
# 结果
li
None

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

Следующее может получить его текстовое содержимое

# 获取标签内的标签
print(soup.li.a)
print(soup.li.a.string)  # 这个标签没有子标签所以可以获取到内容
# 结果
<a data-moreurl-dict='{"from":"top-nav-click-main","uid":"0"}' href="https://www.douban.com" target="_blank">豆瓣</a>
豆瓣

4) Есть два способа получить атрибуты тега

Свойства этикетки:

<a href="https://www.douban.com" target="_blank">豆瓣</a>

Можно просто понять, что атрибутРядом с именем тега и внутри предыдущего символа есть знак равенства, отражающий его.Итак, вышеhrefимя атрибута тега,Правая часть знака равенства — это значение свойства, значение выше — это URL

# 获取标签属性
print(soup.li.a['href'])  # 第一种
print(soup.li.a.attrs['href'])  # 第二种
# 结果
https://www.douban.com
https://www.douban.com

5) Получить вложенные теги внутри тега

Подтеги:

<li><a>豆瓣</a></li>

Например, мы получаемли тег,такэтикеткато естьли тегизподвкладка

# 获取标签内的标签
print(soup.li.a)
# 结果
<a data-moreurl-dict='{"from":"top-nav-click-main","uid":"0"}' href="https://www.douban.com" target="_blank">豆瓣</a>

6) Получить все дочерние узлы

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

# 获取子节点
print(soup.div.contents)  # 返回一个列表 第一种方法
for n, tag in enumerate(soup.div.contents):
   print(n, tag)
# 结果
['\n', <div class="bd">
<div class="top-nav-info">
<a class="nav-login" href="https://www.douban.com/accounts/login?source=book" rel="nofollow">登录</a>
...
0

1 <div class="bd">
<div class="top-nav-info">
...

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

7) Второй метод получает все дочерние узлы

# 第二种方法
print(soup.div.children)  # 返回的是一个迭代器
for n, tag in enumerate(soup.div.children):
   print(n, tag)

это используется.childrenПолучить все дочерние узлы, этот метод возвращает итератор

8) Получить потомки узлов метки, то есть всех потомков

потомок узла:

<ul>
<li>
<a>豆瓣</a>
</li>
</ul>

Зная свыше,ли тегдамаркировка ulизподвкладка,этикеткадали тегизподвкладка, если мы получиммаркировка ul,такИ метка li, и метка a являются потомками метки ul.

# 获取标签的子孙节点
print(soup.div.descendants)  # 返回的是一个迭代器
for n, tag in enumerate(soup.div.descendants):
   print(n, tag)
# 结果
...
<generator object descendants at 0x00000212C1A1E308>
0

1 <div class="bd">
<div class="top-nav-info">
<a class="nav-login" href="https://www.douban.com/accounts/login?source=book" rel="nofollow">登录</a>
...

используется здесь.наследственное имущество, получить узлы-потомки тега div, а возвращаемый результат — итератор

9) Получить родительский узел и все узлы-предки

Поскольку есть дочерние узлы и узлы-потомки, в свою очередь, есть родительские узлы и узлы-предки, поэтому легко понять

# 获取父节点
print(soup.li.parent)  # 返回整个父节点
# 获取祖先节点
print(soup.li.parents)  # 返回的是一个生成器
for n, tag in enumerate(soup.li.parents):
   print(n, tag)

.parentСвойство состоит в том, чтобы получить родительский узел, а возвратом является весь родительский узел, содержащий дочерний узел..parentsсостоит в том, чтобы получить все узлы-предки и вернуть генератор

10) Получить одноуровневые узлы

Родственный узел:

<ul>
<li>
<a>豆瓣1</a>
</li>
<li>
<a>豆瓣2</a>
</li>
<li>
<a>豆瓣3</a>
</li>
</ul>

Например, в приведенном выше html-коде все теги li в нем являются дочерними узлами тега ul, и все теги li находятся на одном уровне, поэтому теги li выше являются их соответствующими братьями. Это родственный узел.

# 获取兄弟节点
print(soup.li.next_siblings)  # 获取该标签的所有同级节点,不包括本身  返回的是一个生成器
for x in soup.li.next_siblings:
   print(x)
# 结果
<generator object next_siblings at 0x000002A04501F308>
<li class="on">
<a data-moreurl-dict='{"from":"top-nav-click-book","uid":"0"}' href="https://book.douban.com">读书</a>
</li>
...

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

Точно так же, поскольку есть все его следующие одноуровневые теги, есть и все его предыдущие одноуровневые теги.

soup.li.previous_siblings

Если вы только что получили один, вы можете поместить атрибут после вышеуказанногоубери букву сОК, следующим образом

soup.li.previous_sibling  # 获取前一个兄弟节点
soup.li.next_sibling  # 获取后一个兄弟节点

3. Более расширенное использование библиотеки bs

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

soup.find_all( name , attrs , recursive , text , **kwargs )

  • Так:Имя тега, который нужно получить

  • атрибуты:Получите словарь, который является ключевым значением атрибута, или напрямую замените его параметрами ключевого слова, как показано ниже.

  • рекурсивный:Установите, следует ли искать прямые дочерние узлы

  • текст:Соответствующее строковое содержимое

  • предел:Установите количество поисков

1) Сначала используйте параметр имени для поиска

# 先使用name参数
print(soup.find_all('li'))  # 返回一个列表,所有的li标签名字
# 结果
[<li class="">
<a data-moreurl-dict='{"from":"top-nav-click-main","uid":"0"}' href="https://www.douban.com" target="_blank">豆瓣</a>
</li>, <li class="on">
...

Здесь мы получаем все теги с именемliТег

2) Используйте параметры name и attrs

# 使用name和attrs参数
print(soup.find_all('div', {'class': 'more-meta'}))  # 这个对上个进行了筛选,属性参数填的是一个字典类型的
# 结果
[<div class="more-meta">
<h4 class="title">
                 刺
               </h4>
...

Здесь поиск имеет такие свойства, кактег div с class='more-meta'

3) Поиск по аргументам ключевого слова

# 对相关属性进行进行查找也可以这样
print(soup.find_all(class_='more-meta'))  # 使用关键字参数,因为class是python关键字,所以关键字参数时需要加多一个下划线来进行区别
# 结果
和上面的结果一样
...

Обратите внимание, что мы ищемТеги с атрибутом class more-meta, используя аргументы ключевого слова, но в питоне есть ключевое слово class, поэтому, чтобы не делать синтаксических ошибок, его нужнокласс с подчеркиванием

Другие параметры вводить не будем, можете зайти на официальный сайт и проверить самостоятельно

4) метод найти()

Этот метод аналогичен методу find_all(), за исключением того, что этот метод просто находит тег, то есть все теги, удовлетворяющие условиям.

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

5) метод выбора()

Этот метод использует селекторы css для фильтрации тегов.

Селектор CSS: выберите теги на основе их имени, идентификатора и атрибутов класса.

  • по имени тега: Напишите имя этикетки напрямую, например li a, это чтобы найти тег a под тегом li

  • через атрибут класса: Используйте символ ., чтобы добавить значение атрибута класса, например.title .timeЭто нужно, чтобы найти метку, значением класса которой является время под заголовком

  • через атрибут id: Используйте #, чтобы добавить значение атрибута id для поиска, например#img #width Это нужно для того, чтобы найти тег, значение идентификатора которого равно img и значение идентификатора которого равно ширине.

  • Вышеупомянутые три могут быть смешаны, например,ul .title #width

Если вы не знакомы с ним, вы можете нажать F12 прямо в браузере, чтобы просмотреть

расположение вПозиция, указанная стрелкой, является выражением селектора

код показывает, как показано ниже

# 还可以用标签选择器来进行筛选元素, 返回的都是一个列表
print(soup.select('ul li div'))  # 这个是根据标签名进行筛选
print(soup.select('.info .title'))  # 这个是根据class来进行筛选
print(soup.select('#footer #icp'))  # 这个是根据id来进行筛选
# 上面的可以进行混合使用
print(soup.select('ul li .cover a img'))

Вот атрибут get и текстовое содержимое

# 获取属性
for attr in soup.select('ul li .cover a img'):
   # print(attr.attrs['alt'])
   # 也可以这样
   print(attr['alt'])

# 获取标签的内容
for tag in soup.select('li'):
   print(tag.get_text())  # 里面可以包含子标签,会将子标签的内容连同输出

Метод .get_tex() немного отличается от предыдущего свойства .string, здесь он получит все текстовое содержимое тега, независимо от того, есть ли вложенные теги

напиши в конце

Это всего лишь несколько заметок, которые я сделал во время учебы. Есть еще некоторые недостатки.Если есть ошибки, пожалуйста, укажите большие ребята. Если вы хотите увидеть больше связанного использования, вы можете перейти к официальной документации, чтобы просмотреть:прекрасный суп. читайте документ S.IO/this_cn/latshan…

Учебные ресурсы: https://edu.hellobi.com/course/157

Если эта статья вам полезна, как насчет лайка и ретвита?

А еще я поздравляю вас всех с Днем дурака сегодня

БОЛЬШЕРасширенное чтение

◐◑Просканируйте книгу «Автостопом по Python!» и создайте PDF-файл.

◐◑ Подробное объяснение запросов в общих библиотеках поисковых роботов Python.

◐◑ Старый драйвер заставит вас использовать python для сканирования изображения девушки.



Изучайте Python каждый день

Код — это не только баги, но и красота и веселье