上篇博客说了正则表达式,但是正则学起来比较费劲,写的时候也不好写,这次说下Beautiful Soup怎么用,这个模块是用来解析html的,它操作很简单,用起来比较方便,比正则学习起来简单多了。

这是第三方模块需要安装

 
1
2
3
pip install beautifulsoup4
 
pip install lxml

Beautiful Soup对象

Beautiful将复杂HTML文档转换成一个复杂的树形结构,每个节点都是Python对象,所有对象可以归纳为4种:

Tag

标签,通过html的标签取到内容, 比如说a标签,如果有多个的话,取的是第一个。

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
html = """
<html><head><title>BestTest</title></head>
<body>
<div>
<p class="content">最专业的软件测试培训
<a href="http://www.besttest.cn" class="link" id="link1"><!--首页--></a>,
<a href="http://www.besttest.cn/page/3.html" class="link" id="link2">BestTest性能测试</a> and
<a href="http://www.besttest.cn/page/47.html" class="link" id="link3">BestTest自动化测试</a>;
课程详情请点击上面的链接.</p>
<p class="content">.这是广告植入.</p>
<p class="title">BestTest is best</p>
</div>
</body>
</html>
"""
obj = BeautifulSoup(html,'lxml')#后面是指定使用lxml解析,lxml解析速度比较快,容错高。
print(obj.prettify()) #格式化输出html
print(obj.title) #取title这个标签里面的内容
print(obj.p)
#tag有两个属性,一个是name,一个是attr
# name ,name这个属性就是标签的名字,比如说a标签就是打印的name就是a
# attrs,attrs这个是这个tag的属性,比如说上面a标签的属性有 class、href、id ,他是一个字典
#既然attrs是一个字典,那就能通过key来取值
 
print(obj.a.name)  #a标签的name,也就是a
print(obj.a.attrs) #a标签的属性,也就是class href id这些,以及对应的值是什么
print(obj.a.attrs['href']) #取到a标签的href熟悉,也就是,http://www.besttest.cn
print(obj.a.attrs.get('href')) #因为attrs是一个字典,所以也可以用.get方法取值和上面的中括号取值一样

NavigableString

也就是内容,获取到一个标签里面的内容,文字,比如说上面title标签里面内容获取到,也就是besttest直接用tag.string即可。

 
1
2
3
print(obj.title.string) #BestTest
print(obj.a.string)    #首页
print(type(obj.title.string)) # <class 'bs4.element.NavigableString'> NavigableString的类型

Beautifulobj

Beautifulobj对象就是代表整个html,比如说上面的obj就是Beautifulobj对象,通过它来操作各个标签

 
1
print(type(obj))  #Beautifulobj对象

Comment

Comment 对象是一个特殊类型的 NavigableString对象, 其实输出的内容仍然不包括注释符号,但是如果不好好处理它,可能会对我们的文本处理造成意想不到的麻烦。例如上面的一个a标签里面,首页是被注释了的。

 
1
2
3
print(obj.a.string)  #首页,不包括 <!-- -->注释的
print(type(obj.a.string)) # <class 'bs4.element.Comment'> Comment类型
#这其实是注释的内容,咱们用string取出来的时候是不带注释符号的所以这里要注意一下

重点操作

上面的都是通过某个标签获取到的,如果想直接获取到某些标签,获取包含某些属性的就要用其他的方法了。

搜索标签

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# find_all方法  find_all( name , attrs , recursive , text , **kwargs )
#find_all方法用来搜索当前所有的tag,判断是否符合过滤条件,如果符合的话,返回符合条件的列表
print(obj.find_all('p'))#找到所有p标签
print(obj.find_all(['a','p']))#找到所有a和p标签
 
#指定属性
print(obj.find_all(id='link1')) #找到id为link1的
print(obj.find_all(id=['link1','link2'])) #找到id为link1和link2的
 
#因为class在python里面是关键字,如果要找class属性的,不能直接写class,要写class_
print(obj.find_all(class_='link')) #class为link的,
print(obj.find_all(class_=['link','content']))#class为link和conent的
print(obj.find_all(attrs={'class':'link','id':'link1'})) #多个属性也可以直接写成一个字典,把属性名写成key,值写成value
print(obj.find_all('p',class_='content')) #从p标签里面找到class为conent的
 
 
print(type(obj.find(class_='link')))#find方法和findall方法的区别是,findall会返回所有的标签,放到一个list里面
#find方法返回的是一个标签,找到多个的话,取第一个。其他用法都是一样的
 

css选择器

css选择器就是通过css获取元素的方式来获取html的标签,如果对css比较熟悉的人用起来就很方便了,在css选择器中 "." 代表选择的class,"#"代表选择的id。

 
1
2
3
4
5
6
7
8
9
10
11
print('p',obj.select('p')) #通过标签选择
print(obj.select('a')) #通过标签选择
print(obj.select('.content'))#通过类名选择
print(obj.select('#link1'))#通过id选择
print(obj.select('p .link'))#组合查找,找p标签下面class为title的
print(obj.select('p #link1'))#组合查找,找p标签下面id为link1的
print(obj.select('a#link1'))#组合查找,找a标签里面id为link1的,和不加空格的区别是,在同级别找的
print(obj.select('p > a'))#标签组合查找,找到p标签下面的a标签
 
print(obj.select('a[class=link]'))#属性查找,找到a标签下面class为link的
print(obj.select('p a[href=http://www.besttest.cn/page/47.html]'))#组合使用,从p标签下面的a标签找到href为http://www.besttest.cn/page/47.html的

节点内容

节点就是怎么获取html的各个节点,比如说和div同级的其他div,div下面的子标签等等。

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# contents tag 的 .contents 属性可以将tag的子节点以列表的方式输出
#children  children和contents一样,也是获取子节点,只不过children不是列表,而是一个生成器
print(obj.div.contents) #获取到div下面的所有tag
print(obj.div.children) #这个是一个生成器,打印出来是一个生成器对象,想获取的话,就要循环了
for chil in obj.div.children:
print(chil)
 
 
 
# 通过contents以及children都是获取子节点,如果想要获取子孙节点可以通过descendants
# print(obj.descendants)同时这种获取的结果也是一个迭代器
#
# 父节点和祖先节点
#
# 通过obj.a.parent就可以获取父节点的信息
#
# 通过obj.a.parents可以获取祖先节点,这个方法返回的结果是一个列表,会分别将a标签的父节点的信息存放到列表中,以及父节点的父节点也放到列表中,并且最后还会讲整个文档放到列表中,所有列表的最后一个元素以及倒数第二个元素都是存的整个文档的信息
#
# 兄弟节点
#
# obj.a.next_siblings 获取后面的兄弟节点
# obj.a.previous_siblings 获取前面的兄弟节点
# obj.a.next_sibling 获取下一个兄弟标签
# obj.a.previous_sinbling 获取上一个兄弟标签

总结

主要说了怎么获取到html里面的各种标签、元素,修改和删除没有写,因为爬虫一般用不到修改,获取数据就够了。find_all()和css选择器都很常用,如果对css比较熟悉的话,建议使用css选择器。标签搜索和css选择器这里非常的常用。

爬虫学习笔记(五) Beautiful Soup使用的更多相关文章

  1. 吴裕雄--天生自然python学习笔记:Beautiful Soup 4.2.0模块

    Beautiful Soup 是一个可以从HTML或XML文件中提取数据的Python库.它能够通过你喜欢的转换器实现惯用的文档导航,查找,修改文档的方式.Beautiful Soup会帮你节省数小时 ...

  2. Python学习笔记之Beautiful Soup

    如何在Python3.x中使用Beautiful Soup 1.BeautifulSoup中文文档:http://www.crummy.com/software/BeautifulSoup/bs3/d ...

  3. C#可扩展编程之MEF学习笔记(五):MEF高级进阶

    好久没有写博客了,今天抽空继续写MEF系列的文章.有园友提出这种系列的文章要做个目录,看起来方便,所以就抽空做了一个,放到每篇文章的最后. 前面四篇讲了MEF的基础知识,学完了前四篇,MEF中比较常用 ...

  4. (转)Qt Model/View 学习笔记 (五)——View 类

    Qt Model/View 学习笔记 (五) View 类 概念 在model/view架构中,view从model中获得数据项然后显示给用户.数据显示的方式不必与model提供的表示方式相同,可以与 ...

  5. java之jvm学习笔记五(实践写自己的类装载器)

    java之jvm学习笔记五(实践写自己的类装载器) 课程源码:http://download.csdn.net/detail/yfqnihao/4866501 前面第三和第四节我们一直在强调一句话,类 ...

  6. python网络爬虫学习笔记

    python网络爬虫学习笔记 By 钟桓 9月 4 2014 更新日期:9月 4 2014 文章文件夹 1. 介绍: 2. 从简单语句中開始: 3. 传送数据给server 4. HTTP头-描写叙述 ...

  7. Learning ROS for Robotics Programming Second Edition学习笔记(五) indigo computer vision

    中文译著已经出版,详情请参考:http://blog.csdn.net/ZhangRelay/article/category/6506865 Learning ROS for Robotics Pr ...

  8. scrapy爬虫学习系列五:图片的抓取和下载

    系列文章列表: scrapy爬虫学习系列一:scrapy爬虫环境的准备:      http://www.cnblogs.com/zhaojiedi1992/p/zhaojiedi_python_00 ...

  9. Typescript 学习笔记五:类

    中文网:https://www.tslang.cn/ 官网:http://www.typescriptlang.org/ 目录: Typescript 学习笔记一:介绍.安装.编译 Typescrip ...

  10. Python爬虫利器二之Beautiful Soup的用法

    上一节我们介绍了正则表达式,它的内容其实还是蛮多的,如果一个正则匹配稍有差池,那可能程序就处在永久的循环之中,而且有的小伙伴们也对写正则表达式的写法用得不熟练,没关系,我们还有一个更强大的工具,叫Be ...

随机推荐

  1. 最小生成树:HDU1863-畅通工程

    畅通工程 Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submissi ...

  2. VMware之无法切换桥接网络

    一.关闭正在运行的虚拟机 二.打开虚拟网络编辑器 三.还原默认设置 四.启动虚拟机即可正常使用桥接网络

  3. day10 消息队列,多进程和多线程以及协程,异步IO,事件驱动等

    回顾一下线程和进程 线程与进程的区别 守护线程: 队列: 两种方式: 先进先出  # 后入先出   #卖水果,后来的来的是新的 生产者消费者模型: 生产包子, 吃包子 事件 event: 红绿灯模型 ...

  4. JQuery easyUi datagrid 中 自定义editor作为列表操作按钮列

    转自   http://blog.csdn.net/tianlincao/article/details/7494467 前言 JQuery easyUi datagrid 中 使用datagrid生 ...

  5. IOS开发---菜鸟学习之路--(八)-实现新闻页面

    本章将具体讲述如何结合前两张的内容最终实现一个新闻页面的雏形 之所以称之为雏形,是因为本章实现的内容只是实现了最基础的效果 还有很多其他诸如下拉刷新 页面导航等效果都需要投入一些时间进行研究 好了直接 ...

  6. 【Add Two Numbers】

    题目: You are given two linked lists representing two non-negative numbers. The digits are stored in r ...

  7. Python+Selenium练习篇之4-利用link text定位元素

    本文介绍如何通过link text 来定位页面元素,我们打开网页,一些可以点击的链接跳转上面的文字,就是link text,用百度首页举例来看: 在上面图中,这一排上面的文字都是link text,例 ...

  8. wordpress 区分多语言站点

    $blog_title = get_bloginfo( 'name' ); $table_name = ''; if ( $blog_title == 'Driver Easy' ) { $table ...

  9. [python][django学习篇][4]django完成数据库代码翻译:迁移数据库(migration)

    上一篇我们已经完成数据库的设计,但是仅仅是python语言,并没有真正创建了数据库表.翻译成数据库语言,真正创建数据库表由django manage.py来实现,这一过程专业术语:迁移数据库 切换到m ...

  10. Generator与async/await与Generator的模拟

    Generator 函数有多种理解角度.语法上,首先可以把它理解成,Generator 函数是一个状态机,封装了多个内部状态. 执行 Generator 函数会返回一个遍历器对象,也就是说,Gener ...