整体思路:利用requests,BeautifulSoup爬虫豆瓣电影分类排行榜数据;数据输出到本地csv文件;构建mongodb数据库,将数据存放入mongodb;利用pandas,matplotlib画图分析数据。
1.利用BeautifulSoup爬虫豆瓣电影分类排行榜数据
第一步:分析url规律,不同的电影分类对应url循环代入requests和BeautifulSoup中解析,再分析解析到的网站结构,提取想要的信息
获取电影分类的网页,传入函数douban中
![](https://img-blog.csdnimg.cn/20210709160034536.png)
分析网站结构,提取信息,并存放到对应的列表中
![](https://img-blog.csdnimg.cn/20210709160346225.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2JleW9uZF9MWUM=,size_16,color_FFFFFF,t_70)
**这里踩了一个坑是for循环的范围,后来通过print S2列表发现长度不一,所以这里改成了range(len(s2))严谨一点(ip被封过一次,所以这里在请求头后面还加上了代理ip)
![](https://img-blog.csdnimg.cn/20210709171048799.png)
**由于电影类别不止一个,这里想把它们都放到dataframe中的同一列,所以用了.join合并。
2.数据输出到本地csv文件
![](https://img-blog.csdnimg.cn/20210709160807348.png)
3.文件保存mongodb数据库
![](https://img-blog.csdnimg.cn/20210709161006714.png)
4.画图数据分析
![](https://img-blog.csdnimg.cn/20210709161149930.png)
**这里由于某些电影是多个国家共同出品,国家这个列表的元素中可能还嵌入了列表,导致报错:列表类型不可哈希,为了程序简练一点,这里我直接取了电影国家的第一个元素,由于plot函数的x,y的维度需要一致,在x轴国家那里构造了集合与列表的嵌套样式。
调试最久的地方是在mean()函数那里,由于评分之前没有定义字符类型,导致评分的‘9.7’等元素的类型为‘str’,非数字类型,describe()函数中没有平均值属性
源代码如下
python源代码
import requests
from bs4 import BeautifulSoup
import json
import pandas as pd
import pymongo
import matplotlib.pyplot as plt
title_list=[]
lianjie_list=[]
rank_list=[]
leibie_list=[]
s2_list=[]
pingfen_list=[]
didian_list=[]
actors_list=[]
sum=0
#解析网页
headers={'User-Agent':'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36 Edg/90.0.818.66'}
def douban(urls):#针对不同分类不同链接,创建爬虫函数
response=requests.get(urls,headers=headers,proxies={'http':'http://47.100.207.26:8080'})#获取网页
soup=BeautifulSoup(response.text,'lxml')#解析网页
s=soup.get_text()#去除网页标签,s为字符串格式,所以用json.loads变成python对象中的list
s2=json.loads(s)#格式化,字符串格式变成集合格式list,方便提取数据
s2_list.append(len(s2))
for j in range(len(s2)):#循环处理集合元素中的信息
s3=s2[j]#提取集合的第i个元素,此集合中的元素本质为字典
title=s3.get('title')#提取电影题目
title_list.append(title)
rank=int(s3.get('rank'))#提取电影排名
rank_list.append(rank)
lianjie=s3.get('url')#提取电影链接
lianjie_list.append(lianjie)
leibie=s3.get('types')#提取电影类型
leibie=''.join(leibie)
leibie_list.append(leibie)
pingfen=float(s3.get('rating')[0])#提取电影评分
pingfen_list.append(pingfen)
didian=s3.get('regions')[0]#提取电影国家,有的电影存在多个制作地点,为了方便后面plot,取第一个地点
didian_list.append(didian)
actors=s3.get('actors')#提取电影主演
actors=''.join(actors)
actors_list.append(actors)
for i in range(1,32):
if i==31:
urls='https://movie.douban.com/j/chart/top_list?type=31&interval_id=100%3A90&action=&start=0&limit=11'
else:
urls = 'https://movie.douban.com/j/chart/top_list?type={}&interval_id=100%3A90&action=&start=0&limit=50'.format(i) # 观察豆瓣链接格式的编码规则,创建爬虫
douban(urls)
dict={'题目':title_list,'分类排名':rank_list,'链接':lianjie_list,'电影类别':leibie_list,'评分':pingfen_list,'国家':didian_list,'演员':actors_list}
dt=pd.DataFrame(dict)#变成dataframe
dt.to_csv(r'C:\Users\asus\Desktop\douban.csv',mode='a')#导出到本地表格
for k in range(len(s2_list)):
sum+=s2_list[k]
print('总条数:',sum)#记录抓取条数
#导入mongodb数据库
client=pymongo.MongoClient('mongodb://localhost:27017/')#链接mongodb数据库
db=client['dianying']#创建数据库dianying
db.collection.insert_one(dict)#数据库中插入字典型数据dict
#plot函数画图
print(list(set(dt['国家'])))
plt.plot(list(set(dt['国家'])),dt['评分'].groupby(dt['国家']).mean())
plt.title('各国电影评分')
plt.xlabel('国家分类')
plt.ylabel('评分')
plt.show()
print('运行完成')