Запутался в методах импорта bs4 и их влиянии на атрибуты - PullRequest
0 голосов
/ 10 апреля 2019

Я знаю, что версии этого вопроса задавались в прошлом, но я все еще в замешательстве и хотел бы раз и навсегда уладить свои сомнения, если это возможно.

Если я использую

from bs4 import BeautifulSoup 

мое soup назначение будет

soup =  BeautifulSoup(html, "lxml")

Если я выполню импорт следующим образом:

from bs4 import BeautifulSoup as bs4

мое soup назначение будет

soup =  bs4(html, "lxml")

Наконец, если я импортирую, используя:

import bs4

мое назначение soup будет

soup =  bs4.BeautifulSoup(html, "lxml")

Давайте используем простой HTML и код:

html = """
<a href="some link" style="some style">Some Document</a>
"""
link = soup.select('a:contains(Document)')

Далее основной вопрос:

type(link[0])

Вывод - во всех трех случаях импорта - это:

bs4.element.Tag

Но если я спрашиваю:

isinstance(link[0],bs4.element.Tag)

В третьем случае я получаю True, но в первых двух случаях я получаю

AttributeError: type object 'BeautifulSoup' has no attribute 'element'

, поскольку методы select() и find_all() часто дают результаты как Tag, так и NavigableString., Мне нужно определить, кто какой использует, например, isinstance().Так что, в этих случаях мне нужно использовать третий метод импорта?Почему разница в первую очередь?

1 Ответ

1 голос
/ 10 апреля 2019

Это игра с именами, которую вы делаете.Давайте продолжим и заявим, что класс bs4.element.Tag является классом экземпляров элементов.Думайте об этом как об абсолютном местоположении класса Tag в bs4.bs4.element представляет вложенные модули, где Tag (который находится в модуле element) является классом, в котором элементы являются экземплярами.При отображении информации о классе этих элементов всегда будет отображаться bs4.element.Tag.

Теперь, после всего сказанного, вы можете получить доступ к объекту BeautifulSoup различными способами.И это не меняет того факта, что теги элементов имеют тип bs4.element.Tag.При импорте bs4:

import bs4
bs4.BeautifulSoup()

Импортирует модуль под именем модуля по умолчанию bs4.И тогда вы можете получить доступ к BeautifulSoup в этом модуле с точечной нотацией, так как BeautifulSoup является членом этого модуля.Но локально bs4 - это просто переменная, которая ссылается на модуль bs4.

Когда вы импортируете как:

from bs4 import BeautifulSoup as bs4

bs4, это не означает то же самое, что и в первом примере,В первом примере мы импортировали весь модуль с именем по умолчанию (bs4), но здесь мы вместо этого импортируем класс BeautifulSoup и переименуем его локально как bs4.Независимо от того, что мы называем это локально, это все еще класс в bs4.BeautifulSoup, где bs4 - имя модуля.Хотя локально (локально для этого файла) мы создали переменную ссылку на класс BeautifulSoup с именем, которое совпадает с именем модуля.

Итак, когда вы используете select для возврата элементовони относятся к типу bs4.element.Tag.Это верно независимо от того, какие локальные переменные названы.Это то, как они внутренне известны.

Итак, при сравнении instance важно знать, что имя переменной не важно, важно то, на что ссылается переменная.В третьем примере import bs4 заставляет bs4 ссылаться на модуль bs4;следовательно, Tag можно получить по адресу bs4.element.Tag.Но в случае использования from bs4 import BeautifulSoup as bs4, bs4 больше не ссылается на модуль bs4, он ссылается на класс BeautifulSoup, который не имеет атрибутов с именем element с атрибутом Tag, поскольку он не является модулемно класс.

Локальное имя - это то, как ваш текущий файл ссылается на объект, на который он ссылается.

Так что в ваших неудачных случаях вам нужно будет импортировать ссылку Tag впеременная, которую вы можете предоставить instance:

>>> from bs4 import BeautifulSoup
>>> from bs4.element import Tag
>>> soup = bs4.BeautifulSoup('<div>Test<span>test</span><span>test2</span></div>')
>>> isinstance(soup.find('div'), Tag)
True

Tag, это просто имя, но оно ссылается на bs4.element.Tag, так что оно работает.

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

>>> from bs4 import BeautifulSoup
>>> from bs4.element import Tag as Apple
>>> soup = bs4.BeautifulSoup('<div>Test<span>test</span><span>test2</span></div>')
>>> isinstance(soup.find('div'), Apple)
True

Надеюсь, это имеет смысл:).

РЕДАКТИРОВАТЬ: просто подсказка, но bs4 дает некоторые ссылкидля таких вещей, как NavigableString и Tag, доступных в модуле верхнего уровня, поэтому вам не нужно доходить до bs4.element, чтобы получить правильную ссылку, вы можете просто сделать:

from bs4 import Tag, NavigableString

Опять же, эта альтернативная ссылка bs4.Tag является просто переменной named Tag в модуле bs4, который относится к фактическому классу bs4.element.Tag.Вы можете использовать это, и это все еще будет относиться к тому же классу.Он просто используется локально в модуле bs4 для ссылки на класс Tag в element.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...