一、主题式网络爬虫设计方案(15分)
1.主题式网络爬虫名称
优酷电影TOP250数据分析
2.主题式网络爬虫爬取的内容与数据特征分析
电影的相关类容
3.主题式网络爬虫设计方案概述(包括实现思路与技术难点)
思路:对网页进行分析,通过爬虫读取数据存入excel,对数据清洗分析
难点:数据的处理
二、主题页面的结构特征分析(15分)
1.主题页面的结构与特征分析
# <span property="v:itemreviewed">肖申克的救赎 The Shawshank Redemption</span>
# <a href="/celebrity/1047973/" rel="v:directedBy">弗兰克·德拉邦特</a>
# <a href="/celebrity/1054521/" rel="v:starring">蒂姆·罗宾斯</a>
2.Htmls页面解析
三、网络爬虫程序设计(60分)
爬虫程序主体要包括以下各部分,要附源代码及较详细注释,并在每部分程序后面提供输出结果的截图。
1.数据爬取与采集(20)
import requests from bs4 import BeautifulSoup import re import pandas from matplotlib import pyplot as plt import numpy as np import scipy as sp import pandas as pd from matplotlib import pyplot as plt import matplotlib import seaborn as sns from scipy.optimize import leastsq headers = { 'Host':'movie.douban.com', 'Origin':'movie.douban.com', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.122 Safari/537.36', } base_url = 'https://movie.youku.com/top250?start={}&filter=' response = requests.get('https://movie.youku.com/top250?start=0&filter=', headers = headers, allow_redirects=False) if response.status_code == 200: # print(response.text) pass pattern1 = re.compile('<div.*?class="item">.*?<div.*?class="pic">.*?<a.*?href="(.*?)">', re.S) # 去掉所有换行符,并用正则表达式去匹配每一个页面的具体电影 urls = re.findall(pattern1, response.text) directors = [] # 导演 names = [] # 电影名 stars = [] # 主演 countrys = [] # 电影的出产地 languages = [] # 电影语言 typs = [] # 电影类型 sorces = [] #评分 # <span property="v:itemreviewed">肖申克的救赎 The Shawshank Redemption</span> # <a href="/celebrity/1047973/" rel="v:directedBy">弗兰克·德拉邦特</a> # <a href="/celebrity/1054521/" rel="v:starring">蒂姆·罗宾斯</a> def base_urls(base_url): urls = [] # for i in range(0, 250, 25): # true_url = base_url.format(i) # print(true_url) for i in range(0, 50, 25): true_url = base_url.format(i) response = requests.get(true_url, headers=headers, allow_redirects=False) if response.status_code == 200: # print(response.text) pattern1 = re.compile('<div.*?class="item">.*?<div.*?class="pic">.*?<a.*?href="(.*?)">',re.S) # 去掉所有换行符,并用正则表达式去匹配每一个页面的具体电影 url = re.findall(pattern1, response.text) # 因为这里是用findall,他返回的是一个列表,如果我们直接append,会导致列表嵌套,故我们这里用个for循环提取出列表的元素再append进去 for i in url: urls.append(i) return urls def parse_url(urls): for i in range(0, 50, 1): res = requests.get(urls[i], headers = headers, allow_redirects=False) if res.status_code == 200: soup = BeautifulSoup(res.text, 'lxml') # 爬取电影名 name = soup.find('span', property="v:itemreviewed") names.append(name.text) # 爬取导演 director = soup.find('a', rel="v:directedBy") directors.append(director.text) #爬取类型 typ =soup.find('span', property="v:genre")[1:] typs.append(typ.text) # 爬取明星 star_save = [] for star in soup.find_all('a', rel="v:starring"): star_save.append(star.text) stars.append(star_save) # 爬取制片国家 #<span class="pl">制片国家/地区:</span> 美国<br> country = soup.find('span', text='制片国家/地区:').next_sibling[1:] countrys.append(country) # 爬取影片语言 # <span class="pl">语言:</span> language = soup.find('span', text='语言:').next_sibling[1:] languages.append(language) #爬取评分 sorce = soup.find('span', class_="rating_num") sorces.append(sorce.text) # print(directors) # print(true_director) # print(a) if __name__ == '__main__': base = base_urls(base_url) parse_url(base) print(countrys) print(directors) print(languages) print(names) print(typs) print(sorces) # # 最后我们将数据写入到一个excel表格里 info ={'Filmname':names, 'Directors':directors, 'Country':countrys, 'Languages':languages, 'typs':typs, "sorce":sorces} pdfile = pandas.DataFrame(info) pdfile.to_excel('DoubanFilm.xlsx', sheet_name="豆瓣电影")
2.对数据进行清洗和处理(10)
df = pd.DataFrame(pd.read_excel('DoubanFilm.xlsx'),columns=['Numbers','Filmname','Directors','Country','Languages','typs','score']) print(df.head()) # 读取excel文件 df.drop('Filmname', axis=1, inplace = True) df.drop('Directors', axis=1, inplace = True) df.drop('Languages', axis=1, inplace = True) print(df.head()) # 删除无效行与列 print(df.isnull().sum()) # 返回0,表示没有空值 print(df.isna().head()) # 统计缺失值 print(df.isna().head()) # 查找重复值
4.数据分析与可视化(例如:数据柱形图、直方图、散点图、盒图、分布图)(15分)
plt.rcParams['font.sans-serif']=['STSong'] # 显示中文 plt.rcParams['axes.unicode_minus']=False # 用来正常显示负号 x = df.typs y = df['Numbers'][:50] plt.xlabel('类型') plt.ylabel('排名') plt.bar(x,y) plt.title("排名与类型比较图") plt.show() #柱状图 x = df.typs y = df['Numbers'][:50] plt.xlabel('类型') plt.ylabel('排名') plt.plot() plt.scatter(x,y) plt.title("排名与类型比较图") plt.show() #散点图 sns.lmplot(x='score',y='Numbers',data=df) #线性图
5.根据数据之间的关系,分析两个变量之间的相关系数,画出散点图,并建立变量之间的回归方程(一元或多元)(10分)。
X = df.score Y = df.Numbers def func(params, x): a, b, c = params return a*x*x+b*x+c def error(params,x,y): return func(params,x)-y def main(a,b,c): p0 = [0,0,0] Para=leastsq(error,p0,args=(X,Y)) a,b,c=Para[0] print("a=",a,"b=",b,"c=",c) plt.scatter(X,Y,color="green",label=u"评分分布",linewidth=2) x=np.linspace(0,30,20) y=a*x*x+b*x+c plt.plot(x,y,color="red",label=u"回归方程直线",linewidth=2) plt.title("电影排名和评分关系图") plt.legend() plt.grid() plt.show() main() #一元二次回归方程
7.将以上各部分的代码汇总,附上完整程序代码
1 import requests 2 from bs4 import BeautifulSoup 3 import re 4 import pandas 5 from matplotlib import pyplot as plt 6 import numpy as np 7 import scipy as sp 8 import pandas as pd 9 from matplotlib import pyplot as plt 10 import matplotlib 11 import seaborn as sns 12 from scipy.optimize import leastsq 13 14 headers = { 15 'Host':'movie.douban.com', 16 'Origin':'movie.douban.com', 17 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.122 Safari/537.36', 18 } 19 base_url = 'https://movie.douban.com/top250?start={}&filter=' 20 21 22 23 24 25 response = requests.get('https://movie.douban.com/top250?start=0&filter=', headers = headers, allow_redirects=False) 26 if response.status_code == 200: 27 # print(response.text) 28 pass 29 30 pattern1 = re.compile('<div.*?class="item">.*?<div.*?class="pic">.*?<a.*?href="(.*?)">', re.S) # 去掉所有换行符,并用正则表达式去匹配每一个页面的具体电影 31 urls = re.findall(pattern1, response.text) 32 33 directors = [] # 导演 34 35 names = [] # 电影名 36 37 stars = [] # 主演 38 39 countrys = [] # 电影的出产地 40 41 languages = [] # 电影语言 42 43 typs = [] # 电影类型 44 45 sorces = [] #评分 46 47 # <span property="v:itemreviewed">肖申克的救赎 The Shawshank Redemption</span> 48 # <a href="/celebrity/1047973/" rel="v:directedBy">弗兰克·德拉邦特</a> 49 # <a href="/celebrity/1054521/" rel="v:starring">蒂姆·罗宾斯</a> 50 def base_urls(base_url): 51 urls = [] 52 53 # for i in range(0, 250, 25): 54 # true_url = base_url.format(i) 55 # print(true_url) 56 for i in range(0, 50, 25): 57 true_url = base_url.format(i) 58 59 response = requests.get(true_url, headers=headers, allow_redirects=False) 60 if response.status_code == 200: 61 # print(response.text) 62 63 pattern1 = re.compile('<div.*?class="item">.*?<div.*?class="pic">.*?<a.*?href="(.*?)">',re.S) 64 # 去掉所有换行符,并用正则表达式去匹配每一个页面的具体电影 65 url = re.findall(pattern1, response.text) 66 # 因为这里是用findall,他返回的是一个列表,如果我们直接append,会导致列表嵌套,故我们这里用个for循环提取出列表的元素再append进去 67 68 for i in url: 69 urls.append(i) 70 return urls 71 72 def parse_url(urls): 73 74 for i in range(0, 50, 1): 75 res = requests.get(urls[i], headers = headers, allow_redirects=False) 76 if res.status_code == 200: 77 soup = BeautifulSoup(res.text, 'lxml') 78 # 爬取电影名 79 name = soup.find('span', property="v:itemreviewed") 80 names.append(name.text) 81 82 # 爬取导演 83 director = soup.find('a', rel="v:directedBy") 84 directors.append(director.text) 85 86 #爬取类型 87 typ =soup.find('span', property="v:genre")[1:] 88 typs.append(typ.text) 89 90 # 爬取明星 91 star_save = [] 92 for star in soup.find_all('a', rel="v:starring"): 93 star_save.append(star.text) 94 stars.append(star_save) 95 96 97 # 爬取制片国家 98 #<span class="pl">制片国家/地区:</span> 美国<br> 99 country = soup.find('span', text='制片国家/地区:').next_sibling[1:] 100 countrys.append(country) 101 102 103 # 爬取影片语言 104 # <span class="pl">语言:</span> 105 language = soup.find('span', text='语言:').next_sibling[1:] 106 languages.append(language) 107 108 #爬取评分 109 sorce = soup.find('span', class_="rating_num") 110 sorces.append(sorce.text) 111 112 # print(directors) 113 # print(true_director) 114 # print(a) 115 if __name__ == '__main__': 116 base = base_urls(base_url) 117 parse_url(base) 118 print(countrys) 119 print(directors) 120 print(languages) 121 print(names) 122 print(typs) 123 print(sorces) 124 125 # 最后我们将数据写入到一个excel表格里 126 info ={'Filmname':names, 'Directors':directors, 'Country':countrys, 'Languages':languages, 'typs':typs, "sorce":sorces} 127 pdfile = pandas.DataFrame(info) 128 129 pdfile.to_excel('DoubanFilm.xlsx', sheet_name="豆瓣电影") 130 131 #读取excel 132 df = pd.DataFrame(pd.read_excel('DoubanFilm.xlsx'),columns=['Numbers','Filmname','Directors','Country','Languages','typs','score']) 133 print(df.head()) 134 135 # 删除无效行与列 136 df.drop('Filmname', axis=1, inplace = True) 137 df.drop('Directors', axis=1, inplace = True) 138 df.drop('Languages', axis=1, inplace = True) 139 print(df.head()) 140 141 print(df.isnull().sum()) 142 # 返回0,表示没有空值 143 print(df.isna().head()) 144 # 统计缺失值 145 print(df.isna().head()) 146 # 查找重复值 147 plt.rcParams['font.sans-serif']=['STSong'] 148 # 显示中文 149 plt.rcParams['axes.unicode_minus']=False 150 # 用来正常显示负号 151 152 x = df.typs 153 y = df['Numbers'][:50] 154 plt.xlabel('类型') 155 plt.ylabel('排名') 156 plt.bar(x,y) 157 plt.title("排名与类型比较图") 158 plt.show() 159 #柱状图 160 161 x = df.typs 162 y = df['Numbers'][:50] 163 plt.xlabel('类型') 164 plt.ylabel('排名') 165 plt.plot() 166 plt.scatter(x,y) 167 plt.title("排名与类型比较图") 168 plt.show() 169 #散点图 170 171 sns.lmplot(x='score',y='Numbers',data=df) 172 #线性图 173 174 X = df.score 175 Y = df.Numbers 176 def func(params, x): 177 a, b, c = params 178 return a*x*x+b*x+c 179 def error(params,x,y): 180 return func(params,x)-y 181 def main(a,b,c): 182 p0 = [0,0,0] 183 Para=leastsq(error,p0,args=(X,Y)) 184 a,b,c=Para[0] 185 print("a=",a,"b=",b,"c=",c) 186 plt.scatter(X,Y,color="green",label=u"评分分布",linewidth=2) 187 x=np.linspace(0,30,20) 188 y=a*x*x+b*x+c 189 plt.plot(x,y,color="red",label=u"回归方程直线",linewidth=2) 190 plt.title("电影排名和评分关系图") 191 plt.legend() 192 plt.grid() 193 plt.show() 194 main() 195 #一元二次回归方程
四、结论(10分)
1.经过对主题数据的分析与可视化,可以得到哪些结论?
可以更直观的了解数据
2.对本次程序设计任务完成的情况做一个简单的小结。
通过此次作业了解到对于函数熟悉应用重要性以及
通过对代码不断的修改,对于python有更深的认识