之前抓取豆瓣图书Top250的时候,获取内容使用的方法是正则表达式匹配,看上去是一种比较简洁的方法,但问题在于,正则表达式的编写必须非常细心,一旦出了任何小问题,就会导致得不到想要的结果。熟悉html的话,不难想到可以利用节点之间的结构和层级关系来作区分并进一步获取节点内想要的文本。
于是BeautifulSoup库为我们实现了这种更加直接的匹配方法,BeautifulSoup是一个python的HTML或XML解析库,可以方便地从页面中提取数据,它自动的将输入的文档转换为Unicode编码,输出文档转换为UTF-8编码,不需要考虑编码方式。
BeautifulSoup在工作时,其实是依赖于解析器来解析文本的,除开python标准库中的解析库外,我们一般使用lxml这个库来实现解析。
下面以豆瓣电影为实例介绍其用法:
为了例子的简洁,这里我们只抓取豆瓣电影排名的首页信息,其url为"https://movie.douban.com/top250",我们先使用requests库获取页面信息,代码如下:
url="https://movie.douban.com/top250"
headers={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36'}
r=requests.get(url,headers=headers).text
在文本总查看包含我们需要获取信息的那部分html代码,这里我们获取信息包括电影名称,简介,评分以及评价,抓取的html代码如下:
<div class="item">
<div class="pic">
<em class="">4em>
<a href="https://movie.douban.com/subject/1292720/">
<img width="100" alt="阿甘正传" src="https://img1.doubanio.com/view/photo/s_ratio_poster/public/p510876377.jpg" class="">
a>
div>
<div class="info">
<div class="hd">
<a href="https://movie.douban.com/subject/1292720/" class="">
<span class="title">阿甘正传span>
<span class="title"> / Forrest Gumpspan>
<span class="other"> / 福雷斯特·冈普span>
a>
<span class="playable">[可播放]span>
div>
<div class="bd">
<p class="">
导演: Robert Zemeckis 主演: Tom Hanks / Robin Wright Penn / Gary Sinise<br>
1994 / 美国 / 剧情 爱情
p>
<div class="star">
<span class="rating45-t">span>
<span class="rating_num" property="v:average">9.4span>
<span property="v:best" content="10.0">span>
<span>948433人评价span>
div>
<p class="quote">
<span class="inq">一部美国近现代史。span>
p>
div>
div>
div>
li>
<li>
分析发现,所有要抓取的信息都在标签
alla=soup.find_all('div',class_='item')
这里我们就得到了
<span class="title">阿甘正传span>
这个的获取就很容易,就是在标签内的文本,抓取代码如下:
for allo in alla:
#name=allo.find('img').get('alt')
name=allo.find('span',class_="title").get_text()
剩下的简介以及评分和name获取方法相同,代码为:
for allo in alla:
#name=allo.find('img').get('alt')
name=allo.find('span',class_="title").get_text()
infor=allo.find('p',class_="").get_text().strip()
#print(infor)
score=allo.find('span',class_="rating_num").get_text()
#print(score)
address=allo.find('img').get('src')
#print(address)
con=allo.find('span', class_="inq").get_text()
#print(con)
这样我们就获取全部所需要的信息。但其实有一个比较不一样的标签信息我们没有提取,就是影片对应的图片,它的html代码为:
<img width="100" alt="阿甘正传" src="https://img1.doubanio.com/view/photo/s_ratio_poster/public/p510876377.jpg" class="">
我们发现之前的办法不能使用了,我们要获取的是img标签下src后面的内容,型号BeutifulSoup提供了get()方法,可以提取标签内其他属性的文本信息,代码为:
pic=allo.find('img').get('src')
这里我们还是先找到对应的img标签,然后利用get()方法来获取"src"对应的文本内容。
这样内容获取大功告成,最后我们将它们保存到文本中,代码如下:
with open ('doubanfilm250.txt','a',encoding='utf-8')as f:
f.write('\n'.join([name,infor,score,con]))
f.write('\n'+'*'*50+'\n')