📅  最后修改于: 2020-11-09 14:29:56             🧑  作者: Mango
在本章中,我们将讨论有关“通过标签导航”的内容。
以下是我们的html文档-
>>> html_doc = """
Tutorials Point
The Biggest Online Tutorials Library, It's all Free
Top 5 most used Programming Languages are:
Java,
C,
Python,
JavaScript and
C;
as per online survey.
Programming Languages
"""
>>>
>>> from bs4 import BeautifulSoup
>>> soup = BeautifulSoup(html_doc, 'html.parser')
>>>
基于上述文档,我们将尝试从文档的一部分移至另一部分。
在任何HTML文档中,元素的重要组成部分之一是标签,其中可能包含其他标签/字符串(标签的子元素)。 Beautiful Soup提供了不同的方式来导航和遍历标签的子对象。
搜索分析树的最简单方法是按其名称搜索标签。如果您想要
标签,请使用soup.head->>> soup.head
&t;title>Tutorials Point
>>> soup.title
Tutorials Point
在
标签中获取特定标签(例如第一个标签)。>>> soup.body.b
The Biggest Online Tutorials Library, It's all Free
使用标签名称作为属性将只给您该名称的第一个标签-
>>> soup.a
Java
要获取标签的所有属性,可以使用find_all()方法-
>>> soup.find_all("a")
[Java, C, Python, JavaScript, C]>>> soup.find_all("a")
[Java, C, Python, JavaScript, C]
我们可以通过其.contents在列表中搜索标签的孩子-
>>> head_tag = soup.head
>>> head_tag
Tutorials Point
>>> Htag = soup.head
>>> Htag
Tutorials Point
>>>
>>> Htag.contents
[Tutorials Point
>>>
>>> Ttag = head_tag.contents[0]
>>> Ttag
Tutorials Point
>>> Ttag.contents
['Tutorials Point']
BeautifulSoup对象本身具有子级。在这种情况下,标记是BeautifulSoup对象的子代-
>>> len(soup.contents)
2
>>> soup.contents[1].name
'html'
字符串没有.contents,因为它不能包含任何内容-
>>> text = Ttag.contents[0]
>>> text.contents
self.__class__.__name__, attr))
AttributeError: 'NavigableString' object has no attribute 'contents'
而不是将它们获取为列表,而是使用.children生成器来访问标签的孩子-
>>> for child in Ttag.children:
print(child)
Tutorials Point
.descendants属性允许您递归遍历标签的所有子元素-
它的直系子孙及其直系子孙的子孙,依此类推-
>>> for child in Htag.descendants:
print(child)
Tutorials Point
Tutorials Point
>>> len(list(soup.children))
2
>>> len(list(soup.descendants))
33
如果标记只有一个孩子,并且该孩子是NavigableString,则该孩子可以作为。字符串-
>>> Ttag.string
'Tutorials Point'
如果标签的唯一子对象是另一个标签,并且该标签具有。字符串,则认为父标签具有相同的标签。字符串作为其子-
>>> Htag.contents
[Tutorials Point ]
>>>
>>> Htag.string
'Tutorials Point'
但是,如果标签包含多个内容,则不清楚是什么。字符串应该引用,所以。字符串定义为None-
>>> print(soup.html.string)
None
如果标记中包含多个内容,您仍然可以只查看字符串。使用 。字符串生成器-
>>> for string in soup.strings:
print(repr(string))
'\n'
'Tutorials Point'
'\n'
'\n'
"The Biggest Online Tutorials Library, It's all Free"
'\n'
'Top 5 most used Programming Languages are: \n'
'Java'
',\n'
'C'
',\n'
'Python'
',\n'
'JavaScript'
' and\n'
'C'
';\n \nas per online survey.'
'\n'
'Programming Languages'
'\n'
要删除多余的空格,请使用.stripped_strings生成器-
>>> for string in soup.stripped_strings:
print(repr(string))
'Tutorials Point'
"The Biggest Online Tutorials Library, It's all Free"
'Top 5 most used Programming Languages are:'
'Java'
','
'C'
','
'Python'
','
'JavaScript'
'and'
'C'
';\n \nas per online survey.'
'Programming Languages'
用“家族树”的比喻来说,每个标签和每个字符串都有一个父对象:包含它的标签:
要访问元素的父元素,请使用.parent属性。
>>> Ttag = soup.title
>>> Ttag
Tutorials Point
>>> Ttag.parent
title>Tutorials Point
在我们的html_doc中,标题字符串本身有一个父:包含它的
>>> Ttag.string.parent
Tutorials Point
像这样的顶级标签的父对象是Beautifulsoup对象本身-
>>> htmltag = soup.html
>>> type(htmltag.parent)
Beautifulsoup对象的.parent定义为None-
>>> print(soup.parent)
None
要遍历所有父元素,请使用.parents属性。
>>> link = soup.a
>>> link
Java
>>>
>>> for parent in link.parents:
if parent is None:
print(parent)
else:
print(parent.name)
p
body
html
[document]
以下是一个简单的文档-
>>> sibling_soup = BeautifulSoup("TutorialsPointThe Biggest Online Tutorials Library, It's all Free ")
>>> print(sibling_soup.prettify())
TutorialsPoint
The Biggest Online Tutorials Library, It's all Free
在上述文档中,和
使用.next_sibling和.previous_sibling在解析树的同一级别上的页面元素之间导航:
>>> sibling_soup.b.next_sibling
The Biggest Online Tutorials Library, It's all Free
>>>
>>> sibling_soup.c.previous_sibling
TutorialsPoint
标记具有.next_sibling但没有.previous_sibling,因为在树的同一级别上标记之前没有任何内容,
>>> print(sibling_soup.b.previous_sibling)
None
>>> print(sibling_soup.c.next_sibling)
None
这两个字符串不是兄弟姐妹,因为它们没有相同的父对象。
>>> sibling_soup.b.string
'TutorialsPoint'
>>>
>>> print(sibling_soup.b.string.next_sibling)
None
要遍历标签的兄弟姐妹,请使用.next_siblings和.previous_siblings。
>>> for sibling in soup.a.next_siblings:
print(repr(sibling))
',\n'
C
',\n'
>a class="prog" href="https://www.tutorialspoint.com/python/index.htm" id="link3">Python
',\n'
JavaScript
' and\n'
C
';\n \nas per online survey.'
>>> for sibling in soup.find(id="link3").previous_siblings:
print(repr(sibling))
',\n'
C
',\n'
Java
'Top 5 most used Programming Languages are: \n'
现在让我们回到前面的“ html_doc”示例的前两行:
&t;html>Tutorials Point
The Biggest Online Tutorials Library, It's all Free
HTML解析器需要以上字符的字符串,并把它转换为一系列像“打开一个标签”,“打开一个
标签”,事件“打开标记或字符串的.next_element属性指向之后立即解析的内容。有时它看起来与.next_sibling类似,但是并不完全相同。以下是我们的“ html_doc”示例文档中的最后一个标记。
>>> last_a_tag = soup.find("a", id="link5")
>>> last_a_tag
C
>>> last_a_tag.next_sibling
';\n \nas per online survey.'
但是,该标记的.next_element(紧接在标记之后的内容)不是该句子的其余部分:它是单词“ C”:
>>> last_a_tag.next_element
'C'
以上行为是因为在原始标记中,字母“ C”出现在该分号之前。解析器遇到一个标记,然后是字母“ C”,然后是结束标记,然后是分号和句子的其余部分。分号与标记处于同一级别,但是首先遇到字母“ C”。
.previous_element属性与.next_element完全相反。它指向此元素之前立即解析的任何元素。
>>> last_a_tag.previous_element
' and\n'
>>>
>>> last_a_tag.previous_element.next_element
C
我们使用这些迭代器向前和向后移动到一个元素。
>>> for element in last_a_tag.next_e lements:
print(repr(element))
'C'
';\n \nas per online survey.'
'\n'
Programming Languages
'Programming Languages'
'\n'