选题的背景
为什么要选择此选题?要达到的数据分析的预期目标是什么?
随着经济社会的快速发展,电影作为精神文化产品,得到越来越多人的青睐,人们对电影的评价页也参差不齐,在海量的资源中如何尽快找到符合个人品味的电影,成为观众新的问题。基于Python的数据爬虫技术是目前使用最广泛的方法之一,它能够以最快捷的方式展示用户体验数据,帮助观众进行影片选择。豆瓣电影是著名的电影网站,通过豆瓣电影提供的开放接口大规模地获取电影相关数据。
主题式网络爬虫设计方案
1.主题式网络爬虫名称 豆瓣电影top250
2.主题式网络爬虫爬取的内容与数据特征分析
用Python编写爬虫程序抓取了Top250排行榜的影片榜单信息,爬取电影的短评、评分、评价数量等数据,并结合Pythorn的多个库(Pandas、Numpy、Matplotib),使用Numpy系统存情和处理大型数据,最终通过图表展示出来。网络信息资源充盈的今天,网络信息的获取工作十分重要,该设计的意义在于为用户观影提供决策支持。
3.主题式网络爬虫设计方案概述
本次设计通过request库访问,用BeautifulSoup分析网页结构获取数据,将采集到的数据保存在本地
Htmls 页面解析
网络爬虫程序设计
1.数据爬取与采集
1 import time 2 import requests 3 import re 4 from openpyxl import workbook # 写入Excel表所用 5 from bs4 import BeautifulSoup as bs 6 from matplotlib import pyplot as plt 7 import matplotlib 8 import seaborn as sns 9 from scipy.optimize import leastsq 10 import numpy as np 11 import scipy as sp 12 import pandas as pd 13 14 class Top250: 15 def __init__(self): 16 #起始地址 17 self.start_url = 'https://movie.douban.com/top250' 18 #请求头,浏览器模拟 19 self.headers = { 20 'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36', 21 } 22 #爬取页数 23 self.page_num = 10 24 25 26 def get_page_url(self): 27 n = 0 #第一页开始,下标0 28 while n<self.page_num: 29 yield self.start_url+'?start={}&filter='.format(n*25) 30 n += 1 31 32 def getHtml(self): 33 gu = self.get_page_url() #url生成器 34 for url in gu: 35 html = requests.get(url,headers=self.headers).text 36 yield html 37 38 def getData(self): 39 gh = self.getHtml() # html源码生成器 40 for html in gh: # html:网页源码 41 soup = bs(html, 'lxml') 42 for info in soup.find_all('div', class_='info'): 43 c_name = info.find('span',class_='title').text.strip() # 得到电影中文名 44 message = info.select('div.bd p')[0].text.strip() #得到导演、主演、年份、地区信息 45 yat = re.search('[0-9]+.*\/?', message).group().split('/') #得到年份、地区、类型信息列表 46 year,area,type = yat[0],yat[1],yat[2]#得到年份、地区、类型 47 da = re.search('导演.+\s',message).group().strip()+'...' #得到导演、主演混合信息 48 director = re.findall('导演:(.+?)\s',da)[0].strip() #得到导演信息 49 #得到主演信息,不存在时发生异常,进行异常处理 50 try: 51 mainActors = re.findall('主演:(.+?)[.,]+',da)[0].strip() 52 except IndexError: 53 mainActors = '暂无主演信息' 54 mark_info = info.find('div',class_='star') #得到评分、评价人数混合信息 55 score= mark_info.find('span',class_='rating_num').text.strip()#得到评分 56 count = re.search('[0-9]+',mark_info.select('span')[3].text).group() #得到评价人数 57 #得到简介,捕捉不存在时的异常 58 try: 59 quote = info.select('p.quote span')[0].text.strip() 60 except IndexError: 61 quote = '该影片暂时无简介' 62 yield [c_name,year,area,type,director,mainActors,score,count,quote] 63 64 65 def saveToExcel(self,file_name): 66 wb = workbook.Workbook() # 创建Excel对象 67 ws = wb.active # 获取当前正在操作的表对象 68 ws.append(['电影名', '年份', '地区', '剧情类型', '导演', '主演', '评分', '评论人数', '简介']) 69 gd = self.getData() #数据生成器 70 for data in gd: 71 ws.append(data) 72 wb.save(file_name) 73 74 if __name__ == '__main__': 75 start = time.time() 76 top = Top250() 77 try: 78 top.saveToExcel('top250.xlsx') 79 print('抓取成功,用时%4.2f'%(time.time()-start)+'秒') 80 except Exception as e: 81 print('抓取失败,原因:%s'%e)
2.对数据进行清洗和处理
1 df = pd.DataFrame(pd.read_excel('top250.xlsx'),columns=['排名','电影名', '年份', '地区', '剧情类型', '导演', '主演', '评分', '评论人数', '简介']) 2 print(df.head()) 3 # 读取excel文件 4 5 6 print(df.head()) 7 # 删除无效行与列 8 9 print(df.isnull().sum()) 10 # 返回0,表示没有空值 11 print(df.isna().head()) 12 # 统计缺失值 13 print(df.isna().head()) 14 # 查找重复值
3.数据分析与可视化
1 x = df.排名 2 y = df['评分'][:250] 3 plt.xlabel('评分') 4 plt.ylabel('排名') 5 plt.bar(x,y) 6 plt.title("排名与评分比较图") 7 plt.show() 8 #柱状图
1 x = df.排名 2 y = df['评分'][:250] 3 plt.xlabel('排名') 4 plt.ylabel('评分') 5 plt.plot() 6 plt.scatter(x,y) 7 plt.title("排名与评分比较图") 8 plt.show() 9 #散点图
1 sns.lmplot(x='排名',y='评分',data=df) 2 #线性图
4.回归方程
1 X=df.loc[:,'排名'] 2 Y=df.loc[:,'评分'] 3 def func(params,x): 4 a,b,c=params 5 return a*x*x+b*x+c 6 def error_func(params,x,y): 7 return func(params,x)-y 8 P0=[1,9.0] 9 def main(): 10 plt.figure(figsize=(8,6)) 11 P0=[1,9.0,1] 12 Para=leastsq(error_func,P0,args=(X,Y)) 13 a,b,c=Para[0] 14 print("a=",a, "b=",b, "c=",c) 15 plt.scatter(X,Y,color="green",label="样本数据",linewidth=2) 16 x=np.linspace(1,250,40) 17 y=a*x*x+b*x+c 18 plt.plot(x,y,color="red",label="拟合曲线",linewidth=2) 19 plt.xlabel('排名') 20 plt.ylabel('得分') 21 plt.title("排名与得分回归方程") 22 plt.grid() 23 plt.legend() 24 plt.show() 25 main()
5.完整代码
1 import time 2 import requests 3 import re 4 from openpyxl import workbook # 写入Excel表所用 5 from bs4 import BeautifulSoup as bs 6 from matplotlib import pyplot as plt 7 import matplotlib 8 import seaborn as sns 9 from scipy.optimize import leastsq 10 import numpy as np 11 import scipy as sp 12 import pandas as pd 13 14 class Top250: 15 def __init__(self): 16 #起始地址 17 self.start_url = 'https://movie.douban.com/top250' 18 #请求头,浏览器模拟 19 self.headers = { 20 'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36', 21 } 22 #爬取页数 23 self.page_num = 10 24 25 26 def get_page_url(self): 27 n = 0 #第一页开始,下标0 28 while n<self.page_num: 29 yield self.start_url+'?start={}&filter='.format(n*25) 30 n += 1 31 32 def getHtml(self): 33 gu = self.get_page_url() #url生成器 34 for url in gu: 35 html = requests.get(url,headers=self.headers).text 36 yield html 37 38 def getData(self): 39 gh = self.getHtml() # html源码生成器 40 for html in gh: # html:网页源码 41 soup = bs(html, 'lxml') 42 for info in soup.find_all('div', class_='info'): 43 c_name = info.find('span',class_='title').text.strip() # 得到电影中文名 44 message = info.select('div.bd p')[0].text.strip() #得到导演、主演、年份、地区信息 45 yat = re.search('[0-9]+.*\/?', message).group().split('/') #得到年份、地区、类型信息列表 46 year,area,type = yat[0],yat[1],yat[2]#得到年份、地区、类型 47 da = re.search('导演.+\s',message).group().strip()+'...' #得到导演、主演混合信息 48 director = re.findall('导演:(.+?)\s',da)[0].strip() #得到导演信息 49 #得到主演信息,不存在时发生异常,进行异常处理 50 try: 51 mainActors = re.findall('主演:(.+?)[.,]+',da)[0].strip() 52 except IndexError: 53 mainActors = '暂无主演信息' 54 mark_info = info.find('div',class_='star') #得到评分、评价人数混合信息 55 score= mark_info.find('span',class_='rating_num').text.strip()#得到评分 56 count = re.search('[0-9]+',mark_info.select('span')[3].text).group() #得到评价人数 57 #得到简介,捕捉不存在时的异常 58 try: 59 quote = info.select('p.quote span')[0].text.strip() 60 except IndexError: 61 quote = '该影片暂时无简介' 62 yield [c_name,year,area,type,director,mainActors,score,count,quote] 63 64 65 def saveToExcel(self,file_name): 66 wb = workbook.Workbook() # 创建Excel对象 67 ws = wb.active # 获取当前正在操作的表对象 68 ws.append(['电影名', '年份', '地区', '剧情类型', '导演', '主演', '评分', '评论人数', '简介']) 69 gd = self.getData() #数据生成器 70 for data in gd: 71 ws.append(data) 72 wb.save(file_name) 73 74 if __name__ == '__main__': 75 start = time.time() 76 top = Top250() 77 try: 78 top.saveToExcel('top250.xlsx') 79 print('抓取成功,用时%4.2f'%(time.time()-start)+'秒') 80 except Exception as e: 81 print('抓取失败,原因:%s'%e) 82 83 df = pd.DataFrame(pd.read_excel('top250.xlsx'),columns=['排名','电影名', '年份', '地区', '剧情类型', '导演', '主演', '评分', '评论人数', '简介']) 84 print(df.head()) 85 # 读取excel文件 86 87 88 print(df.head()) 89 # 删除无效行与列 90 91 print(df.isnull().sum()) 92 # 返回0,表示没有空值 93 print(df.isna().head()) 94 # 统计缺失值 95 print(df.isna().head()) 96 # 查找重复值 97 98 from matplotlib import pyplot as plt 99 import matplotlib 100 import seaborn as sns 101 from scipy.optimize import leastsq 102 103 import numpy as np 104 import scipy as sp 105 import pandas as pd 106 107 x = df.排名 108 y = df['评分'][:250] 109 plt.xlabel('评分') 110 plt.ylabel('排名') 111 plt.bar(x,y) 112 plt.title("排名与评分比较图") 113 plt.show() 114 #柱状图 115 116 117 x = df.排名 118 y = df['评分'][:250] 119 plt.xlabel('排名') 120 plt.ylabel('评分') 121 plt.plot() 122 plt.scatter(x,y) 123 plt.title("排名与评分比较图") 124 plt.show() 125 #散点图 126 127 sns.lmplot(x='排名',y='评分',data=df) 128 #线性图 129 130 X=df.loc[:,'排名'] 131 Y=df.loc[:,'评分'] 132 def func(params,x): 133 a,b,c=params 134 return a*x*x+b*x+c 135 def error_func(params,x,y): 136 return func(params,x)-y 137 P0=[1,9.0] 138 def main(): 139 plt.figure(figsize=(8,6)) 140 P0=[1,9.0,1] 141 Para=leastsq(error_func,P0,args=(X,Y)) 142 a,b,c=Para[0] 143 print("a=",a, "b=",b, "c=",c) 144 plt.scatter(X,Y,color="green",label="样本数据",linewidth=2) 145 x=np.linspace(1,250,40) 146 y=a*x*x+b*x+c 147 plt.plot(x,y,color="red",label="拟合曲线",linewidth=2) 148 plt.xlabel('排名') 149 plt.ylabel('得分') 150 plt.title("排名与得分回归方程") 151 plt.grid() 152 plt.legend() 153 plt.show() 154 main()
经过对主题数据的分析与可视化可以让数据以更生动形象具体的方式呈现在我们眼前
在完成此设计过程中发现通过Chrome浏览器对于写爬虫非常有用,Chrome自带的开发者工具能帮助分析网页的源码、资源和数据包。特别是要写表单提交一类功能时,Chrome自带的抓包功能非常好用,通过分析包结构可以实现各类复杂表单的模拟提交。