上节我们讲到requests只是获取了网页数据,我们需要进一步,获取我们需要的并且能看懂的数据,这里需要用到新的库BeautifulSoup,他是一个HTML/XML的解析器,主要的功能是如何解析和提取 HTML/XML 数据。
pip install beautifulsoup4
BeautifulSoup可以很方便的从网页中抓取我们需要的数据,我们先来导入一下BeautifulSoup
from bs4 import BeautifulSoup #从bs4中导入BeautifulSoup
bs = BeautifulSoup(res.text , 'html.parser')
我们在创建BeautifulSoup
对象时需要传入两个参数,一个参数是需要被解析的html文本(<html>...</html>)
,也就是网站的源代码(res.text
)。另一个参数是html
的解析器:html.parser
,它是 Python 中内置的解析器,它的特点就是简单方便。
接下来我们接上上一节的内容来继续写代码。
import requests #导入requests库
from bs4 import BeautifulSoup #从bs4中导入BeautifulSoup
headers = { #将用户代理数据放入请求头当中,伪装成浏览器
"User-Agent":"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.162 Safari/537.36"
}
url ="https://book.douban.com/top250" #将url地址存入变量中
res = requests.get(url, headers = headers) #获取响应数据存入变量res
bs = BeautifulSoup(res.text , 'html.parser') #创建BeautifulSoup对象
接下来,我们来学习BeautifulSoup
的常用方法:find()
方法和find_all()
方法
find()
方法:用于返回符合查找条件的第一个数据find_all()
方法:用于返回符合查找条件的全部数据假如有这样一个百度页面,我们使用两种方法分别获得数据
<div class="content">
<h1>这是一个示例</h1>
<div class="">
<a href="https://www.baidu.com">百度首页</a>
<div class="item">
<a href="https://www.baidu.com/image">百度图片</a>
</div>
<div class="item">
<a href="https://www.baidu.com/map">百度地图</a>
</div>
<div class="item">
<a href="https://www.baidu.com/tieba">百度贴吧</a>
</div>
</div>
</div>
bs = BeautifulSoup(res.text, 'html.parser')
print(bs.find('a'))
# 输出:<a href="https://www.baidu.com">百度首页</a>
print(bs.find_all('a'))
# 输出:[
<a href="https://www.baidu.com">百度首页</a>,
<a href="https://www.baidu.com/image">百度图片</a>,
<a href="https://www.baidu.com/map">百度地图</a>,
<a href="https://www.baidu.com/tieba">百度贴吧</a>
]
从上面对比可以看出,find()
输出了第一个<a>标签
,而find_all()
则输出了由所有<a>标签
组成的列表
除了直接传入标签名
作为参数之外,这两个方法还支持传入标签的属性
,进行数据的提取,我们再来看个示例:
我们想要提取书本名字,可以这样写
打开豆瓣top250页面,右键选择书本名称,点击检查
#查找属性为class = 'pl2' 的 div 标签
items = bs.find('div' , class_ = 'pl2')
#输出:
<div class="pl2">
<a href="https://book.douban.com/subject/1007305/" onclick=""moreurl(this,{i:'0'})"" title="红楼梦">红楼梦
</a></div>
#查找所有属性为class = 'pl2' 的 div 标签
items = bs.find_all('div' , class_ = 'pl2')
因为在python语言中,class
被用来定义类
,所以我们在查找html标签里
用到的class 需要加一个下划线:class_
BeautifulSoup
把html
中的标签封装为Tag
对象,和BeautifulSoup对象
一样,Tag对象
也有find()
和find_all()
方法。
我们需要的内容在<a>
标签里面,那我们可以这样来写:
#查找所有属性为class = 'pl2' 的 div 标签
items = bs.find_all('div' , class_ = 'pl2')
for i in items:
# 查找 class_='pl2' 的 div 标签中的 a 标签
print(i.find('a'))
但是我们其实只想要书名和链接而已,其他我们都不需要,那么我们再来改写一下:
#查找所有属性为class = 'pl2' 的 div 标签
items = bs.find_all('div' , class_ = 'pl2')
for i in items:
#查找 class_='pl2' 的 div 标签中的 a 标签
tag = i.find('a')
#获取a标签的文本内容用tag.text,但是这里还可以这样写:获取a标签的title属性的值
name = tag['title']
#获取a标签的href属性的值
link = tag['href']
#字符串格式化,使用\n换行
print('书名:{}\n链接:{}' .format(name , link))
输出结果
从上面的例子可以看到,我们通过和字典取值
类似的方式,将html属性名
作为键
,得到了对应属性的值
,这里是以title
属性为例,其他的html属性也同样适用。(tag.text用来获取标签文本内容,tag['属性名']用于获取标签属性的值)
接下来,咱们用同样的方法获取书本作者和出版社等信息:
#查找所有属性为class = 'pl' 的 p 标签
authors = bs.find_all('p' , class_ = 'pl')
for j in authors:
print(j.text)
输出结果
接下来,咱们用同样的方法获取一句话介绍:
#查找所有属性为class = 'pl' 的 p 标签
abstract = bs.find_all('span' , class_ = 'inq')
for k in abstract:
print(k.text)
输出结果
虽然我们把需要的信息全都抓取了出来,但是代码好像不够简洁,那我们是否可以再优化一下呢?
答案当然是可以的。