目录
⭐A person can succeed at almost anything for which they have unlimited enthusiasm.
只要有无限的热情,一个人几乎可以在任何事情上取得成功。 🌈
活动地址:CSDN21天学习挑战赛
1. BeautifulSoup4概述
1.1 BeautifulSoup4介绍
BeautifulSoup是一个可以从HTML或XML文件中提取数据的Python库,它能够通过自己喜欢的转换器实现惯用的文档导航、查找、修改文档的方式。Beautiful可以节省数小时甚至数天的工作时间。BeautifulSoup4是Python第三方库,需要进行下载。Pycharm下载方式:地址
BeautifulSoup4将网页转换为一棵DOM树,如下图所示:
1.2 导入BeautifulSoup
from bs4 import BeautifulSoup
1.3 解析库
BeautifulSoup在解析式实际上依赖解析器,它除了支持Python标准宽中的HTML解析器外,还支持一些第三方解析器(比如lxml)。
解析器 | 使用方法 | 优势 | 劣势 |
---|---|---|---|
Python标准库 | BeautifulSoup(html, 'html.parser') | Python的内置标准、执行速度适中、文档容错能力强 | Python2.7.3及Python3.2.2之前的版本文档容错能力差 |
lxml HTML解析库 | BeautifulSoup(html, 'lxml') | 速度快、文档容错能力强 | 需要安装C语言库 |
lxml XML解析库 | BeautifulSoup(html, 'xml') | 速度快、唯一支持XML的解析器 | 需要安装C语言库 |
html5lib解析库 | BeautifulSoup(html, 'html5lib') | 最好的容错性、以浏览器的方式解析文档,生成HTMLS格式的文档 | 速度慢、不依赖外部扩展 |
其中,最常用的解析器是lxml HTML解析器,其次是html5lib 。
2. 应用举例
2.1 基础操作
方法 | 说明 |
---|---|
soup = BeautifulSoup(html, 'lxml') | 创建对象 |
soup = BeautifulSoup(open('test.html'),'lxml') | 读取HTML文件 |
soup.prettify() | 获取HTML的缩进格式 |
soup.title | 获取title标签的所有内容 |
soup.title.name | 获取title标签的名称 |
soup.title.string | 获取title的文本内容 |
soup.head | 获取head标签的所有内容 |
soup.div | 获取第一个div标签中的所有内容 |
soup.div['id'] | 获取第一个div标签的id的值 |
soup.a | 获取第一个a标签中的所有内容 |
soup.find_all('a') | 获取所有的a标签中的所有内容 |
soup.find(id='u1') | 获取id=u1的内容 |
for item in soup.find_all('a'): print(item.get('href')) | 获取所有的a标签,并遍历打印a变迁中的href值 |
for item in soup.find_all('a'): print(item.get_text()) | 获取所有的a标签,并遍历打印a标签的文本值 |
2.2 对象种类
BeautifulSoup将复杂的HTML文档转换成一个复杂的树形结构,每个节点都是Python对象,所有对象可以归纳为4中:Tag、NavigableString、BeautifulSoup、Comment。
2.2.1 Tag
Tag通俗点讲就是HTML中的一个个标签。Tag有很多方法和属性,在遍历文档树和搜索文档树中有详细解释。Tag最重要的属性是:name和attributes。注意:如果改变了Tag的name属性,将影响所有通过当前BeautifulSoup对象生成的HTML文档。Tag的属性可以被添加、删除和修改。
用法举例:
from bs4 import BeautifulSoup
soup = BeautifulSoup('<b class="boldest">Extremely bold</b>','lxml')
tag = soup.b
print(tag) #输出:<b class="boldest">Extremely bold</b>
print(type(tag)) #输出:<class 'bs4.element.Tag'>
#name属性
print(tag.name) #输出:b
tag.name = 'b1'
print(tag) #输出:<b1 class="boldest">Extremely bold</b1>
#Attributes属性
print(tag['class']) #选择class属性。输出:['boldest']
print(tag.attrs) #之间用“点”取属性,例如.attrs,选择attrs属性。输出:{'class': ['boldest']}
#添加id属性
tag['id']=1
#修改class属性
tag['class'] = 'tl1'
#删除class属性
del tag['class']
2.2.2 NavigableString
NavigableString用.string获取标签内部的文字。
用法举例:
from bs4 import BeautifulSoup
soup = BeautifulSoup('<b class="boldest">Extremely bold</b>','lxml')
print(soup.b.string) #输出:Extremely bold
print(type(soup.b.string)) #输出:<class 'bs4.element.NavigableString'>
2.2.3 BeautifuSoup
BeautifulSoup表示的是一个文档的内容,可以获取它的类型、名称以及属性。
用法举例:
from bs4 import BeautifulSoup
soup = BeautifulSoup('<b class="boldest">Extremely bold</b>','lxml')
print(type(soup.name)) #输出:<class 'str'>
print(soup.name) #输出:[document]
print(soup.attrs) #输出:{} 文档本身的属性为空
2.2.4 Comment
Comment是一个特殊类型的NavigableString对象,其输出的内容不包括注释符号。
用法举例:
from bs4 import BeautifulSoup
soup = BeautifulSoup('<b class="boldest">Extremely bold</b>','lxml')
print(soup.b) #输出:<b class="boldest">Extremely bold</b>
print(soup.b.string) #输出:Extremely bold
print(type(soup.b.string)) #输出:<class 'bs4.element.NavigableString'>
2.3 搜索文档树
函数语法:find_all(name, attrs, recursive, text, **kwargs)
参数说明:
name :name参数可以查找所有名字为name的tag,字符串对象会被自动忽略掉。可以匹配字符串、正则表达式、列表;
text :通过text参数可以搜搜文档中的字符串内容,与name参数的可选值一样,text参数接收字符串、正则表达式、列表;
用法举例:
1.name参数举例
soup.find_all('a') :查找与字符串完整匹配的内容,用于查找文档中所有的<a>标签
soup.find_all(re.compile('^b')) :传入正则表达式,BeautifulSoup会通过正则表达式的match()来匹配内容。返回所有表示<body>和<b>标签。
soup.find_all(['p','a']) :传入列表参数,BeautifulSoup会与列表中任一元素匹配的内容返回。返回所有的<p>和<a>标签。
2.text参数举例
soup.find_all(text='a') :匹配字符串
soup.find_all(text=re.compile('^b')) :匹配正则表达式
soup.find_all(text=['p', 'a']) :匹配列表
3.kwargs参数举例
soup.find_all(id='link2')
2.4 css选择器
在使用BeautifulSoup解析库时,经常会结合css选择器来提取数据。以下仅介绍css选择器选择标签。
获取方式 | 举例说明 |
---|---|
根据标签名查找 | 比如写一个 li 就会选择所有的 li标签,一般不用,因为都是精确到标签再提取数据 |
根据类名class查找 | .line,即一个点加line,这个表达式选的时class=‘line’的所有标签,‘.‘代表class |
根据id查找 | #box,即一个井号加box,表示选取id=’box‘的所有标签,“#”代表id |
根据属性的名字查找 | data[name='username']表达式查找name='username'标签,此处注意和Xpath的区别。 |
标签+类名或id的形式 | 例如:ul#list-1。查找id为list-1的ul标签 |
查找直接子元素 | 例如:#list-1>li。查找id='list-1'的标签下的直接子元素li |
查找子孙标签 | 例如:.panel_body li。.panel_body和li直接是一个空格,表示查找id='panel_body'标签下的子或孙标签li |
取某个标签的属性 | 例如:data['href']。选择data中的href属性的内容。 |
1)获取文本内容:string | 获得某个标签下的文本内容,强调一个标签,不含嵌套。返回一个字符串 |
2)获取文本内容:strings | 获得某个标签下的所有文本内容,可以嵌套。返回一个生成器,可用list(生成器)转换为列表 |
3)获取文本内容:stripped.strings | 跟第二种方法差不多,只不过它会去掉每个字符串头部和尾部的空格和换行符 |
4)获取文本内容:get.text() | 获取所有字符串,含嵌套,不管会把所有字符串拼接为一个,然后返回。 |
注意:获取文本内容的前3个是属性,不加括号;最后一个是函数,加括号。
用法举例:
from bs4 import BeautifulSoup
html = '''
<div class="panel">
<div class="panel-heading">
<h4>Hello</h4>
</div>
<div class="panel_body">
<ul class="list" id="list-1" name="element">
<li class="element">Foo</li>
<li class="element">Bar</li>
<li class="element">Jay</li>
</ul>
<ul class="list list-small" id="list-2">
<li class="element">Foo</li>
<a href="https://www.baidu.com">百度官网</a>
<li class="element">Bar</li>
</ul>
</div>
</div>
'''
#创建对象
soup = BeautifulSoup(html, 'lxml')
#1.根据标签名查找:查找li标签
print(soup.select("li"))
#2.根据类名class查找
print(soup.select(".panel_body"))
#3.根据id查找
print(soup.select('#list-1'))
#4.根据属性名查找
print(soup.select("ul[name='element']"))
#5.标签+类名或id的形式
print(soup.select('ul#list-1')) #查找id为list-1的ul标签
print(soup.select('ul.list')) #查找calss为list的ul标签
#6.查找字节子元素
print(soup.select('#list-1>li')) #查找id='list-1'的标签下的直接子标签li
#7.查找子孙标签
print(soup.select('.panel_body li' )) #.panel_body和li之间是一个空格,表示查找id='panel_body'的标签下的子或孙标签li
#8.取某个标签的属性
div = soup.select('.panel_body')[0] #先取到<div class='panel_body'>
print(div.select('a')[0]['href']) #再取下面的a标签下的href属性
#9.1 string:获取某个标签下的文本内容,强调一个标签,不含嵌套,返回一个字符串。
div = soup.select('.panel_body')[0] #先取到<div class='panel_body'>
print(div.select('a')[0].string) #再取下面的a标签的内容
#9.2 strings:获得某个标签下的所有文本内容,可以嵌套。返回一个生成器,可用list(生成器)转换为列表
print(div.strings)
print(list(div.strings))
#9.3 stripped.strings:跟9.2差不多,只不过会去掉每个子不传头部和尾部的空格和换行符
print(soup.stripped_strings)
print(list(soup.stripped_strings))
#9.4 get.text()获取所有字符串,含嵌套。不管会把所有字符串拼接为一个,然后返回
print(div.get_text())