对bs4命名方法及其对属性的影响感到困惑

时间:2019-04-10 16:54:06

标签: beautifulsoup

我知道过去曾问过这个问题,但是我仍然很困惑,如果可能的话,我想一劳永逸地解决我的疑问。

如果我使用

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()方法经常传递TagNavigableString结果,因此我需要使用isinstance()确定哪个是哪个。因此,在这些情况下,我必须使用第三种导入方法吗?为什么首先要有区别?

1 个答案:

答案 0 :(得分:1)

这是您正在做的命名游戏。让我们继续说一下,类bs4.element.Tag是元素实例的类。可以将其视为Tagbs4类的绝对位置。 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对顶层模块中可用的NavigableStringTag之类的内容进行了一些引用,因此您不必一路走来到bs4.element以获得正确的参考,您只需执行以下操作:

from bs4 import Tag, NavigableString

同样,bs4.Tag的替代引用只是Tag模块中名为bs4的变量,它引用实际的bs4.element.Tag类。您可以使用它,它仍将引用同一类。只是在bs4模块中本地使用它来引用Tag中的element类。