最近不知道为什么很想看电影,但又不知道什么电影好看,就想去豆瓣找找,之前学了一点简单的爬虫,刚好可以用来练练手。内容比较长,可以边听音乐边看,嘻嘻~
废话不多说,咱们直接进入主题。
确定目标
这次我想爬取top250的所有电影,内容包括 影名,链接,类型,评分和推荐语,爬取网址为https://movie.douban.com/top250。
寻找目标
按快捷方式f12可以打开网页源代码,也可以右键->检查,效果是一样的。
按ctrl+shift+c,然后再用鼠标移到左侧里的任意一个影名,我们可以看到右侧会跳出影名在网页源代码中的所在节点。
可以再尝试下将鼠标移到其他我们将要获取的内容信息,同样能找它们的所在节点。
细心点,你会发现我们想要的内容都在一个标签为div并且class属性为“info”的节点内。
那我们再找找其他的电影,看看这个信息是不是一样的。结果非常nice~跟我们预想的一样,这对我们获取数据就更加方便了。只要获取所有的div标签并且class属性为info的节点内容,然后再对里面的信息进行提取就OK了,最后再把信息存储在csv文件里,我们就大功告成啦,好开心~
获取数据
现在开始上代码。
首先我们先导入需要用的一些库--requests,bs4和csv。我是使用Anadanca,所以这些库都不需要自己安装。
from bs4 import BeautifulSoup
import csv,requests
然后我们创建一个爬虫函数spider()用来爬取数据。在函数里面使用requests模块的get属性来下载top250的网页源代码。
def spider():
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36"}
url = "https://movie.douban.com/top250?start=0&filter=" #第一页网址
req = requests.get(url,headers=headers)#添加请求头headers伪装自己是浏览器
html = req.text #将获取到的网页源代码转换为文本
用bs4库里的BeautifulSoup模块对获取到的网页进行解析,解析之后会返回上面看到的html代码,不然我们就无法获取我们想要的数据。
这里我用的解析库是html.parser,也可以用lxml进行解析,大家可以去了解一下。
soup = BeautifulSoup(html,"html.parser")
接下来就是找到并获取div.info(" . "相当于class属性)节点里的内容。我们用soup的find_all方法获取所有的div.info节点。
tag= soup.find_all("div",class_="info")
返回的是tag对象列表(tag对象可以理解为标签对象),之后对该列表进行遍历,这样我们就可以对每个div.info节点里面的内容进行处理了。
tag= soup.find_all("div",class_="info")
for tag_one in tag:
tag_hd=tag_one.find("div",class_="hd")
name=tag_hd.find("span",class_="title").text #电影名
url=tag_hd.find("a")["href"] #链接
tag_bd=tag_one.find("div",class_="bd")
style=tag_bd.find("p").text #类型
style=style.split("/")
style=style[-1] #去除一些不需要的数据
tag_p=tag_one.find("div",class_="star")
rating=tag_p.find("span",class_="rating_num").text #评分
try:
qoute=tag_one.find("span",class_="inq") .text #推荐语
except:
qoute="无"
为了防止多个div里面有相同的标签,提取到一些我们不需要的数据。我们用find方法先找到只包含影名和url的div.hd节点,然后再用tag[属性名]的方式提取标签a里面属性href的值,该值就是我们需要获得的链接。用tag.text的方式获取标签包含的文本信息,也就是影名。获取其他信息的操作和这个是一样的,这里我就不在详细写出。
这里要注意的是,有些电影是没有推荐语的,为了防止报错,这里用try...except...来处理异常。
将结果打印出来你会发现只有25部电影,这是为什么呢?原因是刚才我们输入的网址是第一页的网址哦~我们跳到第二页看看它的网址有没有发生什么变化
网址变成了“https://movie.douban.com/top250?start=25&filter=”,跳到第三页,又变成了“https://movie.douban.com/top250?start=50&filter=”。
大家尝试打开第四、五页观察一下,看下有没有什么规律,总共有10页。
最后我们会发现只有start=的值在发生改变,每翻一页,数值就增加了25,细心点,你会发现这就是每页电影的数量。
现在我们知道了规律,那我们就要对url处理一下。处理完后代码是这样的:
url_list=[f"https://movie.douban.com/top250?start={i*25}&filter=" for i in range(10)]
for url in url_list:
req = requests.get(url,headers=headers)
soup = BeautifulSoup(req.text,"html.parser")
tag= soup.find_all("div",class_="info")
for tag_one in tag:
tag_hd=tag_one.find("div",class_="hd")
name=tag_hd.find("span",class_="title").text #电影名
url=tag_hd.find("a")["href"] #链接
tag_bd=tag_one.find("div",class_="bd")
style=tag_bd.find("p").text #类型
style=style.split("/")
style=style[-1]
tag_p=tag_one.find("div",class_="star")
rating=tag_p.find("span",class_="rating_num").text #评分
try:
qoute=tag_one.find("span",class_="inq") .text #推荐语
except:
qoute="无"
存储数据
恭喜你,已经完成了获取数据的过程,接下来就是将数据进行存储,我们这里是用csv格式进行存储。直接上代码:
with open("top250.csv","w",encoding = "utf-8") as csvfile: #如果内容含有中文的话,最好加上编码格式,不然容易出现乱码
writer = csv.writer(csvfile)
writer.writerow(["电影名","链接","类型","评分","推荐语"]) #以列表的形式写入字段信息
url_list=[f"https://movie.douban.com/top250?start={i*25}&filter=" for i in range(10)]
for url in url_list:
req = requests.get(url,headers=headers)
soup = BeautifulSoup(req.text,"html.parser")
tag= soup.find_all("div",class_="info")
for tag_one in tag:
tag_hd=tag_one.find("div",class_="hd")
name=tag_hd.find("span",class_="title").text #电影名
url=tag_hd.find("a")["href"] #链接
tag_bd=tag_one.find("div",class_="bd")
style=tag_bd.find("p").text #类型
style=style.split("/")
style=style[-1]
tag_p=tag_one.find("div",class_="star")
rating=tag_p.find("span",class_="rating_num").text #评分
try:
qoute=tag_one.find("span",class_="inq") .text #推荐语
except:
qoute="无"
writer.writerow([name,url,style,rating,qoute])
print("已下载完成")
这里要注意的是
with open("top250.csv","w",encoding = "utf-8") as csvfile:
writer = csv.writer(csvfile)
writer.writerow(["电影名","链接","类型","评分","推荐语"])
url_list=[f"https://movie.douban.com/top250?start={i*25}&filter=" for i in range(10)]
这一部分一定要放在for循环外,不然只能得到最后25部电影的信息。最后执行函数,大功告成。250部电影!!够我看的吐,哈哈~
if "__name__"=="__main__": #判断当前函数是否是主程序
spider()
效果图
脑洞大开
其实这只是简单的获取数据,我们还可以对这些数据进行更加有趣的处理,比如再加一些代码,实现运行程序时,随机出现三部电影让你选择,如果有看中的,就获取影名并退出程序,否则再次随机,直到你满意为止。
或者你还可以根据电影类型分类保存,然后在自己喜欢的类型里面进行随机抽选,这也是可以的。
或者获取某个电影的影评,然后做个词云,看看他们都在讨论什么内容。
其实还可以很多玩法,思维放开点,生活会变得更有趣~
希望大家看完后把自己的想法发到后台,我再分享给大家,一起学习呀~