Welcome To Jeremy's Blog --------------------------            JeremyYu

1.5 数据解析 -- BeautifulSoup库详解


1.BeautifulSoup概览

  Beautiful Soup就是Python的一个HTML或XML的解析库. 它借助网页的结构和属性等特性来解析网页.

  Beautiful Soup在解析时实际上依赖解析器,它除了支持Python标准库中的HTML解析器外,还支持一些第三方解析器(比如lxml)

  如下是Beautiful Soup支持的解析器:

解析器 使用方法 优势 劣势
Python标准库 BeautifulSoup(markup, "html.parser") Python的内置标准库、执行速度适中、文档容错能力强 Python 2.7.3及Python 3.2.2之前的版本文档容错能力差
lxml HTML解析器 BeautifulSoup(markup, "lxml") 速度快、文档容错能力强 需要安装C语言库
lxml XML解析器 BeautifulSoup(markup, "xml") 速度快、唯一支持XML的解析器 需要安装C语言库
html5lib BeautifulSoup(markup, "html5lib") 最好的容错性、以浏览器的方式解析文档、生成HTML5格式的文档 速度慢、不依赖外部扩展

注: 上面的解析器中, lxml解析器的速度快, 容错能力强, 而且支持HTML和XML的解析, 所以我们在爬虫程序中一般使用lxml解析器.

返回顶部


2.Beautiful Soup使用步骤

1 # 1.导入模块
2 from bs4 importBeautifulSoup
3 
4 # 2.实例化BeautifulSoup对象
5 soup =BeautifulSoup(文本,"lxml")# lxml实际传入的是解析器类型, 我们一般选择lxml解析器
6 
7 # 3.调用对象的选择器方法提取目标数据
8 target_data = soup.选择器.方法

 

返回顶部


3.节点选择器

 1 # 1.对BeautifulSoup对象直接调用节点名称就可以选择节点元素, 可以再调用节点对象的属性或方法获取数据
 2 
 3 # 2.示例:
 4 text ='''
 5 <html>
 6 <head>
 7 <title>The Dormouse's story</title>
 8 </head>
 9 <body>
10 <p class="title" name="dromouse"><b>TheDormouse's story</b></p>
11 <p class="story">Once upon a time there were three little sisters; and their names were
12 <a href="http://example.com/elsie" class="sister" id="link1"><!-- Elsie --></a>,
13 <a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and
14 <a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>;
15 and they lived at the bottom of a well.
16 </p>
17 <p class="story">...</p>
18 '''
19 from bs4 importBeautifulSoup
20 soup =BeautifulSoup(html,'lxml')
21 print(soup.title)# 结果为title节点: <title>The Dormouse's story</title>
22 
23 # 3.提取目标数据:
24 (1).获取标签名称:利用name属性,对定位的节点标签取其name
25 print(soup.title.name)# 结果为: title
26  
27 (2).获取属性:使用attrs返回结果,其为字典形式
28 print(soup.p.attrs)# 获取标签所有属性结果为: {'class': ['title'], 'name': 'dromouse'}
29 print(soup.p.attrs['name'])# 获取标签name属性, 返回单个值: dromouse
30 
31 (3).获取内容:可以利用string属性获取节点元素包含的文本内容
32 print(soup.p.string)# 结果为: The Dormouse's story
33 
34 # 4.选择定位标签的方式:
35 (1).直接获取一个:soup.title # 直接选取title标签
36 (2).嵌套选择: soup.p.b # 选取p标签下的b标签
37 (3).关联选择:(使用较少,简单介绍)
38             子节点和孙节点: contents
39             父节点和祖先节点: parent / parents
40             兄弟节点:Sibling
41     

 

返回顶部


4.方法选择器

 1 # BeautifulSoup提供了一些查询方法, 调用它们可以得到符合条件的元素
 2 
 3 # 方法如下:(重点为find()与find_all())
 4         find_all()
 5         find()
 6         find_parents()和find_parent()
 7         find_next_siblings()和find_next_sibling()
 8         find_previous_siblings()和find_previous_sibling()
 9         find_all_next()和find_next()
10         find_all_previous()和find_previous()

 

返回顶部

 1 # 1.find_all(name , attrs , recursive , text , **kwargs): 给该方法传入表现名, 或属性名就可以定位到符合条件的标签元素.
 2 
 3 # 2.定位参数:
 4     (1).标签名: name
 5     (2).属性值: attrs
 6     (3).正则化文本: re.compile("正则文本")
 7 
 8 # 3.示例:
 9 html='''
10 <div class="panel">
11 <div class="panel-heading">
12 <h4>Hello</h4>
13 </div>
14 <div class="panel-body">
15 <ul class="list" id="list-1" name="elements">
16 <li class="element">Foo</li>
17 <li class="element">Bar</li>
18 <li class="element" id="jay">Jay</li>
19 </ul>
20 <ul class="list list-small" id="list-2">
21 <li class="element">Foo</li>
22 <li class="element">Bar</li>
23 </ul>
24 </div>
25 </div>
26 '''
27 from bs4 importBeautifulSoup
28 
29 # 实例化BeautifulSoup对象, 传入文本与解析器参数
30 soup =BeautifulSoup(html,'lxml')
31 
32 # 通过name定位: 定位h4标签
33 print(soup.find_all(name="h4")
34 
35 # 属性attrs定位: 定位id为jay的标签
36 print(soup.find_all(attrs={'id':'jay'}))
37 
38 # 通过正则化文本定位: 定位文本信息为Foo的标签
39 print(soup.find_all(text=re.compile('Foo'))

 

返回顶部

1 # 1.find()与find_all基本相同, 不同之处在于find()只匹配第一个元素, 返回的是单个元素, 而find_all()返回的是所有匹配的元素组成的列表.
2 
3 # 其他方法简介:
4     1.find_parents()和find_parent():前者返回所有祖先节点,后者返回直接父节点。
5     2.find_next_siblings()和find_next_sibling():前者返回后面所有的兄弟节点,后者返回后面第一个兄弟节点。
6     3.find_previous_siblings()和find_previous_sibling():前者返回前面所有的兄弟节点,后者返回前面第一个兄弟节点。
7     4.find_all_next()和find_next():前者返回节点后所有符合条件的节点,后者返回第一个符合条件的节点。
8     5.find_all_previous()和find_previous():前者返回节点后所有符合条件的节点,后者返回第一个符合条件的节点。

 

返回顶部


5.CSS选择器

1 BeautifulSoup还提供了另外一种选择器,那就是CSS选择器。如果对Web开发熟悉的话,那么对CSS选择器肯定也不陌生。如果不熟悉的话,可以参考http://www.w3school.com.cn/cssref/css_selectors.asp了解。
2 使用CSS选择器时,只需要调用select()方法,传入相应的CSS选择器即可

 

返回顶部

 1 html='''
 2 <div class="panel">
 3 <div class="panel-heading">
 4 <h4>Hello</h4>
 5 </div>
 6 <div class="panel-body">
 7 <ul class="list" id="list-1">
 8 <li class="element">Foo</li>
 9 <li class="element">Bar</li>
10 <li class="element">Jay</li>
11 </ul>
12 <ul class="list list-small" id="list-2">
13 <li class="element">Foo</li>
14 <li class="element">Bar</li>
15 </ul>
16 </div>
17 </div>
18 '''
19 from bs4 importBeautifulSoup
20 # 实例化BeautifulSoup对象
21 soup =BeautifulSoup(html,'lxml')
22 
23 # 调用css选择器, 定位class属性值为panel标签下的class属性值为panel-heading的标签
24 print(soup.select('.panel .panel-heading'))
25 
26 # 调用css选择器, 定位所有ul标签下的所有li标签
27 print(soup.select('ul li'))
28 
29 # 调用css选择器, 定位id为list-2的标签下的class值为element的所有标签
30 print(soup.select('#list-2 .element'))
31 
32 # 调用css选择器, 定位所有ul标签,取第一个
33 print(type(soup.select('ul')[0]))
34 
35 # 结果输出:
36 [<div class="panel-heading"><h4>Hello</h4></div>]
37 
38 [<li class="element">Foo</li>, <li class="element">Bar</li>,<li class="element">Jay</li>, <li class="element">Foo</li>,<li class="element">Bar</li>]
39 
40 [<li class="element">Foo</li>, <li class="element">Bar</li>]
41 
42 <class'bs4.element.Tag'>

 

返回顶部

 1 # 从定位的标签获取目标数据
 2 (1).获取文本:调用string属性,如果定位的多个标签可以for循环取值
 3 li _list = soup.selcet("ul li")# 这是li组成的列表
 4 for li in li_list:
 5 print(li.string)
 6 
 7 (2).获取属性:调用attrs属性获取标签属性,使用attr与直接使用[]没有区别
 8 for li in li_list:
 9 print(li.attr['class'])
10 print(li['class'])

 

返回顶部


6.小贴士:

1 # 使用解析方法的小贴士:
2     1.推荐使用lxml解析库,必要时使用html.parser。
3     2.节点选择筛选功能弱但是速度快。
4     3.建议使用find()或者find_all()查询匹配单个结果或者多个结果。
5     4.如果对CSS选择器熟悉的话,可以使用select()方法选择。

 

返回顶部

posted on 2018-03-11 11:00  Jeremy_Yu  阅读(173)  评论(0)    收藏  举报

导航