上回我们讲解了 Beautiful Soup 的基本使用方法,这次就带大家使用 Beautiful Soup 进行实战。这次要抓取的目标是豆瓣电影 TOP250,解析出其中的电源名称、评分、简单评价、评价人数等信息,其 base_url 是 https://movie.douban.com/top250。
其实简单的网络爬虫无外乎查看网页源码,从源码中获取自己想要的东西,然后对其进行处理。
1 解析 - 获取目标元素
我们首先按下 F12
看下目标远视眼的 HTML 源码:
通过查看页面元素代码可以看出:
- 电影条目是被
<ol class="grid_view">
所包围的; - 其中每个电影条目是一个
<li>
; - 另外,每页有 25 个条目,共 10 页,这意味着需要解析多页数据。
再来看下其中一个条目的源码:
<li>
<div class="item">
<div class="pic">
<em class="">1</em>
<a href="https://movie.douban.com/subject/1292052/">
<img width="100" alt="肖申克的救赎" src="https://img3.doubanio.com/view/photo/s_ratio_poster/public/p480747492.webp" class=""></a>
</div>
<div class="info">
<div class="hd">
<a href="https://movie.douban.com/subject/1292052/" class="">
<span class="title">肖申克的救赎</span>
<span class="title"> / The Shawshank Redemption</span>
<span class="other"> / 月黑高飞(港) / 刺激1995(台)</span></a>
<span class="playable">[可播放]</span></div>
<div class="bd">
<p class="">导演: 弗兰克·德拉邦特 Frank Darabont 主演: 蒂姆·罗宾斯 Tim Robbins /...
<br>1994 / 美国 / 犯罪 剧情</p>
<div class="star">
<span class="rating5-t"></span>
<span class="rating_num" property="v:average">9.6</span>
<span property="v:best" content="10.0"></span>
<span>1041580人评价</span></div>
<p class="quote">
<span class="inq">希望让人自由。</span></p>
<p>
<span class="gact">
<a href="https://movie.douban.com/wish/50494322/update?add=1292052" target="_blank" class="j a_collect_btn" name="sbtn-1292052-wish" rel="nofollow">想看</a></span> </p>
</div>
</div>
</div>
</li>
对于每个条目,我们需要解析出其中的 电影名称、评分、评价人数,及一句话点评。
1.1 标题、评分、评价解析
标题是在 <span class="title">肖申克的救赎</span>
里的,我们可以结合上回的 Beautiful Soup 来获取:
title = soup.find("span", attrs={"class": "title"}).getText()
在 HTML 源码里,发现有多个标题:<span class="title">
,这里我们就只获取第一个,其他的不关心。
评分和评价的解析和标题类似,用同一种解析方法解析即可。
# 评分
rating_num = soup.find("span", attrs={"class": "rating_num"}).getText()
# 评价
inq = soup.find("span", attrs={"class": "inq"}).getText()
1.2 评价人数解析
评价人数这里是这样的: <span>1041580人评价</span>
,明显跟上面的不同,它没有 class 属性,这里只能通过 text 来查找了:
find(text=re.compile('人评价$'))
这里用了正则表达式来进行匹配,即匹配以 人评价
结尾的文本。
或者你有什么其他好的方法,也可以留言交流。
1.3 下一页解析
<span class="next">
<link rel="next" href="?start=25&filter="/>
<a href="?start=25&filter=" >后页></a>
</span>
对照代码,需要从中解析出下一页的连接 ?start=25&filter=
。
解析方法类似于标题的解析,先解析出 <span class="next">
,然后解析其中的 <a>
标签。
next_page = soup.find("span", attrs={"class":"next"}).find("a")
要解析的东西基本上就是这些,最后需要将解析结果整合保存到文本文件中。
2 实现代码
# encoding:utf-8
import requests, re
from bs4 import BeautifulSoup
def download_page(url):
response = requests.get(url)
soup = BeautifulSoup(response.text, "lxml")
return soup
def parse_soup(soup):
return_list = []
# 利用 class 属性找到 grid
grid = soup.find("ol", attrs={"class": "grid_view"})
# 不加 attrs= 也可以
# grid = soup.find("ol", {"class": "grid_view"})
if grid:
# 利用标签获取 list
movie_list = grid.find_all("li")
# 遍历 list
for movie in movie_list:
# 一个电影有多个名字,这里只取第一个
title = movie.find("span", attrs={"class": "title"}).getText()
rating_num = movie.find("span", attrs={"class": "rating_num"}).getText()
inq = movie.find("span", attrs={"class": "inq"})
# 利用 text 配合正则表达式匹配搜索文本
rating_p = soup.find(text=re.compile('人评价$'))
# 有些暂时没有一句话评论
if not inq:
inq = "暂无"
else:
inq = inq.getText()
return_list.append(title + "," + rating_p + ",评分:" + rating_num + ",一句话评价:" + inq)
next_page = soup.find("span", attrs={"class":"next"}).find("a")
if next_page:
return return_list, next_page["href"]
else:
return return_list, None
if __name__ == "__main__":
url = "https://movie.douban.com/top250"
next_url = ""
# 将结果保存到文件
with open("doubanMoviesTop250.txt","w+") as f:
while next_url or next_url == "":
soup = download_page(url + next_url)
movie_list, next_url = parse_soup(soup)
# 将 list 拆分成不同行
f.write("\n".join(movie_list))
3 运行结果
$ cat doubanMoviesTop250.txt
肖申克的救赎,1041580人评价,评分:9.6,一句话评价:希望让人自由。
霸王别姬,1041580人评价,评分:9.5,一句话评价:风华绝代。
这个杀手不太冷,1041580人评价,评分:9.4,一句话评价:怪蜀黍和小萝莉不得不说的故事。
阿甘正传,1041580人评价,评分:9.4,一句话评价:一部美国近现代史。
美丽人生,1041580人评价,评分:9.5,一句话评价:最美的谎言。
千与千寻,1041580人评价,评分:9.3,一句话评价:最好的宫崎骏,最好的久石让。
泰坦尼克号,1041580人评价,评分:9.3,一句话评价:失去的才是永恒的。
辛德勒的名单,1041580人评价,评分:9.4,一句话评价:拯救一个人,就是拯救整个世界。
...
篇幅有限,这里未展示全部。
4 总结
本文中举得例子虽然简单,但是「麻雀虽小五脏俱全」,涉及到了 Beautiful Soup 的各个方法以及文件的读写。网站的爬虫基本流程答题如此,其他要解决的就是用户认证、反爬的应对等问题,后续再一一讲解。
如果觉得有用,欢迎关注我的微信,有问题可以直接交流,另外提供精品 Python 资料!