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()方法选择。
浙公网安备 33010602011771号