Python从零开始写爬虫(二)BeautifulSoup库使用
来源:互联网 发布:全民枪战怒龙改38数据 编辑:程序博客网 时间:2024/05/21 11:49
Beautiful Soup 是一个可以从HTML或XML文件中提取数据的Python库, BeautifulSoup在解析的时候是依赖于解析器的,它除了支持Python标准库中的HTML解析器,还支持一些第三方的解析器比如lxml等。可以从其官网得到更详细的信息:http://beautifulsoup.readthedocs.io/zh_CN/latest/#。在windows环境下,直接通过pip install beautifulsoup4
安装使用它把,同时也可以将lxml解析库安装上pip install lxml
。
一、BeautifulSoup基础
1、打开文件
如下代码所示,用lxml方式解析文件,也可以使用html.parser方式。如果担心使用的文件不规则,可以使用soup.prettify()
方法来格式化文档。
# coding=utf-8import requestsfrom bs4 import BeautifulSoup#创建BeautifulSoup对象,打开文件r = requests.get('http://music.163.com/')soup = BeautifulSoup(r.text, "lxml")print(soup.title)#<title>网易云音乐</title>soup2 = BeautifulSoup(open("D:\music.html",encoding="utf-8",errors="ignore"),"lxml")print(soup2.title)#<title>网易云音乐</title>
2、四大对象
Beautiful Soup将复杂HTML文档转换成一个复杂的树形结构,每个节点都是Python对象,所有对象可以归纳为4种: Tag , NavigableString , BeautifulSoup , Comment .
Tag对象:
Tag对象和xml、html原生文档中的tag相同。tag就是一个个标签,如下面html片段当中的meta、title等等。
<meta name="baidu-site-verification" content="cNhJHKEzsD" /><meta charset="utf-8"><meta property="qc:admins" content="27354635321361636375" /><title>网易云音乐</title><meta name="applicable-device" content="pc,mobile"><script type="text/javascript">
使用BeautifulSoup对象,可以方便的获取tag,如下所示:
soup2 = BeautifulSoup(open("D:\\test.html",encoding="utf-8",errors="ignore"),"lxml")#获取meta这个tag对象tag = soup2.metaprint(type(tag))#<class 'bs4.element.Tag'>
可以看到,很方便的便获取到了Tag对象,Tag对象有两个重要的属性name和attrs,怎么获取这两个属性呢?使用print(tag.name)、print(tag.attrs)
即可,其输出为:
meta{'name': 'baidu-site-verification', 'content': 'cNhJHKEzsD'}
可以看见,默认输出了第一个meta tag的数据,属性是以dictionary形式输出的,获取特定的属性就可以用字典的相关方法了:
print(tag.attrs["name"])print(tag.attrs.get("content"))#输出为:#baidu-site-verification#cNhJHKEzsD
NavigableString对象:
这个对象呢,就是用来获取tag中的文字的,还是用上面的例子:
tag = soup2.titleprint(tag.string)print(type(tag.string))#网易云音乐#<class 'bs4.element.NavigableString'>
这样我们就轻松获取到了标签里面的内容。如果tag包含了多个子节点tag就无法确定 .string 方法应该调用哪个子节点的内容, .string 的输出结果是 None。这时可以使用 .strings 来循环获取。
BeautifulSoup对象:
BeautifulSoup 对象表示的是一个文档的全部内容.大部分时候,可以把它当作 Tag 对象,是一个特殊的 Tag。比如上面使用BeautifulSoup对象调用文档中的tag信息。因为 BeautifulSoup 对象并不是真正的HTML或XML的tag,所以它没有name和attribute属性.但有时查看它的 .name 属性是很方便的,所以 BeautifulSoup 对象包含了一个值为 “[document]” 的特殊属性 .name:
soup2 = BeautifulSoup(open("D:\\test.html",encoding="utf-8",errors="ignore"),"lxml")print(soup2.name)#[document]
Comment 对象:
Tag , NavigableString , BeautifulSoup 几乎覆盖了html和xml中的所有内容,但是还有一些特殊对象.就像文档的注释部分。比如文档中含有这样一行:<b><!--Hey, buddy. Want to buy a used parser?--></b>
,使用以下代码来查看输出:
b_tag = soup2.bprint(b_tag.string)print(type(b_tag.string))#输出为:#Hey, buddy. Want to buy a used parser?#<class 'bs4.element.Comment'>
可以看到,输出的仅仅是注释的文字部分,已经把注释符号去掉了,要注意这个小细节。
二、遍历文档树
1、直接子节点
一个Tag可能包含多个字符串或其它的Tag,这些都是这个Tag的子节点.Beautiful Soup提供了许多操作和遍历子节点的属性。
.contents 和 .children
tag的 .contents 属性可以将tag的子节点以列表的方式输出:
head_tag = soup.head#输出head tag中的子节点的个数print(len(head_tag.contents))#子节点的内容,列表形式返回print(head_tag.contents)
tag的 .children属性可以将tag的子节点循环输出:
for child in soup.head.children: print(child)
遇到的问题,下面这个文档执行上面代码的输出和期望的不太一致:
<html><head><meta charset="utf-8"/><meta name="baidu-site-verification" content="cNhJHKEzsD"/><meta property="qc:admins" content="27354635321361636375"/></head></html>
输出为:
#为什么会有那么多换行符?7['\n', <meta charset="utf-8"/>, '\n', <meta content="cNhJHKEzsD" name="baidu-site-verification"/>, '\n', <meta content="27354635321361636375" property="qc:admins"/>, '\n']
2、所有子节点
.contents 和 .children 属性仅包含tag的直接子节点,.descendants 属性可以对所有tag的子孙节点进行递归循环。
3、节点内容
单节点:如果tag只有一个 NavigableString 类型子节点,那么这个tag可以使用 .string
得到子节点。
多节点:如果tag中包含多个字符串 ,可以使用 .strings
来循环获取,使用 .stripped_strings
可以去除多余空白内容。
4、其他节点
其他各种节点有很多,不逐个解释了,这里只列出它们:
~
这些属性的使用和前面子节点的使用类似,后面会陆续用到。
三、搜索文档树
BeautifulSoup定义了很多搜索方法,这里着重介绍find_all() ,其它方法的参数和用法类似。
find_all( name , attrs , recursive , string , **kwargs )
find_all() 方法搜索当前tag的所有tag子节点,并判断是否符合过滤器的条件。常用的过滤器的类型有以下几种:
- 字符串: 最简单的过滤器是字符串.在搜索方法中传入一个字符串参数,Beautiful Soup会查找与字符串完整匹配的内容
- 正则表达式: 如果传入正则表达式作为参数,Beautiful Soup会通过正则表达式的 match() 来匹配内容
- 列表:如果传入列表参数,Beautiful Soup会将与列表中任一元素匹配的内容返回
- True:True 可以匹配任何值,下面代码查找到所有的tag,但是不会返回字符串节点
- 方法:如果没有合适过滤器,那么还可以定义一个方法,方法只接受一个元素参数 ,如果这个方法返回 True 表示当前元素匹配并且被找到,如果不是则反回 False
下面介绍一下find_all()方法中的参数:
1、name 参数:
可以查找所有名字为 name 的tag,字符串对象会被自动忽略掉。搜索 name 参数的值可以使任一类型的 过滤器 ,字符串,正则表达式,列表,方法或是 True。
3、recursive 参数:
调用tag的 find_all() 方法时,Beautiful Soup会检索当前tag的所有子孙节点,如果只想搜索tag的直接子节点,可以使用参数 recursive=False。
r = requests.get('http://music.163.com/#/discover/toplist')soup = BeautifulSoup(r.text, "lxml")print(soup.title)#<title>网易云音乐</title>print(soup.html.find_all("title",recursive = False))#[]
只有 find_all() 和 find() 支持 recursive 参数。
4、string 参数:
通过 string 参数可以搜搜文档中的字符串内容.与 name 参数的可选值一样, string 参数接受 字符串 , 正则表达式 , 列表, True。
5、keyword 参数(kwargs ):
如果一个指定名字的参数不是搜索内置的参数名,搜索时会把该参数当作指定名字tag的属性来搜索,如果包含一个名字为 id 的参数,Beautiful Soup会搜索每个tag的”id”属性。
按CSS搜索:从Beautiful Soup的4.1.1版本开始,可以通过 class_ 参数搜索有指定CSS类名的tag。可以通过CSS值完全匹配,也可以使用各种过滤。
limit 参数:
使用 limit 参数限制返回结果的数量.效果与SQL中的limit关键字类似,当搜索到的结果数量达到 limit 的限制时,就停止搜索返回结果。
find_all() 的简写方法: find_all几乎是Beautiful Soup中最常用的搜索方法,所以我们定义了它的简写方法. BeautifulSoup 对象和 tag 对象可以被当作一个方法来使用,这个方法的执行结果与调用这个对象的 find_all() 方法相同,下面两行代码是等价的:
soup.find_all("a")soup("a")
这两行代码也是等价的:
soup.title.find_all(string=True)soup.title(string=True)
find()与 find_all() 方法的区别是 find_all() 方法的返回结果是值包含一个元素的列表,而 find() 方法直接返回结果。
四、CSS选择器
Beautiful Soup支持大部分的CSS选择器 ,在 Tag 或 BeautifulSoup 对象的 .select() 方法中传入字符串参数, 即可使用CSS选择器的语法找到tag。
CSS选择器的语言可以参考笔者之前的文章:Selenium自动化测试-入门
或者官方资料: CSS 选择器参考手册
- Python从零开始写爬虫(二)BeautifulSoup库使用
- Python从零开始写爬虫(一)requests库使用
- python 自己写爬虫 ----- BeautifulSoup
- Python爬虫(2)--BeautifulSoup的使用
- Python--从零开始学会写爬虫(Python)
- python从零开始写爬虫(2)
- python从零开始写爬虫(3)
- Python使用BeautifulSoup进行爬虫
- python网络爬虫-使用BeautifulSoup
- Python爬虫入门(三)BeautifulSoup库
- 用BeautifulSoup来写python爬虫
- Python网络爬虫与信息提取(二) BeautifulSoup库
- Python爬虫包 BeautifulSoup 学习(二) 异常处理
- Python爬虫学习纪要(二):BeautifulSoup相关知识点2
- 从零开始写Python爬虫 --- 导言
- python爬虫之BeautifulSoup库
- Python爬虫利器:BeautifulSoup库
- Python 3爬虫网易云(二)—— BeautifulSoup库用法上篇
- C++ Primer 第11章 关联容器 第一次学习笔记
- css总结(1)
- 使用Hadoop命令行执行jar包详解(生成jar、将文件上传到dfs、执行命令、下载dfs文件至本地)
- Linxu 进程死循环问题调试
- HTML+CSS+DIV问题积累(1)
- Python从零开始写爬虫(二)BeautifulSoup库使用
- MySQL---登陆与退出、数据库基本操作
- 条件编译
- 【面试题】剑指offer24--判断一个序列是否为二叉树的后序遍历
- javaweb服务端跨域支持
- 程序员必知8大排序3大查找(三)
- Wireshark TCP报文到达ACK确认机制
- 读书笔记-人月神话9
- 深度学习利器:TensorFlow使用实战分享