Beautiful Soup是Python的一个网页解析库,处理快捷; 支持多种解析器,功能强大。教程细致讲解Beautiful Soup的深入使用、节点选择器、CSS选择器、Beautiful Soup4的方法选择器等重要知识点,是学好爬虫的基础课程。
1. 了解Beautiful Soup的方法选择器
前面所讲的选择方法都是通过标签和属性来选择的,这种方法非常快,但是如果在比较复杂的页面中选择元素,无法精准的定位到元素。
比如:
<a href="http://example.com/elsie" class="sister" id="link1">Elsie</a>,
<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>;
在HTML文档中存在多个<a>
标签,我们无法使用节点选择器精准的定位到第二、第三个<a>
标签。所以我们在这里学习findall()
和find()
方法,通过传入参数的方法,来进行精准的定位。
前置代码
html = '''
<div class="panel">
<div class="panel-heading">
<h4>Hello</h4>
</div>
<div class="panel-body">
<ul class="list" id="list-1">
<li class="element"> Foo</li>
<li class="element">Bar</li>
<li class="element">]ay</li>
</ul>
<ul class="list list-small" id="list-2">
<li class="element"> Foo</li>
<li class="element">Bar</li>
</ul>
</div>
</div>
'''
from bs4 import BeautifulSoup
soup = BeautifulSoup(html, 'lxml')
2.方法选择器之 find_all() 方法
学习目标
- 掌握find_all()方法中的参数的用法
2.1 作用及范围:
- 作用:用于搜索当前节点的所有符合条件的节点
- 范围:当前节点下的所有节点,如果没有指定当前节点,则进行全文的搜索
1.2 用法介绍:
find_all(name, attrs, recursive, text, **kwargs)
(1.) name参数
如图所示,name
参数的作用是用来查找所有名字为名字的节点(tag对象)。在使用的时候,可以接收字符串、正则表达式、列表、布尔值。
参数形式:字符串
传入一个字符串参数,即标签名(tag),Beautiful Soup会查找与字符串内容完全匹配的内容
# 寻找所有span标签
print(soup.find_all('span'))
# 输出结果
[<span>Elsie</span>]
参数形式:正则表达式
传入正则表达式,Beautiful Soup会通过正则表达式的match()
函数来匹配内容
# 使用正则匹配以b开头的标签
import re
for tag in soup.find_all(re.compile('^b')):
print(tag.name)
# 输出结果
body
参数形式:列表
传入列表参数,Beautiful Soup会将与列表中任一元素匹配,并返回结果。
# 使用列表选择包含a和span的所有标签
print(soup.find_all(['a', 'span']))
# 输出结果
[<a class="sister" href="http://example.com/elsie" id="link1"><span>Elsie</span></a>, <span>Elsie</span>, <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>, <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]
参数形式:布尔值True
True可以匹配任何值
# 使用True选择文件中所有标签
for tag in soup.find_all(True):
print(tag.name)
# 输出结果
html
head
title
body
p
a
span
a
a
p
(2.) attrs参数
- 作用:查询含有接受的属性值的标签
- 参数形式:字典类型
# 获取id为link1的标签 print(soup.find_all(attrs={ id: 'link1'})) # 输出结果 [<a class="sister" href="http://example.com/elsie" id="link1"><span>Elsie</span></a>]
(3.) kwargs参数
-
作用:接收常用的属性参数,如
id
和class
-
参数形式:变量赋值的形式
# 获取id为link1的标签 print(soup.find_all(id='link1')) # 输出结果 [<a class="sister" href="http://example.com/elsie" id="link1"><span>Elsie</span></a>]
这里直接传入id=‘link1’,就查询到id为’link1’的节点元素了。而对于class来说,它在Python中是一个关键字,需要加一个下划线,即class_=‘element’。
# 获取id为link1的标签 print(soup.find_all(class_='story')) # 输出结果 [<p class="story">Once upon a time there were three little sisters; and their names were <a class="sister" href="http://example.com/elsie" id="link1"><span>Elsie</span></a>, <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a> and <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>; and they lived at the bottom of a well.</p>, <p class="story">...</p>]
(4.) text参数
- 作用:查询含有接收的文本的标签
- 参数形式:字符串
- 通过搜索文档中的字符串内容,来确定文件标签。
# 获取文本中包含Elsie内容 print(soup.find_all(text='Elsie')) # 输出结果 ['Elsie']
虽然text参数用于搜索字符串,还可以与其他参数混合使用来过滤tag
# 获取文本中包含Elsie内容的标签 print(soup.find_all('a', text='Elsie')) # 输出结果 [<a class="sister" href="http://example.com/elsie" id="link1"><span>Elsie</span></a>]
(5.) limit参数
- 作用:用于限制返回结果的数量
- 参数形式:整数
# 获取前两个a标签 print(soup.find_all('a', limit=2)) # 输出结果 [<a class="sister" href="http://example.com/elsie" id="link1"><span>Elsie</span></a>, <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>]
(6.) recursive参数
- 作用:决定是否获取子孙节点
- 参数形式:布尔值,默认是True
print(soup.find_all('title')) print(soup.find_all('title', recursive=False)) # 输出结果 [<title>The Dormouse's story</title>] []
3. 方法选择器之find()方法
find()
方法和find_all()
方法类似,作用都是在文档中查找需要的信息
区别点在于:
find_all()
方法返回所有符合条件的元素列表,而find()
方法就是返回符合条件的第一个元素- 除了
limit
参数不能在find()
方法中使用,find()
方法的其他参数和find_all()
的参数用法一样
find()
方法
- 作用:查找当前节点下,符合条件的一个元素节点
- 范围:当前节点下的一个元素
(1.) name参数
# 获取a标签
print(soup.find('a'))
# 输出结果
<a class="sister" href="http://example.com/elsie" id="link1"><span>Elsie</span></a>
(2.) attrs参数
# 获取class等于sister的标签
print(soup.find(attrs={
'class': 'sister'}))
# 输出结果
<a class="sister" href="http://example.com/elsie" id="link1"><span>Elsie</span></a>
(3.) kwargs参数
- 作用:接收常用的属性参数,如
id
和class
- 参数形式:变量赋值的形式
# 获取class等于sister的标签
print(soup.find(class_='sister'))
# 输出结果
<a class="sister" href="http://example.com/elsie" id="link1"><span>Elsie</span></a>
(4.) text参数
- 作用:查询含有接收的文本的标签
- 参数形式:字符串
- 通过搜索文档中的字符串内容,来确定文件标签。
# 获取文本中包含story的标签
print(soup.find(text=re.compile('.*?story')))
# 输出结果
The Dormouse's story
(5.) recursive参数
- 作用:决定是否获取子孙节点
- 参数形式:布尔值,默认是True
# 获取文本中包含story的标签
print(soup.find('a', recursive=False)
# 输出结果
None
4. 其他的方法介绍
在Beautiful Soup中还存在其他的方法,根据自己的业务需求使用就行可以。参数的用法相同,唯一的区别点在于搜索的范围。
5. 总结
find_all()方法的使用
- name参数用来接收tag名称,有四种形式:字符串,正则,列表和True
- attrs参数用来接收属性的键值对字典
- kwargs参数用来接收常用属性的变量赋值的形式 例如:
id='link1'
,class_="sister"
- text参数用来接收文本信息
- limit参数用来限制返回结果的数量
- recursive参数用来决定是否获取子孙节点
查询范围
find()
方法:
- 查找当前节点下,符合条件的第一个节点
find_all()
方法:
- 查找点前节点下,符合条件的所有节点
可供使用的参数
find()
方法:
name
,attrs
,text
,kwargs
,recursive
find_all()
方法:
name
,attrs
,text
,kwargs
,recursive
,limit
在大多数的情况下,find()
方法配合find_all()
方法就已经能够满足工作需求,如果遇到特殊情况,需要查询特殊的范围,可以使用Beautiful Soup的其他方法。