码迷,mamicode.com
首页 > 其他好文 > 详细

遍历文档树

时间:2019-04-21 14:28:49      阅读:205      评论:0      收藏:0      [点我收藏+]

标签:mouse   ast   列表   出现   elements   没有   很多   打开   元素   

子节点

  • 一个Tag可能包含多个字符串或其它的Tag,这些都是这个Tag的子节点.Beautiful Soup提供了许多操作和遍历子节点的属性.

  • 注意: Beautiful Soup中字符串节点不支持这些属性,因为字符串没有子节点

1. tag的名字

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

  • 这是个获取tag的小窍门,可以在文档树的tag中多次调用这个方法.下面的代码可以获取<body>标签中的第一个<b>标签:

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

  • 如果想要得到所有的<a>标签,或是通过名字得到比一个tag更多的内容的时候,就需要用到搜索文档树中描述的方法,比如: find_all()

2. .contents 和 .children

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

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

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

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

3. .descendants

  • .contents.children 属性仅包含tag的直接子节点.例如,<head>标签只有一个直接子节点<title>

head_tag.contents

# [<title>The Dormouse's story</title>]
  • 但是标签也包含一个子节点:字符串 “The Dormouse’s story”,这种情况下字符串 “The Dormouse’s story”也属于<code><head></code>标签的子孙节点. <code>.descendants</code> 属性可以对所有tag的子孙节点进行递归循环(先序遍历):</li> </ul> <pre class="python"><code> for child in head_tag.descendants: print(child) # <title>The Dormouse's story</title> # The Dormouse's story </code></pre> <p>上面的例子中, <code><head></code>标签只有一个子节点,但是有2个子孙节点:<code><head></code>节点和<code><head></code>的子节点, BeautifulSoup 有一个直接子节点(<code><html></code>节点),却有很多子孙节点:</p> <pre><code> len(list(soup.children)) # 1 len(list(soup.descendants)) # 25 </code></pre> <h3 id="string">4. .string</h3> <ul> <li>如果tag只有一个 NavigableString 类型子节点,那么这个tag可以使用 <code>.string</code>得到子节点:</li> </ul> <pre class="python"><code> title_tag.string # u'The Dormouse's story' </code></pre> <p>如果一个tag仅有一个子节点,那么这个tag也可以使用 <code>.string</code> 方法,输出结果与当前唯一子节点的 <code>.string</code> 结果相同:</p> <pre class="python"><code> head_tag.contents # [<title>The Dormouse's story</title>] </code></pre> <pre class="python"><code> head_tag.string # u'The Dormouse's story' </code></pre> <p>如果tag包含了多个子节点,tag就无法确定 <code>.string</code> 方法应该调用哪个子节点的内容, <code>.string</code> 的输出结果是 None :</p> <pre class="python"><code> print(soup.html.string) # None </code></pre> <h3 id="strings-和-stripped_strings">5. .strings 和 stripped_strings</h3> <h2 id="父节点">父节点</h2> <ul> <li>每个tag或字符串都有父节点:被包含在某个tag中</li> </ul> <h3 id="parent">1. .parent</h3> <ul> <li><p>通过<code>.parent</code>属性来获取某个元素的父节点.在例子文档中,<code><head></code>标签是<code><title></code>标签的父节点:</p></li> <li><p>文档title的字符串也有父节点:<title>标签</p></li> <li><p>文档的顶层节点比如<code><html></code>的父节点是 BeautifulSoup 对象:</p></li> <li><p>BeautifulSoup 对象的 <code>.parent</code> 是None:</p></li> </ul> <h3 id="parents">2. .parents</h3> <ul> <li>通过元素的 .parents 属性可以递归得到元素的所有父辈节点,下面的例子使用了 .parents 方法遍历了<code><a></code>标签到根节点的所有节点</li> </ul> <h2 id="兄弟节点">兄弟节点</h2> <pre class="python"><code> sibling_soup = BeautifulSoup("<a><b>text1</b><c>text2</c></b></a>") print(sibling_soup.prettify()) # <html> # <body> # <a> # <b> # text1 # </b> # <c> # text2 # </c> # </a> # </body> # </html> </code></pre> <blockquote> <p>因为<b>标签和<c>标签是同一层:他们是同一个元素的子节点,所以<b>和<c>可以被称为兄弟节点.一段文档以标准格式输出时,兄弟节点有相同的缩进级别.在代码中也可以使用这种关系.</p> </blockquote> <h3 id="next_sibling-和-.previous_sibling">1. .next_sibling 和 .previous_sibling</h3> <ul> <li><p>在文档树中,使用 <code>.next_sibling</code> 和 <code>.previous_sibling</code> 属性来查询兄弟节点:</p></li> <li><p>例子中的字符串“text1”和“text2”不是兄弟节点,因为它们的父节点不同:</p></li> <li><p>实际文档中的tag的<code>.next_sibling</code> 和 <code>.previous_sibling</code> 属性通常是字符串或空白.</p></li> </ul> <pre><code> <a href="http://example.com/elsie" class="sister" id="link1">Elsie</a> <a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> <a href="http://example.com/tillie" class="sister" id="link3">Tillie</a> </code></pre> <blockquote> <p>如果以为第一个<code><a></code>标签的<code>.next_sibling</code> 结果是第二个<code><a></code>标签,那就错了,真实结果是第一个<code><a></code>标签和第二个<code><a></code>标签之间的顿号和换行符:</p> </blockquote> <p>第二个<code><a></code>标签是顿号的 <code>.next_sibling</code> 属性:</p> <h3 id="next_siblings-和-.previous_siblings">2. .next_siblings 和 .previous_siblings</h3> <ul> <li>通过 .next_siblings 和 .previous_siblings 属性可以对当前节点的兄弟节点迭代输出:</li> </ul> <h2 id="回退和前进">回退和前进</h2> <pre><code> <html><head><title>The Dormouse's story</title></head> <p class="title"><b>The Dormouse's story</b></p> </code></pre> <blockquote> <p>HTML解析器把这段字符串转换成一连串的事件: “打开<html>标签”,”打开一个<head>标签”,”打开一个<title>标签”,”添加一段字符串”,”关闭<title>标签”,”打开<p>标签”,等等.Beautiful Soup提供了重现解析器初始化过程的方法.</p> </blockquote> <h3 id="next_element-和-.previous_element">1. .next_element 和 .previous_element</h3> <blockquote> <p><code>.next_element</code> 属性指向解析过程中下一个被解析的对象(字符串或tag),结果可能与<code>.next_sibling</code>相同,但通常是不一样的.</p> </blockquote> <blockquote> <p>这是文档中最后一个<code><a></code>标签,它的 <code>.next_sibling</code> 结果是一个字符串,因为当前的解析过程 [2] 因为当前的解析过程因为遇到了<code><a></code>标签而中断了:</p> </blockquote> <pre class="python"><code> 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.' </code></pre> <blockquote> <p>但这个<code><a></code>标签的<code>.next_element</code>属性结果是在<code><a></code>标签被解析之后的解析内容,不是<code><a></code>标签后的句子部分,应该是字符串”Tillie”:</p> </blockquote> <pre class="python"><code> last_a_tag.next_element # u'Tillie' </code></pre> <blockquote> <p>这是因为在原始文档中,字符串“Tillie” 在分号前出现,解析器先进入<code><a></code>标签,然后是字符串“Tillie”,然后关闭<code></a></code>标签,然后是分号和剩余部分.分号与<code><a></code>标签在同一层级,但是字符串“Tillie”会被先解析.</p> </blockquote> <blockquote> <p><code>.previous_element</code> 属性刚好与 <code>.next_element</code>相反,它指向当前被解析的对象的前一个解析对象:</p> </blockquote> <h3 id="next_elements-和-.previous_elements">2. .next_elements 和 .previous_elements</h3> <ul> <li>通过 .next_elements 和 .previous_elements 的迭代器就可以向前或向后访问文档的解析内容,就好像文档正在被解析一样:</li> </ul><p><a href="http://www.mamicode.com/info-detail-2662827.html" title="遍历文档树,mamicode.com" style="color:#ffffff" target="_blank">遍历文档树</a></p><p>标签:<a href='http://www.mamicode.com/so/1/mouse' title='mouse'>mouse</a>   <a href='http://www.mamicode.com/so/1/ast' title='ast'>ast</a>   <a href='http://www.mamicode.com/so/1/%e5%88%97%e8%a1%a8' title='列表'>列表</a>   <a href='http://www.mamicode.com/so/1/%e5%87%ba%e7%8e%b0' title='出现'>出现</a>   <a href='http://www.mamicode.com/so/1/elements' title='elements'>elements</a>   <a href='http://www.mamicode.com/so/1/%e6%b2%a1%e6%9c%89' title='没有'>没有</a>   <a href='http://www.mamicode.com/so/1/%e5%be%88%e5%a4%9a' title='很多'>很多</a>   <a href='http://www.mamicode.com/so/1/%e6%89%93%e5%bc%80' title='打开'>打开</a>   <a href='http://www.mamicode.com/so/1/%e5%85%83%e7%b4%a0' title='元素'>元素</a>   </p><p>原文地址:https://www.cnblogs.com/lalavender/p/10744880.html</p></span> </div> <div id="divcomment"> <div> <div class="divtextaligncenter paddingright2 overflowauto"> <div class="detailcai" id="infono" onclick="infono_click();"> <div class="detailcai1 colorboldlan"> 踩</div> <div class="detailcai2 colorboldlan"> (<span id="spanNo">0</span>)</div> </div> <div class="detailzan" id="infoyes" onclick="infoyes_click();"> <div class="detailzan1 colorboldHong"> 赞</div> <div class="detailzan2 colorboldHong"> (<span id="spanYes">0</span>)</div> </div> </div> <div class="divtextalignright margintop10"> <div class="width100bi paddingleft10right10"> <span id="spanYesContent" class="colorboldHong"></span>  <span id="spanNoContent" class="colorboldlan"></span>  <span id="spanBadContent" class="colorboldHong"> </span> </div> </div> </div> <div class="divtextalignright margintop10"> <span class="detailjubao" id="infobad" onclick="infobad_click();">举报</span> </div> <script type="text/javascript"> mamicode_adload('content_after');</script> <div id="comment" class="divtextalignleft margintop20"> <div class="detailpinglun1"> <span class="detailpinglun2 title6">评论</span> <span class="detailpinglun3">一句话评论(<span id="commentCount" class="colorboldHong">0</span>)</span> </div> <div class="paddingtop20"> <div id="commentlistend" name="commentlistend" class="divtextaligncenter margintop20"> <span id="lblpage"></span> </div> </div> <div class="margintop20"> <form method="post" action="/ajaxjs/info_detail_commentadd.aspx"> <div class="divtextalignleft paddingtop20"> <div id="commenthf" class="divbackgroundcolor1"> </div> <div> <textarea name="tbcommentcontent" id="tbcommentcontent" class="tb" disabled="disabled" style="width: 680px; height: 120px;" ></textarea> </div> </div> <div class="divtextalignright paddingtop10 "> <span id="addCommentTishi" class="colorboldHong">登录后才能评论!</span> <span id="loginno"><input type="button" class="mbtn1" value="登录" onclick="location.href='http://member.mamicode.com/login.aspx?returnUrl='+document.URL.replace(new RegExp('&', 'g'), '(_)')" /></span> </div> </form> </div> </div> </div> <script type="text/javascript"> mamicode_adload('content_bottom');</script> </div> </div> <div class="width30bi divfloatright"> <div class="paddingbottom20"> <script type="text/javascript">(function(){document.write(unescape('%3Cdiv id="bdcs"%3E%3C/div%3E'));var bdcs = document.createElement('script');bdcs.type = 'text/javascript';bdcs.async = true;bdcs.src = 'http://znsv.baidu.com/customer_search/api/js?sid=8166352449904245503' + '&plate_url=' + encodeURIComponent(window.location.href) + '&t=' + Math.ceil(new Date()/3600000);var s = document.getElementsByTagName('script')[0];s.parentNode.insertBefore(bdcs, s);})();</script> </div> <script type="text/javascript"> mamicode_adload('right_top');</script> <div class="width99bi divborder"> <div class="divtitle"> <div id="infofile1_div1" class="divfloatleft divtitlefont"> 分享档案</div> <div class="divfloatright"> <a href="/infotimemore.html" title="分享档案更多" class="colorCheng">更多></a> </div> </div> <div class="divtextalignleft paddingleft10right10 margintop10bottom10 heightline30px"> <a class="taga" href="/info-time-20210729-1.html" target="_blank" title="2021年07月29日技术分享文章"> 2021年07月29日 (22)</a><br /> <a class="taga" href="/info-time-20210728-1.html" target="_blank" title="2021年07月28日技术分享文章"> 2021年07月28日 (40)</a><br /> <a class="taga" href="/info-time-20210727-1.html" target="_blank" title="2021年07月27日技术分享文章"> 2021年07月27日 (32)</a><br /> <a class="taga" href="/info-time-20210726-1.html" target="_blank" title="2021年07月26日技术分享文章"> 2021年07月26日 (79)</a><br /> <a class="taga" href="/info-time-20210723-1.html" target="_blank" title="2021年07月23日技术分享文章"> 2021年07月23日 (29)</a><br /> <a class="taga" href="/info-time-20210722-1.html" target="_blank" title="2021年07月22日技术分享文章"> 2021年07月22日 (30)</a><br /> <a class="taga" href="/info-time-20210721-1.html" target="_blank" title="2021年07月21日技术分享文章"> 2021年07月21日 (42)</a><br /> <a class="taga" href="/info-time-20210720-1.html" target="_blank" title="2021年07月20日技术分享文章"> 2021年07月20日 (16)</a><br /> <a class="taga" href="/info-time-20210719-1.html" target="_blank" title="2021年07月19日技术分享文章"> 2021年07月19日 (90)</a><br /> <a class="taga" href="/info-time-20210716-1.html" target="_blank" title="2021年07月16日技术分享文章"> 2021年07月16日 (35)</a><br /> </div> </div> <div class="width99bi margintop20 divborder"> <div class="divtitle"> <div id="infotop2_divtitle" class="divfloatleft divtitlefont">周排行</div> <div class="divfloatright"> <img src="/img/j01.jpg" width="14" height="14" alt="mamicode.com排行更多图片" /></div> <div class="divfloatright"> <a href="/info-toplist-11-2-1.html" id="infotop2_amore" title="周排行更多">更多</a></div> </div> <div> <ul> <li class="divullititle heightline25px divtextalignleft"><a href="/info-detail-3126753.html" title="分布式事务" target="_blank"> 分布式事务  <span class="colorlan">2021-07-29</span> </a> </li> <li class="divullititle heightline25px divtextalignleft"><a href="/info-detail-3126752.html" title="OpenStack云平台命令行登录账户" target="_blank"> OpenStack云平台命令行登录账户  <span class="colorlan">2021-07-29</span> </a> </li> <li class="divullititle heightline25px divtextalignleft"><a href="/info-detail-3126751.html" title="getLastRowNum()与getLastCellNum()/getPhysicalNumberOfRows()与getPhysicalNumberOfCells()" target="_blank"> getLastRowNum()与getLastCellNum()/getPhysicalNumberOfRows()与getPhysicalNumberOfCells()  <span class="colorlan">2021-07-29</span> </a> </li> <li class="divullititle heightline25px divtextalignleft"><a href="/info-detail-3126749.html" title="【K8s概念】CSI 卷克隆" target="_blank"> 【K8s概念】CSI 卷克隆  <span class="colorlan">2021-07-29</span> </a> </li> <li class="divullititle heightline25px divtextalignleft"><a href="/info-detail-3126748.html" title="vue3.0使用ant-design-vue进行按需加载原来这么简单" target="_blank"> vue3.0使用ant-design-vue进行按需加载原来这么简单  <span class="colorlan">2021-07-29</span> </a> </li> <li class="divullititle heightline25px divtextalignleft"><a href="/info-detail-3126746.html" title="stack栈" target="_blank"> stack栈  <span class="colorlan">2021-07-29</span> </a> </li> <li class="divullititle heightline25px divtextalignleft"><a href="/info-detail-3126745.html" title="抽奖动画 - 大转盘抽奖" target="_blank"> 抽奖动画 - 大转盘抽奖  <span class="colorlan">2021-07-29</span> </a> </li> <li class="divullititle heightline25px divtextalignleft"><a href="/info-detail-3126742.html" title="PPT写作技巧" target="_blank"> PPT写作技巧  <span class="colorlan">2021-07-29</span> </a> </li> <li class="divullititle heightline25px divtextalignleft"><a href="/info-detail-3126738.html" title="003-核心技术-IO模型-NIO-基于NIO群聊示例" target="_blank"> 003-核心技术-IO模型-NIO-基于NIO群聊示例  <span class="colorlan">2021-07-29</span> </a> </li> <li class="divullititle heightline25px divtextalignleft"><a href="/info-detail-3126737.html" title="Bootstrap组件2" target="_blank"> Bootstrap组件2  <span class="colorlan">2021-07-29</span> </a> </li> </ul> </div> </div> <script type="text/javascript"> mamicode_adload('right_bottom');</script> </div> <div class="divfloatclear"> </div> </div> <script type="text/javascript"> mamicode_adload('bottom');</script> <div class="width1000px divmargin0auto paddingtop20bottom20"> <div class="width1000px divborder margintop20"> <div class="youqingtitle"> <a title="友情链接">友情链接</a> </div> <div class="youqingcontent"> <a href='http://www.lightinit.com' target='_blank' title='互联网产品定制开发专家'>兰亭集智</a>   <a href='http://www.guozhihua.net/' target='_blank'>国之画</a>   <a href='http://tongji.baidu.com' target='_blank'>百度统计</a>   <a href='http://www.cnzz.com/' target='_blank'> 站长统计</a>   <a href='http://www.aliyun.com/' target='_blank'>阿里云</a>   <a href='http://www.cnplugins.com/' target='_blank'>chrome插件</a>   <a href="https://m.tiantingfm.com/list/" target='_blank'>新版天听网</a> </div> </div> </div> <div class="bottomdiv"> <div class="width1000px divmargin0auto paddingtop20"> <div class="height30px divtextalignleft"> <a href="/about.html" title="mamicode.com关于我们">关于我们</a> - <a href="/contactus.html" title="mamicode.com联系我们">联系我们</a> - <a href="/guest.html" title="mamicode.com留言反馈">留言反馈</a> </div> <div class="height30px divtextalignleft"> © 2014 <a href="http://www.mamicode.com" target="_blank" title="mamicode.com,技术分享">mamicode.com</a> 版权所有 <!--<a href="http://www.beian.miit.gov.cn" target="_blank">京ICP备13008772号-2</a>-->  联系我们:gaon5@hotmail.com </div> <div class="divtextalignleft"> <span class="colorlan">迷上了代码!</span> </div> <div class="paddingtop20"> <script> (function () { var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })(); </script> <script> var _hmt = _hmt || []; (function() { var hm = document.createElement("script"); hm.src = "https://hm.baidu.com/hm.js?c932f0b810213e2feccccbb987715fd6"; var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(hm, s); })(); </script> </div> </div> </div> <script type="text/javascript"> var mid = ''; var id = '2662827'; var idm = '9154ea'; var commentitemcount = '0'; var memberhost = 'http://member.mamicode.com/'; prettyPrint(); </script> <script src="/js/infodetail.js" type="text/javascript" charset="utf-8"></script> <script src="/js/member.js" type="text/javascript" charset="utf-8"></script> <script type="text/javascript" src="/js/mamicodejs.js"></script> </body> </html>