鱼C论坛

 找回密码
 立即注册
查看: 12016|回复: 30

[技术交流] python爬虫进阶BeautifulSoup节点

[复制链接]
发表于 2017-7-10 11:18:01 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 MSK 于 2017-7-10 11:23 编辑

节点





这一帖的内容可能有点多,请大家耐心
推荐阅读:BeautifulSoup对象

-----------------------------------------------------------------------------------------------------------------------------------------------------------
子节点





在html文档中一个Tag可能包含多个字符串或其它的Tag,这些都是这个Tag的子节点

<title>就是<head>的子节点,反过来<head>就是<title>的父节点
注意: Beautiful Soup中字符串节点不支持这些属性,因为字符串没有子节点



  1. <head><title>标题</title></head>
复制代码



Beautiful Soup提供了许多操作和遍历子节点的属性.



最简单的方法就是告诉它你想获取的tag的name.如果想获取 <head> 标签,只要用 soup.head :


  1. soup.head
  2. # <head><title>The Dormouse's story</title></head>
复制代码



获取<title>标签
  1. soup.title
  2. # <title>The Dormouse's story</title>
复制代码



你也可以多次调用这个方法
  1. soup.head.title
  2. # <title>The Dormouse's story</title>
复制代码







但是!!!



通过点取属性的方式只能获得当前名字的第一个tag!


通过点取属性的方式只能获得当前名字的第一个tag!


通过点取属性的方式只能获得当前名字的第一个tag!








[u] find_all [/u]

如果想要得到所有的标签,比如<a>标签,就需要用到一些方法,比如: find_all()


  1. soup.find_all('a')
  2. # [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>,
  3. #  <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>,
  4. #  <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]
复制代码

返回的是一个列表









查看子节点



.contents 和 .children

tag的 .contents 属性可以将tag的子节点以列表的方式输出:

  1. head_tag = soup.head
  2. head_tag
  3. # <head><title>The Dormouse's story</title></head>

  4. head_tag.contents
  5. [<title>The Dormouse's story</title>]

  6. title_tag = head_tag.contents[0]
  7. title_tag
  8. # <title>The Dormouse's story</title>
  9. title_tag.contents
  10. # [u'The Dormouse's story']
复制代码



BeautifulSoup 对象本身一定会包含子节点,也就是说<html>标签也是 BeautifulSoup 对象的子节点:


游客,如果您要查看本帖隐藏内容请回复






字符串没有 .contents 属性,因为字符串没有子节点:

  1. text = title_tag.contents[0]
  2. text.contents
  3. # AttributeError: 'NavigableString' object has no attribute 'contents'
复制代码



游客,如果您要查看本帖隐藏内容请回复







通过tag的 .children 生成器,可以对tag的子节点进行循环:

  1. for child in title_tag.children:
  2.     print(child)
  3.     # The Dormouse's story
  4. .descendants
复制代码





-----------------------------------------------------------------------------------------------------------------------------------------------------------

子孙节点



上!代!码!


  1. head_tag.contents
  2. # [<title>The Dormouse's story</title>]
复制代码


.contents 和 .children 属性仅包含tag的直接子节点.例如,<head>标签只有一个直接子节点<title>
但是<title>标签也包含一个子节点:字符串 “The Dormouse’s story”,这种情况下字符串 “The Dormouse’s story”也属于<head>标签的子孙节点.



子节点   !=   子孙节点
儿子   !=    儿子的儿子





.descendants

.descendants 属性可以对所有tag的子孙节点进行递归循环  :



  1. for child in head_tag.descendants:
  2.     print(child)
  3.     # <title>The Dormouse's story</title>
  4.     # The Dormouse's story
复制代码





-----------------------------------------------------------------------------------------------------------------------------------------------------------
父节点


.parent

通过 .parent 属性来获取某个元素的父节点.在例子“爱丽丝”的文档中,<head>标签是<title>标签的父节点:

  1. title_tag = soup.title
  2. title_tag
  3. # <title>The Dormouse's story</title>
  4. title_tag.parent
  5. # <head><title>The Dormouse's story</title></head>
复制代码






文档title的[/b]
字符串也有父节点:<title>标签

  1. title_tag.string.parent
  2. # <title>The Dormouse's story</title>
复制代码




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

  1. html_tag = soup.html
  2. type(html_tag.parent)
  3. # <class 'bs4.BeautifulSoup'>
复制代码




当然BeautifulSoup 对象没有父节点,所以它的 .parent 是None:

  1. print(soup.parent)
  2. # None
复制代码





-----------------------------------------------------------------------------------------------------------------------------------------------------------
兄弟节点




同一个元素的子节点,被称为兄弟节点



for example

  1. sibling_soup = BeautifulSoup("<a><b>text1</b><c>text2</c></b></a>")
  2. print(sibling_soup.prettify())
  3. # <html>
  4. #  <body>
  5. #   <a>
  6. #    <b>
  7. #     text1
  8. #    </b>
  9. #    <c>
  10. #     text2
  11. #    </c>
  12. #   </a>
  13. #  </body>
  14. # </html>
复制代码



因为<b>标签和<c>标签是同一层,都是<a>的子节点,所以<b>和<c>可以被称为兄弟节点。




.next_sibling 和 .previous_sibling



使用 .next_sibling 和 .previous_sibling 属性来查询兄弟节点:


游客,如果您要查看本帖隐藏内容请回复




  1. sibling_soup.b.next_sibling
  2. # <c>text2</c>

  3. sibling_soup.c.previous_sibling


  4. [size=4]不过。。。。
  5. [hide]实际文档中的tag的 .next_sibling 和 .previous_sibling 属性通常是字符串或空白.
  6. {:10_258:} [/size]


  7. [size=4]
  8. 看看这一段html文档:[/size]

  9. [code]<a href="http://example.com/elsie" class="sister" id="link1">Elsie</a>
  10. <a href="http://example.com/lacie" class="sister" id="link2">Lacie</a>
  11. <a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>
复制代码




如果以为第一个<a>标签的 .next_sibling 结果是第二个<a>标签,那就错了!

真实结果是第一个<a>标签和第二个<a>标签之间的顿号和换行符:




  1. link = soup.a
  2. link
  3. # <a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>

  4. link.next_sibling
  5. # u',\n'
复制代码






游客,如果您要查看本帖隐藏内容请回复

评分

参与人数 2鱼币 +6 收起 理由
小甲鱼 + 4
康小泡 + 2

查看全部评分

本帖被以下淘专辑推荐:

小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2017-9-27 12:08:00 | 显示全部楼层
感谢楼主分享
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-2-22 22:50:18 | 显示全部楼层
学习
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2018-3-1 23:10:21 | 显示全部楼层
学习
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2018-3-6 14:28:01 | 显示全部楼层
学习
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2018-3-8 20:58:12 | 显示全部楼层
len(soup.contents)
# 1
soup.contents[0].name
# u'html'
为啥我的运行结果和说明不一样啊?
  1. from bs4 import BeautifulSoup

  2. html_doc = '''
  3. <html><head><title>The Dormouse's story</title></head>
  4. <body>
  5. <p class="title"><b>The Dormouse's story</b></p>

  6. <p class="story">Once upon a time there were three little sisters; and their names were
  7. <a  class="sister" id="link1">Elsie</a>,
  8. <a  class="sister" id="link2">Lacie</a> and
  9. <a  class="sister" id="link3">Tillie</a>;
  10. and they lived at the bottom of a well.</p>'''

  11. soup = BeautifulSoup(html_doc,'html.parser')
  12. print(8,len(soup.contents))
  13. print(9,soup.contents[0].name)
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-3-11 17:11:30 | 显示全部楼层
学习学习
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-8-25 15:52:21 | 显示全部楼层
学习一下
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-9-18 15:47:05 | 显示全部楼层
1
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2018-9-20 14:28:52 | 显示全部楼层
写的不错 很实用
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-11-5 22:53:16 | 显示全部楼层
求previous_sibling详解
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-11-10 15:59:13 | 显示全部楼层
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2019-11-8 20:19:31 | 显示全部楼层
楼主开心
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-11-9 13:08:03 | 显示全部楼层
学习
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2020-1-6 16:16:08 | 显示全部楼层
666
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2020-3-11 15:14:35 | 显示全部楼层
学习
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2020-3-13 15:44:51 | 显示全部楼层
学习了,感谢
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-3-22 01:05:23 | 显示全部楼层
我想看下面的,谢谢楼主
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-4-3 14:59:29 | 显示全部楼层
谢谢楼主的讲解
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-4-18 23:57:51 | 显示全部楼层
进来学习一下
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-5-21 15:07

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表