python3解析库BeautifulSoup4的安装配置与基本用法


Posted in Python onJune 26, 2018

前言

Beautiful Soup是python的一个HTML或XML的解析库,我们可以用它来方便的从网页中提取数据,它拥有强大的API和多样的解析方式。

Beautiful Soup的三个特点:

  • Beautiful Soup提供一些简单的方法和python式函数,用于浏览,搜索和修改解析树,它是一个工具箱,通过解析文档为用户提供需要抓取的数据
  • Beautiful Soup自动将转入稳定转换为Unicode编码,输出文档转换为UTF-8编码,不需要考虑编码,除非文档没有指定编码方式,这时只需要指定原始编码即可
  • Beautiful Soup位于流行的Python解析器(如lxml和html5lib)之上,允许您尝试不同的解析策略或交易速度以获得灵活性。

1、Beautiful Soup4的安装配置

Beautiful Soup4通过PyPi发布,所以可以通过系统管理包工具安装,包名字为beautifulsoup4

$easy_install beautifulsoup4
或者
$pip install beautifulsoup4

也可用通过下载源码包来安装:

#wget https://www.crummy.com/software/BeautifulSoup/bs4/download/4.0/beautifulsoup4-4.1.0.tar.gz
#tar xf beautifulsoup4-4.1.0.tar.gz
#cd beautifulsoup4
#python setup.py install

Beautiful Soup在解析时实际上是依赖解析器的,它除了支持python标准库中的HTML解析器外还支持第三方解析器如lxml

Beautiful Soup支持的解析器,以及它们的优缺点:

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

安装解析器:

$pip install lxml
$pip install html5lib

推荐使用lxml作为解析器,因为效率更高. 在Python2.7.3之前的版本和Python3中3.2.2之前的版本,必须安装lxml或html5lib, 因为那些Python版本的标准库中内置的HTML解析方法不够稳定

2、BeautifulSoup的基本用法

通过传入一段字符或一个文件句柄,BeautifulSoup的构造方法就能得到一个文档的对象,选择合适的解析器来解析文档,如手动指定将选择指定的解析器来解析文档,Beautiful Soup将复杂的HTML文档转换成一个复杂的树形结构,每个节点都是python对象,所有对象可以归纳为4种:Tag、NavigableString、BeautifulSoup、Comment

注意:BeautifulSoup版本4的包是在bs4中引入的

from bs4 import BeautifulSoup

#下面代码示例都是用此文档测试
html_doc = """
<html><head><title>The Dormouse's story</title></head>
<body>
<p class="title"><b>The Dormouse's story</b></p>

<p class="story">Once upon a time there were three little sisters; and their names were
<a href="http://example.com/elsie" rel="external nofollow" class="sister" id="link1">Elsie</a>,
<a href="http://example.com/lacie" rel="external nofollow" class="sister" id="link2">Lacie</a> and
<a href="http://example.com/tillie" rel="external nofollow" class="sister" id="link3">Tillie</a>;
and they lived at the bottom of a well.</p>

<p class="story">...</p>
"""
markup="<b><!--Hey, buddy. Want to buy a used parser?--></b>"
soup=BeautifulSoup(html_doc,"lxml")
soup1=BeautifulSoup(markup,"lxml")
tag=soup.a
navstr=tag.string
comment=soup1.b.string
print(type(tag)) #Tag标签对象
print(type(comment)) #Comment对象包含文档注释内容
print(type(navstr)) #NavigableString对象包装字符串内容
print(type(soup)) #BeautifulSoup对象为文档的全部内容

#
<class 'bs4.element.Tag'>
<class 'bs4.element.Comment'>
<class 'bs4.element.NavigableString'>
<class 'bs4.BeautifulSoup'>

(1)节点选择器(tag)

直接调用节点的名称就可以选择节点元素,节点可以嵌套选择返回的类型都是bs4.element.Tag对象

soup=BeautifulSoup(html_doc,'lxml')
print(soup.head) #获取head标签
print(soup.p.b) #获取p节点下的b节点
print(soup.a.string) #获取a标签下的文本,只获取第一个

name属性获取节点名称:

soup.body.name

attrs属性获取节点属性,也可以字典的形式直接获取,返回的结果可能是列表或字符串类型,取决于节点类型

soup.p.attrs #获取p节点所有属性
soup.p.attrs['class'] #获取p节点class属性
soup.p['class'] #直接获取p节点class属性

string属性获取节点元素包含的文本内容:

soup.p.string #获取第一个p节点下的文本内容

contents属性获取节点的直接子节点,以列表的形式返回内容

soup.body.contents #是直接子节点,不包括子孙节点

children属性获取的也是节点的直接子节点,只是以生成器的类型返回

soup.body.children

descendants属性获取子孙节点,返回生成器

soup.body.descendants

parent属性获取父节点,parents获取祖先节点,返回生成器

soup.b.parent
soup.b.parents

next_sibling属性返回下一个兄弟节点,previous_sibling返回上一个兄弟节点,注意换行符也是一个节点,所以有时候在获取兄弟节点是通常是字符串或者空白

soup.a.next_sibling
soup.a.previous_sibling

next_siblings和previous_sibling分别返回前面和后面的所有兄弟节点,返回生成器

soup.a.next_siblings
soup.a.previous_siblings

next_element和previous_element属性获取下一个被解析的对象,或者上一个

soup.a.next_element
soup.a.previous_element

next_elements和previous_elements迭代器向前或者后访问文档解析内容

soup.a.next_elements
soup.a.previous_elements

(2)方法选择器

前面使用的都是通过节点属性来选择的,这种方法非常快,但在进行比较复杂的选择时就不够灵活,幸好Beautiful Soup还为我们提供了一些查询方法,如fang_all()和find()等

find_all(name,attrs,recursive,text,**kwargs):查询所有符合条件的元素,其中的参数

name表示可以查找所有名字为name的标签(tag),也可以是过滤器,正则表达式,列表或者是True

attrs表示传入的属性,可以通过attrs参数以字典的形式指定如常用属性id,attrs={'id':'123'},由于class属性是python中的关键字,所有在查询时需要在class后面加上下划线即class_='element',返回的结果是tag类型的列表

text参数用来匹配节点的文本,传入的形式可以是字符串也可以是正则表达式对象

recursive表示,如果只想搜索直接子节点可以将参数设为false:recursive=Flase

limit参数,可以用来限制返回结果的数量,与SQL中的limit关键字类似

import re
from bs4 import BeautifulSoup

html_doc = """ #下面示例都是用此文本内容测试
<html><head><title>The Dormouse's story</title></head>
<body>
<p class="title"><b>The Dormouse's story</b></p>
<p class="story">Once upon a time there were three little sisters; and their names were
<a href="http://example.com/elsie" class="sister" id="link1">Elsie</a>
 ddd
<a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and
<a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>;
and they lived at the bottom of a well.</p>
<p class="story">...</p>
<span>中文</span>
"""

soup=BeautifulSoup(html_doc,'lxml')
print(type(soup))
print(soup.find_all('span')) #标签查找
print(soup.find_all('a',id='link1')) #属性加标签过滤
print(soup.find_all('a',attrs={'class':'sister','id':'link3'})) #多属性
print(soup.find_all('p',class_='title')) #class特殊性,此次传入的参数是**kwargs
print(soup.find_all(text=re.compile('Tillie'))) #文本过滤
print(soup.find_all('a',limit=2)) #限制输出数量


#
<class 'bs4.BeautifulSoup'>
[<span>中文</span>]
[<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>]
[<a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]
[<p class="title"><b>The Dormouse's story</b></p>]
['Tillie']
[<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>, <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>]

find( name , attrs , recursive , text , **kwargs ):它返回的是单个元素,也就是第一个匹配的元素,类型依然是tag类型

参数同find_all()一样

另外还有许多查询方法,其用法和前面介绍的find_all()方法完全相同,只不过查询范围不同,参数也一样

find_parents(name , attrs , recursive , text , **kwargs )find_parent(name , attrs , recursive , text , **kwargs ) :前者返回所有祖先节点,后者返回直接父节点

find_next_siblings(name , attrs , recursive , text , **kwargs )find_next_sibling(name , attrs , recursive , text , **kwargs ) :对当前tag后面的节点进行迭代,前者返回后面的所有兄弟节点,后者返回后面第一个兄弟节点

find_previous_siblings(name , attrs , recursive , text , **kwargs )find_previous_sibling(name , attrs , recursive , text , **kwargs ) :对当前tag前面的节点进行迭代,前者返回前面的所有兄弟节点,后者返回前面的第一个兄弟节点

find_all_next(name , attrs , recursive , text , **kwargs )find_next(name , attrs , recursive , text , **kwargs ) :对当前tag之后的tag和字符串进行迭代,前者返回所有符合条件的节点,后者返回第一个符合条件的节点

find_all_previous()find_previous() :对当前tag之前的tag和字符串进行迭代,前者返回节点后所有符合条件的节点,后者返回第一个符合条件的节点

(3)CSS选择器

Beautiful Soup还提供了CSS选择器,如果多CSS选择器不熟悉可以参考下http://www.w3school.com.cn/cssref/css_selectors.asp

在 Tag 或 BeautifulSoup 对象的 .select()方法中传入字符串参数,即可使用CSS选择器的语法找到tag:

In [10]: soup.select('title')
Out[10]: [<title>The Dormouse's story</title>]

通过tag标签逐层查找:

In [12]: soup.select('body a')
Out[12]: 
[<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>,
 <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>,
 <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]

查找某个tag标签下的直接子标签:

In [13]: soup.select('head > title')
Out[13]: [<title>The Dormouse's story</title>]

查找兄弟节点标签:

In [14]: soup.select('#link1 ~ .sister')
Out[14]: 
[<a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>,
 <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]

通过CSS类名查找:

In [15]: soup.select('.title')
Out[15]: [<p class="title"><b>The Dormouse's story</b></p>]

In [16]: soup.select('[class~=title]')
Out[16]: [<p class="title"><b>The Dormouse's story</b></p>]

通过tag的id查找:

In [17]: soup.select('#link1')
Out[17]: [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>]

In [18]: soup.select('a#link2')
Out[18]: [<a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>]

通过是否存在某个属性来查找:

In [20]: soup.select('a[href]')
Out[20]: 
[<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>,
 <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>,
 <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]

通过属性的值来查找匹配:

In [22]: soup.select('a[href="http://example.com/elsie"]')
Out[22]: [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>]

In [23]: soup.select('a[href^="http://example.com/"]') #匹配值的开头
Out[23]: 
[<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>,
 <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>,
 <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]

In [24]: soup.select('a[href$="tillie"]') #匹配值的结尾
Out[24]: [<a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]

In [25]: soup.select('a[href*=".com/el"]') #模糊匹配
Out[25]: [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>]

tag节点查找,方法选择器查找和CSS选择器查找三种方法的实现方式基本相似,tag相对于其他两种所有最快速的查找方式,但方法选择器提供更便利更复杂的查找方式,使用更如有上手。

(4)tag修改方法

Beautiful Soup的强项是文档的搜索功能,修改功能使用场景不是很多只做简单介绍,要了解更多修改方法请前往Beautiful Soup官方文档查看。

Beautiful Soup可以实现改变tag标志的属性的值,添加或删除属性和内容,下面介绍一些常用的方法

In [26]: markup='<a href="http://www.baidu.com/">baidu</a>'
In [28]: soup=BeautifulSoup(markup,'lxml')
In [29]: soup.a.string='百度'
In [30]: soup.a
Out[30]: <a href="http://www.baidu.com/">百度</a>
#如果a节点下包括子也将被覆盖掉

Tag.append() 方法想tag中添加内容,就好像Python的列表的 .append() 方法:

In [30]: soup.a
Out[30]: <a href="http://www.baidu.com/">百度</a>

In [31]: soup.a.append('一下')

In [32]: soup.a
Out[32]: <a href="http://www.baidu.com/">百度一下</a>

new_tag()方法用于创建一个tag标签

In [33]: soup=BeautifulSoup('<b></b>','lxml')

In [34]: new_tag=soup.new_tag('a',href="http://www.python.org") #创建tag,第一个参数必须为tag的名称

In [35]: soup.b.append(new_tag) #添加到b节点下

In [36]: new_tag.string='python' #为tag设置值

In [37]: soup.b
Out[37]: <b><a href="http://www.python.org">python</a></b>

其他方法:

insert()将元素插入到指定的位置

inert_before()在当前tag或文本节点前插入内容

insert_after()在当前tag或文本节点后插入内容

clear()移除当前tag的内容

extract()将当前tag移除文档数,并作为方法结果返回

prettify()将Beautiful Soup的文档数格式化后以Unicode编码输出,tag节点也可以调用

get_text()输出tag中包含的文本内容,包括子孙tag中的内容

soup.original_encoding 属性记录了自动识别的编码结果

from_encoding:参数在创建BeautifulSoup对象是可以用来指定编码,减少猜测编码的运行速度

#解析部分文档,可以使用SoupStrainer类来创建一个内容过滤器,它接受同搜索方法相同的参数

from bs4 import BeautifulSoup,SoupStrainer

html_doc = """
<html><head><title>The Dormouse's story</title></head>
<body>
<p class="title"><b>The Dormouse's story</b></p>
<p class="story">Once upon a time there were three little sisters; and their names were
<a href="http://example.com/elsie" class="sister" id="link1">Elsie</a>
 ddd
<a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and
<a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>;
and they lived at the bottom of a well.</p>
<p class="story">...</p>
<span>中文</span>
"""


only_a_tags = SoupStrainer('a') #顾虑器

soup=BeautifulSoup(html_doc,'lxml',parse_only=only_a_tags)

print(soup.prettify())

#
<a class="sister" href="http://example.com/elsie" id="link1">
 Elsie
</a>
<a class="sister" href="http://example.com/lacie" id="link2">
 Lacie
</a>
<a class="sister" href="http://example.com/tillie" id="link3">
 Tillie
</a>

#Beautiful Soup异常处理:

HTMLParser.HTMLParseError:malformed     start    tag 

HTMLParser.HTMLParseError:bad   end   tag 这个两个异常都是解析器引起的,解决方法是安装lxml或者html5lib

更多内容...

官方文档:https://www.crummy.com/software/BeautifulSoup/bs4/doc/

中文文档:https://www.crummy.com/software/BeautifulSoup/bs4/doc.zh

PyPI:https://pypi.org/project/beautifulsoup4/

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

Python 相关文章推荐
Python2中的raw_input() 与 input()
Jun 12 Python
Python加密方法小结【md5,base64,sha1】
Jul 13 Python
Python实现的递归神经网络简单示例
Aug 11 Python
Python中将dataframe转换为字典的实例
Apr 13 Python
Python3实现的字典遍历操作详解
Apr 18 Python
Python 获取中文字拼音首个字母的方法
Nov 28 Python
python实现贪吃蛇游戏
Mar 21 Python
我用Python抓取了7000 多本电子书案例详解
Mar 25 Python
python实现键盘输入的实操方法
Jul 16 Python
python用win32gui遍历窗口并设置窗口位置的方法
Jul 26 Python
Python 字符串、列表、元组的截取与切片操作示例
Sep 17 Python
Python操作SQLite/MySQL/LMDB数据库的方法
Nov 07 Python
Python 修改列表中的元素方法
Jun 26 #Python
Python 找到列表中满足某些条件的元素方法
Jun 26 #Python
python3解析库pyquery的深入讲解
Jun 26 #Python
Python将list中的string批量转化成int/float的方法
Jun 26 #Python
python中从str中提取元素到list以及将list转换为str的方法
Jun 26 #Python
django2+uwsgi+nginx上线部署到服务器Ubuntu16.04
Jun 26 #Python
pycharm下查看python的变量类型和变量内容的方法
Jun 26 #Python
You might like
采用thinkphp自带方法生成静态html文件详解
2014/06/13 PHP
CodeIgniter常用知识点小结
2016/05/26 PHP
php微信浏览器分享设置以及回调详解
2016/08/01 PHP
php redis实现对200w用户的即时推送
2017/03/04 PHP
phpwind放自动注册方法
2006/12/02 Javascript
jQuery UI Dialog控件中的表单无法正常提交的解决方法
2010/12/19 Javascript
extjs表格文本启用选择复制功能具体实现
2013/10/11 Javascript
javascript 按键事件(兼容各浏览器)
2013/12/20 Javascript
谷歌地图打不开的解决办法
2014/08/07 Javascript
jQuery中serializeArray()与serialize()的区别实例分析
2015/12/09 Javascript
使用jQuery判断Div是否在可视区域的方法 判断div是否可见
2016/02/17 Javascript
JavaScript操作 url 中 search 部分方法函数
2016/06/15 Javascript
node.js学习之交互式解释器REPL详解
2016/12/08 Javascript
js时间查询插件使用详解
2017/04/07 Javascript
使用 Node.js 对文本内容分词和关键词抽取
2017/05/27 Javascript
vue将后台数据时间戳转换成日期格式
2019/07/31 Javascript
使用Angular material主题定义自己的组件库的配色体系
2019/09/04 Javascript
vue-property-decorator用法详解
2019/12/12 Javascript
超详细小程序定位地图模块全系列开发教学
2020/11/24 Javascript
[05:22]DOTA2 2015国际邀请赛中国区预选赛首日TOP10
2015/05/26 DOTA
wxPython中listbox用法实例详解
2015/06/01 Python
Python回文字符串及回文数字判定功能示例
2018/03/20 Python
Pyqt5 基本界面组件之inputDialog的使用
2019/06/25 Python
Python 实现大整数乘法算法的示例代码
2019/09/17 Python
浅析python标准库中的glob
2020/03/13 Python
Python任务调度利器之APScheduler详解
2020/04/02 Python
全球在线商店:BerryLook
2019/04/14 全球购物
金山毒霸系列的笔试题
2013/04/13 面试题
行政总经理岗位职责
2013/12/05 职场文书
房屋改造计划书
2014/01/10 职场文书
30年同学聚会邀请函
2014/01/25 职场文书
装饰工程师岗位职责
2014/06/08 职场文书
解除劳动合同协议书范本
2014/09/13 职场文书
2015年度党风廉政建设工作情况汇报
2015/01/02 职场文书
golang gopm get -g -v 无法获取第三方库的解决方案
2021/05/05 Golang
Python一些基本的图像操作和处理总结
2021/06/23 Python