Skip to main content

对象的种类

Beautiful Soup将复杂的HTML文档转换为Python对象的复杂树。但是你只需要处理大约四个 kinds 对象:TagNavigableStringBeautifulSoupComment

Tag

Tag 对象对应于原始文档中的XML或HTML标记:

soup = BeautifulSoup('<b class="boldest">Extremely bold</b>')
tag = soup.b
type(tag)
# <class 'bs4.element.Tag'>

标签有很多属性和方法,我将涵盖大多数的 浏览树搜索树。现在,标记的最重要的特征是它的名称和属性。

名称

每个标签都有一个名称,可以作为 .name 访问:

tag.name
# u'b'

如果您更改标记的名称,更改将反映在Beautiful Soup生成的任何HTML标记中:

tag.name = "blockquote"
tag
# <blockquote class="boldest">Extremely bold</blockquote>

属性

标签可以具有任何数量的属性。标签 <b id="boldest"> 具有值为“boldest”的属性“id”。您可以通过像字典一样处理标记来访问标记的属性:

tag['id']
# u'boldest'

您可以直接作为 .attrs 访问该字典:

tag.attrs
# {u'id': 'boldest'}

您可以添加,删除和修改标记的属性。同样,这是通过将标签作为字典来实现的:

tag['id'] = 'verybold'
tag['another-attribute'] = 1
tag
# <b another-attribute="1" id="verybold"></b>

del tag['id']
del tag['another-attribute']
tag
# <b></b>

tag['id']
# KeyError: 'id'
print(tag.get('id'))
# None

多值属性

HTML 4定义了一些可以有多个值的属性。 HTML 5删除了它们中的一些,但是定义了更多。最常见的多值属性是 class (也就是说,一个标签可以有多个CSS类)。其它包括 relrevaccept-charsetheadersaccesskey。 Beautiful Soup将多值属性的值显示为列表:

css_soup = BeautifulSoup('<p class="body strikeout"></p>')
css_soup.p['class']
# ["body", "strikeout"]

css_soup = BeautifulSoup('<p class="body"></p>')
css_soup.p['class']
# ["body"]

如果属性 looks 喜欢它有多个值,但它不是任何版本的HTML标准定义的多值属性,Beautiful Soup将保留该属性:

id_soup = BeautifulSoup('<p id="my id"></p>')
id_soup.p['id']
# 'my id'

将标签重新转换为字符串时,会合并多个属性值:

rel_soup = BeautifulSoup('<p>Back to the <a rel="index">homepage</a></p>')
rel_soup.a['rel']
# ['index']
rel_soup.a['rel'] = ['index', 'contents']
print(rel_soup.p)
# <p>Back to the <a rel="index contents">homepage</a></p>

如果将文档解析为XML,则没有多值属性:

xml_soup = BeautifulSoup('<p class="body strikeout"></p>', 'xml')
xml_soup.p['class']
# u'body strikeout'

BeautifulSoup

BeautifulSoup 对象本身表示整个文档。对于大多数用途,您可以将其视为 Tag 对象。这意味着它支持在 浏览树搜索树 中描述的大多数方法。

由于 BeautifulSoup 对象不对应于实际的HTML或XML标记,因此它没有名称和属性。但有时它是有用的看看它的 .name,所以它被给了特殊的 .name “[文档]”:

soup.name
# u'[document]'

注释和其他特殊字符串

TagNavigableStringBeautifulSoup 几乎涵盖了您在HTML或XML文件中看到的所有内容,但有一些剩余的位。你唯一可能需要担心的是评论:

markup = "<b><!--Hey, buddy. Want to buy a used parser?--></b>"
soup = BeautifulSoup(markup)
comment = soup.b.string
type(comment)
# <class 'bs4.element.Comment'>

Comment 对象只是一种特殊类型的 NavigableString:

comment
# u'Hey, buddy. Want to buy a used parser'

但是当它作为HTML文档的一部分出现时,Comment 将以特殊的格式显示:

print(soup.b.prettify())
# <b>
#  <!--Hey, buddy. Want to buy a used parser?-->
# </b>

Beautiful Soup定义了可能出现在XML文档中的其他类的类:CDataProcessingInstructionDeclarationDoctype。就像 Comment 一样,这些类是 NavigableString 的子类,为字符串添加额外的东西。这里有一个例子,用CDATA块替换注释:

from bs4 import CData
cdata = CData("A CDATA block")
comment.replace_with(cdata)

print(soup.b.prettify())
# <b>
#  <![CDATA[A CDATA block]]>
# </b>