BeautifulSoup的高级应用 之.parent .parents .next_sibling.previous_sibling.next_siblings.previous_siblings

继上一篇BeautifulSoup的高级应用,主要讲解的是contents children descendants string strings stripped_strings,本篇主要讲解.parent .parents .next_sibling .previous_sibling .next_siblings .previous_siblings

本篇博客继续使用上篇的html页面内容:

html_doc = """ 
<html>
<head><title>The Dormouse's story</title></head> 
<p class="title"><b>The Dormouse's story</b></p> 
<p class="story">Once upon a time there were three little sisters; and their names were 
<a href="http://example.com/elsie" class="sister" id="link1">Elsie</a>, 
<a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and
<a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>; and they lived at the bottom of a well.</p> 
<p class="story">...</p> 
</html>"""

继续分析文档树 ,每个 tag或字符串都有父节点 :被包含在某个 tag中
.parent:
通过 .parent 属性来获取某个元素的父节点.在例子html文档中,标签是标签的父节点:

title_tag = soup.title 
title_tag
# <title>The Dormouse's story</title> 
title_tag.parent 
# <head><title>The Dormouse's story</title></head>

文档title的字符串也有父节点:标签

title_tag.string.parent 
# <title>The Dormouse's story</title>

文档的顶层节点比如的父节点是 BeautifulSoup 对象:

html_tag = soup.html 
type(html_tag.parent) 
# <class 'bs4.BeautifulSoup'>

BeautifulSoup 对象的 .parent 是None。

.parents
通过元素的.parents属性可以递归得到元素的所有父辈节点 , 下面的例子使用了 .parents方 法遍历了 标签到根节点 的所有节点:

link = soup.a 
link 
# <a class="sister" href="http://example.com/elsie" id="link1">Elsie</a> 
for parent in link.parents: 
    if parent is None: 
        print(parent) 
    else: 
        print(parent.name) 
# p 
# body 
# html 
# [document] 
# None

兄弟节点
举例说明:

<a>
    <b>text1</b>
    <c>text2</c>
</a>

这里的b和c节点为兄弟节点
.next_sibling 和 .previous_sibling .:
在文档树中 ,使用 .next_sibling 和 .previous_sibling 属性来查询兄弟节点:

sibling_soup = BeautifulSoup("<a><b>text1</b><c>text2</c></b></a>")
sibling_soup.b.next_sibling   
# <c>text2</c> 
sibling_soup.c.previous_sibling 
# <b>text1</b>

b 标签有.next_sibling 属性 ,但是没有 .previous_sibling 属性 ,因为 b标签在同级节点中是第一个 .同理 ,c标签有 .previous_sibling 属性 ,却没有 .next_sibling 属性 。

link = soup.a link 
# <a class="sister" href="http://example.com/elsie" id="link1">Elsie</a> 
link.next_sibling 
# u',\n'

注意:第一个a标签的next_sibling 属性值为 ,\n

link.next_sibling.next_sibling 
# <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>

第一个a标签的next_sibling的next_sibling 属性值为Lacie

.next_siblings.previous_siblings.
通过 .next_siblings 和 .previous_siblings 属性对当前节点的兄弟节点迭代输出:

for sibling in soup.a.next_siblings: 
    print(repr(sibling)) # u',\n' 
# <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a> 
# u' and\n' 
# <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a> 
# u'; and they lived at the bottom of a well.' 
# None 
for sibling in soup.find(id="link3").previous_siblings:                                 print(repr(sibling)) 
# ' and\n' 
# <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a> 
# u',\n'
# <a class="sister" href="http://example.com/elsie" id="link1">Elsie</a> 
# u'Once upon a time there were three little sisters; and their names were\n' 
# None

回退和前进:
举例html如下:

<html><head><title>The Dormouse's story</title></head> <p class="title"><b>The Dormouse's story</b></p>

HTML 解析器把这段字符串转换成一连的事件 : “ 打开标签 ”添加一段字符串 ”,关闭 标签 ”,”打开

标签 ”, 等.Beautiful Soup提供了重现解析器初始化过程的方法

.next_element 和 .previous_element .
.next_element 属性指向解析过程中下一个被的对象 (字符串或 tag),结果可能 与 .next_sibling 相同 ,但通常是不一样的 .

last_a_tag = soup.find("a", id="link3") 
last_a_tag 
# <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a> 
last_a_tag.next_sibling 
# '; and they lived at the bottom of a well.'

但这个 标签的 .next_element 属性结果是在标签被解析之后的内容 ,不是 标 签后的句子部分 ,应该是字符串 ”Tillie”:

last_a_tag.next_element 
# u'Tillie'

.previous_element 属性刚好与.next_element 相反 ,它指向当前被解 析的对象的前一个解析对象 :

last_a_tag.previous_element 
# u' and\n' 
last_a_tag.previous_element.next_element
# <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>

.next_elements 和 .previous_elements
通过 .next_elements 和 .previous_elements 的迭代器就可以向前或后访问文档解析内容 ,就好像文档正在被解析一样 :

for element in last_a_tag.next_elements:                  print(repr(element)) 
# u'Tillie' 
# u';\nand they lived at the bottom of a well.' 
# u'\n\n' 
# <p class="story">...</p> 
# u'...' 
# u'\n' 
# None

下一篇 将讲解一下BeautifulSoup的搜索文档树的高级方法。

### 使用 BeautifulSoup 进行 HTML/XML 节点遍历 Beautiful Soup 提供了多种方式来遍历 HTML 或 XML 文档中的节点。以下是几种常见的遍历方法及其说明: #### 下行遍历 通过 `tag.contents` 和 `tag.children` 可以实现向下遍历子节点的操作。 - **`tag.contents`**: 返回当前标签的所有直接子节点组成的列表,包括文本节点和标签节点[^5]。 ```python html_doc = "<html><head></head><body><p>First</p><p>Second</p></body></html>" soup = BeautifulSoup(html_doc, "html.parser") body_tag = soup.body print(body_tag.contents) # 输出 [<p>First</p>, <p>Second</p>] ``` - **`tag.children`**: 返回一个迭代器对象,用于逐一遍历当前标签的直接子节点。 ```python for child in body_tag.children: print(child) # 输出 <p>First</p>\n<p>Second</p> ``` #### 上行遍历 可以通过 `.parent` 属性访问父节点。 - **`.parent`**: 获取当前节点的父节点。 ```python p_tag = soup.p print(p_tag.parent.name) # 输出 'body' ``` #### 平行遍历 平行遍历指的是在同一层次上移动到前后的兄弟节点。 - **`.next_sibling` / `.previous_sibling`**: 访问下一个或上一个兄弟节点。 ```python first_p = soup.find('p') second_p = first_p.next_sibling print(second_p) # 输出 <p>Second</p> ``` #### 子孙遍历 如果需要遍历所有的后代节点而不仅仅是直接子节点,则可以使用 `descendants` 方法。 - **`tag.descendants`**: 返回所有后代节点的迭代器。 ```python for descendant in soup.html.descendants: print(descendant) ``` 上述方法可以帮助开发者灵活地定位并提取文档中的特定部分数据。 ### 总结 通过对 `contents`, `children`, `parents`, `siblings`, 和 `descendants` 的合理运用,能够高效完成对 HTML/XML 结构化数据的不同维度上的遍历需求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值