简介
解析库BeautifulSoup4和XPath一样都是解析用的,他不是完整的hmtl BeautifulSoup4也可以复原,他是在html和xml中查找信息的语言,他是通过标签属性来查询,Beautiful Soup 自动将输入文档转换为 Unicode 编码,输出文档转换为 UTF-8 编码
lxml 只 会 局 Object 部 遍 历 Model)的,会载入整个文档,解析整个 , Beautiful Soup 是 基 的
于 HTML DOM
DOM树,因此时间和内存开销都会大很多,所以性能要低于lxml。
Beautiful Soup 提取数据速度最慢
安装bs4
默认kali已经安装了
安装
1
| pip3 install beautifulsoup4
|
解析器
BeautifulSoup4依赖解析器,它除了支持 Python 标准库中的 HTML 解析器外,还支持一些第三方解析器(比如 lxml)

Python 标准库
Python 的内置标准库、执行速度适中、文档容错能力强
Python 2.7.3 及 Python 3.2.2 之前的版本文档容错能力差
1
| BeautifulSoup(markup, "html.parser")
|
lxml HTML 解析器
速度快、文档容错能力强
需要安装 C 语言库
1
| BeautifulSoup(markup, "lxml")
|
lxml XML 解析器
速度快、唯一支持 XML 的解析器
需要安装 C 语言库
1
| BeautifulSoup(markup, "xml")
|
html5lib
最好的容错性、以浏览器的方式解析文档、生成 HTML5 格式的文档
速度慢、不依赖外部扩展
通过以上对比可以看出,lxml 解析器有解析 HTML 和 XML 的功能,而且速度快,容错能力强,所以推荐使用它。
如果使用 lxml,那么在初始化 Beautiful Soup 时,可以把第二个参数改为 lxml 即可
1
| BeautifulSoup(markup, "html5lib")
|
指定使用那个解析库
格式
1
| soup = BeautifulSoup('<p>Hello</p>', '要用的解析库的名字')
|
咧
1 2 3
| from bs4 import BeautifulSoup soup = BeautifulSoup('<p>Hello</p>', 'lxml') print(soup.p.string)
|
用法
下面提取出来的内容都是
语法bs4.element.Tag 类型的
获得节点下的内容
1 2
| soup = BeautifulSoup(html, 'lxml') soup.要获得的节点的名字
|
咧
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| from bs4 import BeautifulSoup html = \ """ <div id="top"> <span class="position" width="350">职位名称</span> <span>职位类别</span> <li class="item-0"> <a href="link1.html">爬虫</a> </li> </div> """
soup = BeautifulSoup(html, 'lxml')
print(soup.div)
|
结果
1 2 3 4 5 6 7
| <div id="top"> <span class="position" width="350">职位名称</span> <span>职位类别</span> <li class="item-0"> <a href="link1.html">爬虫</a> </li> </div>
|

string属性显示数据内容
他只能取单个节点
语法
1 2
| soup = BeautifulSoup(html, 'lxml') soup.要获得的节点的名字.string
|
咧
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| from bs4 import BeautifulSoup html = \ """ <div id="top"> <span class="position" width="350">职位名称</span> <span>职位类别</span> <li class="item-0"> <a href="link1.html">爬虫</a> </li> </div> """
soup = BeautifulSoup(html, 'lxml')
print(soup.span.string)
print(soup.div.string)
|
结果可以看见只能取单节点内容

prettify()标准的缩进格式输出
他就是叫乱的html进行标准的缩进格式输出
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| from bs4 import BeautifulSoup html = \ """ <div id="top"> <span class="position" width="350">职位名称</span> <span>职位类别</span> <li class="item-0"> <a href="link1.html">爬虫</a> </li> </div> """
soup = BeautifulSoup(html, 'lxml')
print(soup.prettify())
|
结果可以看见他的排序都是标准的,还有缩进
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| <html> <body> <div id="top"> <span class="position" width="350"> 职位名称 </span> <span> 职位类别 </span> <li class="item-0"> <a href="link1.html"> 爬虫 </a> </li> </div> </body> </html>
|
name属性获取节点的名称
他就是提取你要提取的节点的名字
语法
1 2
| soup = BeautifulSoup(html, 'lxml') soup.要获取节点的名称.name
|
咧
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| from bs4 import BeautifulSoup html = \ """ <div id="top"> <span class="position" width="350">职位名称</span> <span>职位类别</span> <li class="item-0"> <a href="link1.html">爬虫</a> </li> </div> """
soup = BeautifulSoup(html, 'lxml')
print(soup.span.name)
|
结果
获取属性和值
attrs方法获取全部属性
语法
1 2
| soup = BeautifulSoup(html, 'lxml') print(soup.要取属性的节点名字.attrs)
|
咧
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| from bs4 import BeautifulSoup html = \ """ <div id="top"> <img src="www.xxxx./a.png" alt="你好"> <li class="item-0"> <a href="link1.html">爬虫</a> </li> </div> """
soup = BeautifulSoup(html, 'lxml')
print(soup.img.attrs)
|
结果
1
| {'src': 'www.xxxx./a.png', 'alt': '你好'}
|
attrs方法获取指定属性值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| from bs4 import BeautifulSoup html = \ """ <div id="top"> <img src="www.xxxx./a.png" alt="你好"> <li class="item-0"> <a href="link1.html">爬虫</a> </li> </div> """
soup = BeautifulSoup(html, 'lxml')
print(soup.img.attrs['src'])
|
结果
直接的方法获取指定属性值
语法
1 2
| soup = BeautifulSoup(html, 'lxml') print(soup.要取属性的节点名字['要获得的属性名'])
|
咧
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| from bs4 import BeautifulSoup html = \ """ <div id="top"> <li class="item-0"> <a href="link1.html">爬虫</a> </li> </div> """
soup = BeautifulSoup(html, 'lxml')
print(soup.img['src'])
|
结果:可以看见和上面的一样
嵌套选择
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| from bs4 import BeautifulSoup html = \ """ <div id="top"> <li class="item-0"> <a href="link1.html">爬虫</a> </li> </div> """
soup = BeautifulSoup(html, 'lxml')
print(soup.div.li.a)
|
结果
1
| <a href="link1.html">爬虫</a>
|
关联选择
| 取子节点 |
解释 |
| contents |
得到的结果是直接子节点的列表,返回的是一个列表 |
| children |
迭代器格式存储,返回的是一个迭代器 |
| descendants |
生成器格式存储,返回的是一个生成器 |
| 取父节点 |
解释 |
| parent |
取父节点,他返回的是bs4.element.Tag类型 |
| parents |
取全部父节点,他返回是的生成器类型 |
| 兄弟节点元素 |
解释 |
| next_sibling |
获得下一个兄弟节点,返回bs4 |
| previous_sibling |
获得上一个兄弟节点,返回bs4 |
| next_siblings |
获得下面的全部兄弟节点,返回生成器 |
| previous_siblings |
获得上面的全部兄弟节点,返回生成器 |
取子节点
contents列表的格式存储
contents 属性得到的结果是直接子节点的列表
属性得到的结果是直接子节点的列表
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| from bs4 import BeautifulSoup html =\ """ <div id="top"> <img src="www.xxxx./a.png" alt="你好"> <li class="item-0"> <a href="link1.html">爬虫</a> </li> </div> """
soup = BeautifulSoup(html, 'lxml') print(soup.div.contents)
|
结果
1 2 3
| ['\n', <img alt="你好" src="www.xxxx./a.png"/>, '\n', <li class="item-0"> <a href="link1.html">爬虫</a> </li>, '\n']
|
children迭代器格式存储
他返回的是一个迭代器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| from bs4 import BeautifulSoup html =\ """ <div id="top"> <span class="position" width="350">职位名称</span> <span>职位类别</span> <li class="item-0"> <a href="link1.html">爬虫</a> </li> </div> """
soup = BeautifulSoup(html, 'lxml')
print(soup.div.children)
for i in soup.div.children: print(i)
|
结果:可以看见他是迭代器类的
1 2 3 4 5 6
| <list_iterator object at 0x7fe49a745f70> <span class="position" width="350">职位名称</span> <span>职位类别</span> <li class="item-0"> <a href="link1.html">爬虫</a> </li>
|
descendants生成器格式存储
他返回的是一个生成器
descendants他和children,descendants他会单独叫数据给显示出来
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| from bs4 import BeautifulSoup html =\ """ <div id="top"> <span class="position" width="350">职位名称</span> <span>职位类别</span> <li class="item-0"> <a href="link1.html">爬虫</a> </li> </div> """
soup = BeautifulSoup(html, 'lxml')
print(soup.div.descendants)
for i in soup.div.descendants: print(i)
|
结果:可以看见他会叫单独的数据给显示出来
1 2 3 4 5 6 7 8 9
| <span class="position" width="350">职位名称</span> 职位名称 <span>职位类别</span> 职位类别 <li class="item-0"> <a href="link1.html">爬虫</a> </li> <a href="link1.html">爬虫</a> 爬虫
|
取父节点
parent取父节点
他返回的是bs4.element.Tag类型的
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| from bs4 import BeautifulSoup html =\ """ <div id="top"> <li class="item-0"> <a href="link1.html">爬虫</a> </li> </div> """
soup = BeautifulSoup(html, 'lxml')
print(soup.a.parent)
|
结果:可以看见他取了a的父标签
1 2 3
| <li class="item-0"> <a href="link1.html">爬虫</a> </li>
|
### parents取全部父节点
他返回是的生成器类型的,
如果想获取所有的祖父节点
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| from bs4 import BeautifulSoup html =\ """ <div id="top"> <li class="item-0"> <a href="link1.html">爬虫</a> </li> </div> """
soup = BeautifulSoup(html, 'lxml')
print(soup.a.parents) for i in soup.a.parents: print(i)
|
结果,可以看见结果会,逐个向父节点去获取
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| <generator object PageElement.parents at 0x7f82a6bb59e0> <li class="item-0"> <a href="link1.html">爬虫</a> </li> <div id="top"> <li class="item-0"> <a href="link1.html">爬虫</a> </li> </div> <body><div id="top"> <li class="item-0"> <a href="link1.html">爬虫</a> </li> </div> </body> <html><body><div id="top"> <li class="item-0"> <a href="link1.html">爬虫</a> </li> </div> </body></html> <html><body><div id="top"> <li class="item-0"> <a href="link1.html">爬虫</a> </li> </div> </body></html>
|
兄弟节点元素
就是获得下面这个

| 获得兄弟节点属性 |
作用 |
| next_sibling |
获得下一个兄弟节点,返回bs4 |
| previous_sibling |
获得上一个兄弟节点,返回bs4 |
| next_siblings |
获得上面的全部兄弟节点,返回生成器 |
| previous_siblings |
获得下面的全部兄弟节点,返回生成器 |
next_sibling
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| from bs4 import BeautifulSoup html =\ """ <div id="top"> 1 <span class="position" width="350">职位名称</span> 2 <span>职位类别</span> 3 <li class="item-0">abc</li> 4 <span>职位类别</span> 5 <a href="link1.html">爬虫</a> 6 </div> """
soup = BeautifulSoup(html, 'lxml')
print(soup.li.next_sibling)
|
结果
previous_sibling
获得上一个兄弟节点,返回bs4
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| from bs4 import BeautifulSoup html =\ """ <div id="top"> 1 <span class="position" width="350">职位名称</span> 2 <span>职位类别</span> 3 <li class="item-0">abc</li> 4 <span>职位类别</span> 5 <a href="link1.html">爬虫</a> 6 </div> """
soup = BeautifulSoup(html, 'lxml')
print(soup.li.previous_sibling)
|
结果
next_siblings
获得下面的全部兄弟节点,返回生成器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| from bs4 import BeautifulSoup html =\ """ <div id="top"> 1 <span class="position" width="350">职位名称</span> 2 <span>职位类别1</span> 3 <li class="item-0">abc</li> 4 <span>职位类别2</span> 5 <a href="link1.html">爬虫</a> 6 </div> """
soup = BeautifulSoup(html, 'lxml')
print(list(soup.li.next_siblings))
|
结果
1
| ['\n 4\n ', <span>职位类别1</span>, '\n 5\n ', <a href="link1.html">爬虫</a>, '\n 6\n']
|
previous_siblings
获得上面的全部兄弟节点,返回生成器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| from bs4 import BeautifulSoup html =\ """ <div id="top"> 1 <span class="position" width="350">职位名称</span> 2 <span>职位类别1</span> 3 <li class="item-0">abc</li> 4 <span>职位类别2</span> 5 <a href="link1.html">爬虫</a> 6 </div> """
soup = BeautifulSoup(html, 'lxml')
print(list(soup.li.previous_siblings))
|
结果
1
| ['\n 3\n ', <span>职位类别1</span>, '\n 2\n ', <span class="position" width="350">职位名称</span>, '\n 1\n ']
|
提取信息
其实其实用到的但是上面用过的内容
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| from bs4 import BeautifulSoup html =\ """ <div id="top"> <img src="www.xxxx./a.png" alt="你好"> <li class="item-0"> <a href="link1.html">爬虫</a> </li> </div> """
soup = BeautifulSoup(html, 'lxml') print(soup.a.string) print(soup.a.attrs['href'])
|
结果
方法选择器
前面都是通过属性来过滤的,如果遇见复杂的情况可以用下面这个方法进行过滤
find_all()
获取全部指定的标签
用到的参数是name,他返回是s4.element.ResultSet类型
格式
1
| xxxx.find_all(name="要获取的标签的名字")
|
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| from bs4 import BeautifulSoup html =\ """ <div> <ul> <li class="item-0"> <a href="link1.html">first item</a> </li> <li class="item-1"> </li> second item <li class="item-inactive"> <a href="link3.html">third item</a> </li>
</ul> </div> """
soup = BeautifulSoup(html, 'lxml')
print(type(soup.find_all(name="a"))) print(soup.find_all(name="a"))
|
结果
1 2
| <class 'bs4.element.ResultSet'> [<a href="link1.html">first item</a>, <a href="link3.html">third item</a>]
|
查询属性
用attrs参数
他类型是字典类型,返回是bs4.element.ResultSet
格式
1
| xxxx.find_all(attrs={'id': 'list-1'})
|
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| from bs4 import BeautifulSoup html =\ """ <div> <ul> <li class="item-0"> <a href="link1.html">first item</a> </li> <li class="item-1"> </li> second item <li class="item-inactive"> <a href="link3.html">third item</a> </li>
</ul> </div> """
soup = BeautifulSoup(html, 'lxml')
print(type(soup.find_all(name="a",attrs={"href":"link1.html"}))) print(soup.find_all(name="a",attrs={"href":"link1.html"}))
|
结果
1 2
| <class 'bs4.element.ResultSet'> [<a href="link1.html">first item</a>]
|
不用参数
我们可以不用带参数,直接就href="link1.html"来过滤属性,可以叫属性值当参数用
格式
1
| xxxx.find_all(href="link1.html")
|
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| from bs4 import BeautifulSoup html =\ """ <div> <ul> <li class="item-0"> <a href="link1.html">first item</a> </li> <li class="item-1"> </li> second item <li class="item-inactive"> <a href="link3.html">third item</a> </li>
</ul> </div> """
soup = BeautifulSoup(html, 'lxml')
print(type(soup.find_all(name="a",href="link1.html"))) print(soup.find_all(name="a",href="link1.html"))
|
结果
1 2
| <class 'bs4.element.ResultSet'> [<a href="link1.html">first item</a>]
|
text 参数
text 参数可以搜索内容,text 参数接受 字符串 , 正则表达式 , 列表, True
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| import re html=''' <div class="panel"> <div class="panel-body"> <a>a</a> <a>b</a> </div> <a>1</a> <a>2</a> <div class="panel-body"> <a>c</a> <a>d</a> </div> </div> ''' from bs4 import BeautifulSoup soup = BeautifulSoup(html, 'lxml') print(soup.find_all(text="a")) print(soup.find_all(text=["a","c"])) print(soup.find_all(text=re.compile("\d")))
|
结果
1 2 3
| ['a'] ['a', 'c'] ['1', '2']
|
find()方法
除了 find_all() 方法,还有 find() 方法,只不过后者返回的是单个元素,也就是第一个匹配的元素,而前者返回的是所有匹配的元素组成的列表
CSS 选择器