思路:
从豆瓣上抓取数据【主要是评分,只是那个人数的百分比和最终评分,不过够用了】
一、收集数据
起始URL:https://movie.douban.com/j/new_search_subjects?sort=U&range=0,10&tags=&start=0
【注,爬取的对象是使用ajax传输数据的,就是传输json字符串的那种啦,学过一点web基础,但不是很懂,别喷我喔,留言我会改正说法的啦】
首先就是先爬取单页嘛,然后找到规律然后根据需要循环爬取一定数量的数据,当然了期间要加一些反反爬的措施。(这里用到了timeout,verify=False关闭证书验证,headers,还有就是IP代理池【中间的时候用了一下,后来发现根本用不着】)
然后注意还需要一些异常处理。之后就是把结果值返回,然后添加到一个列表里面,可以使用pandas的Dataframe或者numpy的array规范数据,或者使用字典然后存储到json文件也好【不过我这个不太熟】,最后存储写入文件即可。
大家都是有点基础的啦,那我就直接贴代码了,基础不行的请先学习爬虫的基础知识。
注释在代码中:
# -*- coding: utf-8 -*-
# @Time : 2019/6/12 19:00
# @Author : chenruhai
# @File : GetMovie.py
import requests
import logging
import json
from lxml import etree
import pandas as pd
'''
获取数据分析所需的字段内容
抓取字段:影片名,最终评分,五星、四星、三星、二星、一星
抓取的startURL: https://movie.douban.com/j/new_search_subjects?sort=U&range=0,10&tags=&start=0
'''
class Movie:
def __init__(self):
self.PROXY_POOL_URL = 'http://localhost:5000/get'
self.headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36'}
# self.proxys = {}
def get_proxy(self):#代理池 未启用
try:
response = requests.get(self.PROXY_POOL_URL)
if response.status_code == 200:
return {
'http':response.text,
'https':response.text
}
#proxies=Movie.get_proxy(self)
except ConnectionError:
return None
def getUrl(self,upLimit):
logging.captureWarnings(True) #关闭多余的警告信息
for i in range(0, upLimit, 20):
#确定起始URL
urls = 'https://movie.douban.com/j/new_search_subjects?sort=U&range=0,10&tags=&start={}'.format(i)
try:
responses = requests.get(urls,headers=self.headers,timeout=5,verify=False) # verify=False,不验证证书
if responses.status_code == 200:
#如果起始URL响应正常,打印一下信息
print('成功连接: ', urls)
responsesDict = json.loads(responses.text)
for dicts in responsesDict['data']:
url = dicts['url']
try:
response = requests.get(url, headers=self.headers, timeout=5, verify=False)
response.encoding = 'utf-8'
if response.status_code == 200: #对是否有正常的响应 加入判断
#如果url响应正常打印如下信息
print("子网页链接成功: ", url, ' 链接状态 :', response.status_code, '正在等待解析.....')
html = etree.HTML(response.text)
#使用xpath进行解析
movie_Name_Year = html.xpath('//*[@id="content"]/h1/span/text()')
movie_Score = html.xpath(
'//*[@id="interest_sectl"]//div[@class="rating_self clearfix"]/strong/text()')
movie_Star = html.xpath(
'//*[@id="interest_sectl"]//div[@class="ratings-on-weight"]/div[@class="item"]/span[@class="rating_per"]/text()')
item = [movie_Name_Year[0], movie_Score[0], movie_Star[0], movie_Star[1], movie_Star[2],
movie_Star[3], movie_Star[4]]
print('解析成功!')
# 名字 电影评分 五星 四星 三星 二星 一星
yield item
else:
pass
except:
#url没有正常响应
print("子网链接失败: ",url)
else:
pass
except:
#起始URL没有返回正常响应
print('当前urls: ', urls, ' 未响应!')
def saveFile(self):
datas = [] #所有数据将加入这里
for item in Movie.getUrl(self,1200):
datas.append(item) #添加数据到datas列表
dataColums = ['影片名', '最终评分', '五星', '四星', '三星', '二星', '一星']
#将数据转成Dataframe
files = pd.DataFrame(columns=dataColums, data=datas)
files.to_csv(r'E:\DemoMain\课程考核接单\data.csv',index=None) #=保存到文件
#成功保存到文件后,打印输出done!提示
print("done!")
def main(self):
Movie.saveFile(self)
if __name__ == '__main__':
M = Movie()
M.main()1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
二、建模分析
【菜鸟上路,勿喷,嘻。欢迎大佬们一起讨论和学习】
思路:
1.观察数据:数据除"影片名"外,为数值型,也就是参与模型构建的数据是数值型,标签"最终评分"也为数值型,而且无明显类别界限。
2.由1可知,这是一个监督问题【所有数据都有标签以及标签值】,而且这不是一个分类问题。
3.特征字段有多个,多特征问题
5.考虑选取线性规划模型进行问题的探究
6.进行模型的评估:根据预测值以及真实值之间的关系(或者对比)来确定模型的预测精度
7.建议以及改进想法:
(1)增大数据量
(2)模型参数调优
(3)更换模型以及模型之间的组合
(4)进行特征的高级筛选处理
解决matplotlib中文显示问题
from pylab import *
mpl.rcParams['font.sans-serif'] = ['SimHei']1
2
常规操作,先查看一下前十条数据
df = pd.read_csv('data.csv')
print(len(df))
df.head(10)1
2
3
检测缺失值 false无
df.isnull().any()1
选取数据列以便 提供数据进行训练
datas = df.iloc[:,1:]
datas.head(8)1
2
把数据处理一下:
for columns in datas.iloc[:,1:].columns:
datas[columns] = datas[columns].str.strip("%").astype(float)/100
datas['最终评分'] = datas['最终评分'].astype(float)
datas.head(10)1
2
3
4
转换成数组,方便操作以及个人习惯
datasArray2 = datas.values1
构建模型:
# 拆分数据集
X_train, X_test, y_train, y_test = train_test_split(datasArray2[:,1:],datasArray2[:,:1],test_size=0.25, random_state=0)
# 对训练集进行训练
lr = linear_model.LinearRegression()
lr.fit(X_train, y_train)
# 对测试集进行预测
y_predict2= lr.predict(X_test)
rmse = np.sqrt(metrics.mean_squared_error(y_test, y_predict2)) #均方根误差
print('RMSE:',rmse)1
2
3
4
5
6
7
8
9
10
11
所以此模型准确率:98.2% 【1-rmse】
观察图形:
plt.figure(figsize=(15,5))
plt.plot(range(len(y_test)), y_test, 'r', label='测试数据')
plt.plot(range(len(y_test)), y_predict2, 'b', label='预测数据')
plt.legend()1
2
3
4
查看回归系数【其实相当于权重系数】
查看常数值
也就是说,这个模型的表达式:
Y = 6.20437848 * x1+4.20811423*x2+2.20227207*x3+0.23005196*x4-1.80063617*x5+3.793331721
简单检验一下模型:
checkLabel = 6.7
checkArray = np.array([[0.091,0.330,0.442,0.110,0.028]])
y_predict_check= lr.predict(checkArray)
y_predict_check
#查看y_predict_check的值1
2
3
4
5
大致接近 标签值6.7,还行。
其实用线性模型的目的是因为其简单和数据类型的局限,我的猜测是:那个评分模型肯定不是那么简单的,可能还会有一些用户评论的情感分析和其他的东西在里面。