Beautiful Soup 是一个能够从HTML或XML文件中提取数据的Python库.它可以经过你喜欢的转换器实现惯用的文档导航,查找,修改文档的方式html
在python3版本中安装BeautifulSouphtml5
pip install BeautifulSoup4
也能够经过下载BS4的源码,经过setup.py来安装python
主要的几个解析器:浏览器
bs4的HTML解析器-->BeautifulSoup(mk,'html.parser')-->安装bs4库markdown
lxml的HTML解析器-->BeautifulSoup(mk,'lxml')-->pip install lxml框架
lxml的XML解析器-->BeautifulSoup(mk,'xml')-->pip install lxmlide
html5lib的解析器-->BeautifulSoup(mk,'html5lib')-->pip installl html5lib函数
解析器 | 使用方法 | 优点 | 劣势 |
---|---|---|---|
Python标准库 | BeautifulSoup(markup, "html.parser") | 1.Python的内置标准库2.执行速度适中3.文档容错能力强 | Python 2.7.3 or 3.2.2)前 的版本中文档容错能力差 |
lxml HTML 解析器 | BeautifulSoup(markup, "lxml") | 1.速度快2.文档容错能力强 | 须要安装C语言库 |
lxml XML 解析器 | BeautifulSoup(markup, ["lxml-xml"])/BeautifulSoup(markup, "xml") | 1.速度快2.惟一支持XML的解析器 | 须要安装C语言库 |
html5lib | BeautifulSoup(markup, "html5lib") | 1.最好的容错性2.以浏览器的方式解析文档3.生成HTML5格式的文档 | 1.速度慢2.不依赖外部扩展 |
推荐使用lxml做为解析器,效率高。测试
Beautiful Soup支持Python标准库中的HTML解析器,还支持一些第三方的解析器,其中一个是 lxml .根据操做系统不一样,能够选择下列方法来安装lxml。this
pip install lxml
解析原理:
实例化一个BeautifulSoup对象,且将即将被解析的页面源码加载到该对象中
使用该对象中的属性或方法进行标签订位和数据提取
解析方式:
BeautifulSoup(fp,"lxml"),lxml指定解析器,将本地存储的html文档加载到该对象中
BeautifulSoup(page_text,"lxml"),将互联网上获取的html源码加载到该对象中
from bs4 import BeautifulSoup soup = BeautifulSoup('<p>data</p>', 'html.parser')
BeautifulSoup库是解析、遍历、维护“标签树”的功能库
BeautifulSoup对象和文档树是对应的
Tag:标签,最基本的信息组织单元,分别用<>和</>标明开头和结尾
Name:标签的名字,<p>…</p>的名字是'p',格式:<tag>.name
Attributes:标签的属性,字典形式组织,格式:<tag>.attrs
NavigableString:标签内非属性字符串,<>…</>中字符串,格式:<tag>.string
Comment:标签内字符串的注释部分,一种特殊的Comment类型
本地文件test.html
<html lang="en"> <head> <meta charset="utf-8"/> <title>测试bs4</title> </head> <body> <div> <p>百里守约</p> </div> <div class="song"> <p>李清照</p> <p>王安石</p> <p>苏轼</p> <p>柳宗元</p> <a href="http://www.song.com/" target="_self" title="赵匡胤"> <span>this is span</span> 宋朝是最强大的王朝,不是军队的强大,而是经济很强大,国民都颇有钱</a> <a class="du" href="">总为浮云能蔽日,长安不见令人愁</a> <img alt="" src="http://www.baidu.com/meinv.jpg"/> </div> <div class="tang"> <ul> <li><a href="http://www.baidu.com" title="qing">清明时节雨纷纷,路上行人欲断魂,借问酒家何处有,牧童遥指杏花村</a></li> <li><a href="http://www.163.com" title="qin">秦时明月汉时关,万里长征人未还,但使龙城飞将在,不教胡马度阴山</a></li> <li><a alt="qi" href="http://www.126.com">岐王宅里寻常见,崔九堂前几度闻,正是江南好风景,落花时节又逢君</a></li> <li><a class="du" href="http://www.sina.com">杜甫</a></li> <li><a class="du" href="http://www.dudu.com">杜牧</a></li> <li><b>杜小月</b></li> <li><i>度蜜月</i></li> <li><a href="http://www.haha.com" id="feng">凤凰台上凤凰游,凤去台空江自流,吴宫花草埋幽径,晋代衣冠成古丘</a></li> </ul> </div> </body> </html>
利用lxml解析成soup对象
from bs4 import BeautifulSoup fp = open("./test.html","r",encoding="utf-8") soup = BeautifulSoup(fp,"lxml")
Tag 对象与XML或HTML原生文档中的tag相同
soup.tagName:返回的是页面中第一次出现的tagName标签,(一个单数)
tag = soup.title type(tag) # <title>测试bs4</title>
标签对象的那么属性:每一个tag都有本身的名字,经过 .name 来获取
tag.name # u'title'
一个tag可能有不少个属性. tag <b class="boldest"> 有一个 “class” 的属性,值为 “boldest” . tag的属性的操做方法与字典相同
soup.find("tagName",attrName="value")
注意:返回的是单数
tag = soup.find("div",class_="song") # 由于class为关键字,因此改成class_
tag对象能够直接“点”取属性,好比:.attrs
tag.attrs # {u'class': u'song'}
soup.find_all("tagName"):定位全部的tagName的标签
soup.find_all("tagName",attrName="value"):属性定位
注意:返回值是列表
soup.find_all("div") soup.find_all("div",class_="song")
select("选择器"):根据选择器进行标签订位且返回的是复数(列表)
标签选择器,id选择器,类选择器,属性选择器,层级选择器
层级选择器:>表示一个层级,空格表示多个层级
soup.select(".tang")
层级选择
# soup.select(".tang li") soup.select(".tang > ul > li") # 二者效果相同
string:获取找到的标签中第一个标签的文本
soup.p.string # 获取第一个p标签的文本 # '百里守约'
text:获取找到的标签中第一个标签的文本
soup.p.text # 获取第一个p标签的文本 # '百里守约'
区别:
string获取的是标签中只存在文本的直系文本内容,
text获取的是标签中全部的文本内容
tag["attrName"]
for a in soup.select(".tang > ul > li > a"): print(a["href"]) http://www.baidu.com http://www.163.com http://www.126.com http://www.sina.com http://www.dudu.com http://www.haha.com
bs4库的html输出格式
bs4的prettify方法:为html文内容添加换行符,是文本格式更加清晰
soup.prettify
html基本格式
.contents:子节点的列表,将<tag>全部儿子节点存入列表 .children:子节点的迭代类型,与.contents相似,用于循环遍历儿子节点 .descendants:子孙节点的迭代类型,包含全部子孙节点,用于循环遍历
for child in soup.body.children: # 遍历儿子节点 print(child) for child in soup.body.descendants: # 遍历子孙节点 print(child)
.parent:节点的父亲标签 .parents:节点先辈标签的迭代类型,用于循环遍历先辈节点
代码框架
soup = BeautifulSoup(demo, "html.parser") for parent in soup.a.parents: if parent is None: print(parent) else: print(parent.name)
.next_sibling:返回按照HTML文本顺序的下一个平行节点标签 .previous_sibling:返回按照HTML文本顺序的上一个平行节点标签 .next_siblings:迭代类型,返回按照HTML文本顺序的后续全部平行节点标签 .previous_siblings:迭代类型,返回按照HTML文本顺序的前续全部平行节点标签
1.XML:eXtensible Markup Language
标签内容的表达形式:
<name> … </name> 标签中有内容 <name/> 标签中没有内容 <!-- --> 注释表达方式
2.JSON:JavsScript Object Notation
有类型的键值对 key:value,"name":"北京理工大学"
键值对的值有多个:"name":["北京理工大学","延安天然科学院"]
键值对的嵌套使用
3.YAML:YAML Ain't Markup Language
无类型键值对key:value name:北京理工大学
键值对的值有多个:“-”表达并列关系
键值对的嵌套使用:用缩进表达所属关系
| 表达整块数据,#表示注释
XML:最先的通用信息标记语言,可扩展性好,但繁琐
Internet上的信息交互与传递
JSON:信息有类型,适合程序处理(js),较XML简洁
移动应用云端和节点的信息通讯,无注释,优点:在通过传输后可以做为程序代码的一部分,缺点:没法体现注释
YAML:信息无类型,文本信息比例最高,可读性好
用于各种系统的配置文件,有注释易读
方法一:完整解析信息的标记形式,在提取关键信息
标记解析器解析:XML JSON YAML
须要标记解析器,如:bs4库的标签树遍历
优势:信息解析准确
提取过程繁琐,速度慢
方法二:无视标记形式,直接搜索关键信息
搜索:对信息的文本产找函数便可
优势:提取过程简洁,速度较快
缺点:提取结果准确性与信息内容相关
融合方法:结合形式解析和搜索方法,提取关键信息
须要表及解析器及文本查找函数
实例:
提取HTML中全部URL连接
思路:
搜索到全部<a>标签
解析<a>标签格式,提取herf后的连接内容