BeautifulSoup的使用

参考资料地址:https://www.crummy.com/software/BeautifulSoup/bs4/doc.zh/#id28

练习数据准备

  • 获取个人简书首页的html页面,并写入一个html文件中:
  • 说明:本来想用requests获取页面的html的,但是简书的反爬机制应该比较厉害,在headers中添加浏览器信息搞不定,所以选择了用selenium+phantomJS获取页面html。
  • 如果想用requests可以试试如下方式:

BeautifulSoup学习

前面已经将一个html页面以beautifulsoup对象的格式保存在了index.html中,接下来将用这个html文件用作示例练习(PS:这个时候就不要去访问网站了,直接读取保存好的文件)。

1、对象的种类

要掌握BeautifulSoup中对象操作,需要了解html的结构:http://www.runoob.com/html/html-elements.html。

  • 1.标签 tag

Python数据分析 作者:[印尼]Ivan Idris 伊德里斯 当当 广告 购买

获得link标签的结果:

  • 2.标签Tag有很多属性,比如:name和attributes。
  • 3.Name:每个Tag都有名字,通过.name获取,比如:a、p、title等都是名字
get_title = bsobj.titleprint(get_title)print(get_title.name)

结果:

  • 4.属性Attributes:一个标签会包含多个属性,属性在开始标签中,tag中属性的操作方法与字典的操作方法一样,并且支持增删改查

结果:

  • 5.多值属性:tag中的属性支持多值属性,常见的多值属性是class,多值属性的返回结果是列表

结果:

移动App性能评测与优化

作者:TMQ专项测试团队

当当 广告

购买

  • 6.可遍历的字符串:字符串包含在tag内,通过.string获取,字符串的内容不能被编辑,只能通过replace_with()进行替换。

结果:

2、遍历文档树

遍历文档树可以获得文档中的子节点、父节点、兄弟节点等标签。

  • 子节点:tag.name、tag.contents、tag.string、tag.strings、tag.stripped_strings等
  • 父节点:tag.parent、tag.parents
  • 兄弟节点:next_sibling、previous_sibling、next_siblings、previous_siblings
  • 回退和前进:.next_elements、.previous_elements、next_element 和 .previous_element
1、子节点

要获取子节点,首先要分析子节点中的内容,一个tag标签中,通常会包含多个字符串或者多个其他的tag标签。由于字符串没有子节点,是不具备遍历属性的。

  • 1)、获取所有的link标签:前面提到bsobj.link可以获取link标签信息,但是这种方式只能获取到第一条link信息,要获取文档中全部的link标签信息,可以用bsobj.find_all('link'),返回的结果是一个列表。
  • 2)、获取.contents和.children属性:
  • .contents:获取一个标签中的所有内容,以列表的格式输出。当然,由于contents中可能包含子节点信息,则所有的子节点信息都会在列表中输出。

结果:

  • .children:这是一个迭代器,可以对tag标签的子节点进行循环获取。比如,contents是获取到一个标签之间的所有内容,同一层级的多个子节点在contents中算作列表中的一个元素。此时,可以通过.children将子节点中的同一层级的标签进行分割。

结果:

  • 3)、.descendants:获取子节点和子孙节点 .children和.contents只会包含tag的直接子节点,对直接子节点中的子孙节点不会分离出来。.descendants返回的结果是一个生成器。

结果:首页这个内容,相当于是span的子节点,.descendants会把它当成子孙节点处理,其他子孙节点标签同理。

  • 4)、.string:获取NavigableString 类型子节点 当一个tag只有一个NavigableString 类型子节点时,可以采用.string获取,但是当有多个子节点时,.string无法得知获取哪一个,会直接返回None。
  • 5)、.strings 和 stripped_strings:获取一组NavigableString 类型子节点 .strings获取的信息中,包含空行,stripped_strings可以去除前后所有的空行以及为空的内容
get_title = bsobj.body.div
for sting in get_title.stripped_strings:
    print(sting)

结果:

写文章
注册
登录
夜间模式
开
关
...
2、父节点

每个tag都会包含父节点,比如前面采用bsobj.body.div获取节点信息,body就是div的一个父节点。

  • 1)、parent
get_title = bsobj.body.div.ul
print(get_title.parent)
print(get_title.parent.name)

结果:

<div class="collapse navbar-collapse" id="menu">
    <ul class="nav navbar-nav">        
        <li class="tab ">            
            <a href="/">....
        </li>        
    </ul>    
</div>

div
  • 2)、parents:通过元素的 .parents 属性可以递归得到元素的所有父辈节点
get_title = bsobj.body.div.ul
for parent in get_title.parents:
    if parent is None:
        print(parent)
    else:        
        print(parent.name)

结果:

div
div
div
nav
body
html
[document]
3、兄弟节点

标签处于同一层的节点,他们的父节点是同一个,这样的节点称为兄弟节点。

  • 1)、.next_sibling 和 .previous_sibling 属性来查询兄弟节点,实际文档中的tag的 .next_sibling 和 .previous_sibling 属性通常是字符串或空白。
get_title = bsobj.head.meta
print(get_title)
print(get_title.previous_sibling)
print(get_title.next_sibling)
  • 2)、.next_siblings 和 .previous_siblings:通过 .next_siblings 和 .previous_siblings 属性可以对当前节点的兄弟节点迭代输出。
get_title = bsobj.head.meta
for sibling in get_title.next_siblings:
    print(repr(sibling))

结果:

'\n'<meta content="IE=Edge" http-equiv="X-UA-Compatible"/>'\n'<meta content="width=device-width, initial-scale=1.0,user-scalable=no" .../>
...
4、回退和前进

让解析的属性指向上一个被解析对象或下一个被解析对象。

  • 1)、.next_element 和 .previous_element:.next_element 属性指向解析过程中下一个被解析的对象(字符串或tag),结果可能与 .next_sibling 相同,但通常是不一样的。
get_title = bsobj.body.div.ul.li.span
print(get_title)
print(get_title.nex_sibling)
print(get_title.next_element)

结果:

<span class="menu-text">
          首页         </span>None

          首页
  • 2)、.next_elements 和 .previous_elements:通过 .next_elements 和 .previous_elements 的迭代器就可以向前或向后访问文档的解析内容,就好像文档正在被解析一样
get_title = bsobj.body.div.ul.li.span
for element in get_title.next_elements:
    print(repr(element))

总结

  • 本节学习了beautifulsoup的tag对象、遍历文档树的使用
  • 通过查找子节点、父节点等信息,可以获取到想要的标签信息
  • 通过获取标签信息的.name、.attrs等,可以获取精确的信息
  • 后续继续学习搜索文档树 作者:乐大爷L 链接:https://www.jianshu.com/p/a0ff9f70e9a7 來源:简书 简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

原文发布于微信公众号 - 开源优测(DeepTest)

原文发表时间:2018-06-20

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏C/C++基础

内存池介绍与经典内存池的实现

利用默认的内存管理函数new/delete或malloc/free在堆上分配和释放内存会有一些额外的开销。

871
来自专栏java思维导图

值得收藏!Redis五大数据类型应用场景(一)

Redis开创了一种新的数据存储思路,使用Redis,我们不用在面对功能单调的数据库时,把精力放在如何把大象放进冰箱这样的问题上,而是利用Redis灵活多变的数...

2574
来自专栏好好学java的技术栈

java基础提升篇:深入浅出Java多线程

1272
来自专栏Janti

Java多线程高并发学习笔记(二)——深入理解ReentrantLock与Condition

锁的概念 从jdk发行1.5版本之后,在原来synchronize的基础上,增加了重入锁ReentrantLock。 本文就不介绍synchronize了,有兴...

4346
来自专栏JavaEdge

类加载器与双亲委派模型1 类加载器 2 双亲委派模型

类加载器(ClassLoader)是Java语言的一项创新,也是Java流行的一个重要原因。 在类加载的第一阶段“加载”过程中,需要通过一个类的全限定名来获取...

1622
来自专栏林欣哲

Redis知识点速查

NoSQL概述 为什么需要NoSQL 高并发读写 海量数据的高效率存储和访问 高可扩展性和高可用性 NoSQL数据库分类 键值存储。Redis 列存储。HBas...

37511
来自专栏云霄雨霁

Java虚拟机--内存模型

2255
来自专栏智能算法

Python学习(六)---- 常用模块必备知识

https://blog.csdn.net/fgf00/article/details/52357477

1653
来自专栏JackieZheng

AngularJS in Action读书笔记3——走近Services

  试着想想这些问题:如果一个controller只关心自己所控制的view页面,那么对于整个application来说,你如何调用想要的function;如果...

2119
来自专栏coder修行路

《深入理解计算机系统》阅读笔记--程序的机器级表示(上)

编译器基于编程语言的规则,目标机器的指令集和操作系统遵循的惯例,经过一系列的阶段生成机器代码。GCC c语言编译器以汇编代码的形式产生输出,汇编代码是机器代码的...

1100

扫码关注云+社区

领取腾讯云代金券