zoukankan      html  css  js  c++  java
  • 豆瓣电影简单评分模型-从收集数据到建模分析

    思路:
    从豆瓣上抓取数据【主要是评分,只是那个人数的百分比和最终评分,不过够用了】

    一、收集数据
    起始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  : 
    # @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.由1可知,这是一个监督问题【所有数据都有标签以及标签值】,而且这不是一个分类问题。
    3.特征字段有多个,多特征问题
    5.考虑选取线性规划模型进行问题的探究
    6.进行模型的评估:根据预测值以及真实值之间的关系(或者对比)来确定模型的预测精度
    7.建议以及改进想法:
    (1)增大数据量
    (2)模型参数调优
    (3)更换模型以及模型之间的组合
    (4)进行特征的高级筛选处理

    解决matplotlib中文显示问题

    from pylab import *
    mpl.rcParams['font.sans-serif'] = ['SimHei']

    常规操作,先查看一下前十条数据

    df = pd.read_csv('data.csv')
    print(len(df))
    df.head(10) 

    在这里插入图片描述
    检测缺失值 false无

    df.isnull().any()

    在这里插入图片描述
    选取数据列以便 提供数据进行训练

    datas = df.iloc[:,1:]
    datas.head(8)

    在这里插入图片描述
    把数据处理一下:

    for columns in datas.iloc[:,1:].columns:
        datas[columns] = datas[columns].str.strip("%").astype(float)/100
    datas['最终评分'] = datas['最终评分'].astype(float)
    datas.head(10)

    在这里插入图片描述
    转换成数组,方便操作以及个人习惯

    datasArray2 = datas.values

    构建模型:

    # 拆分数据集
    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)
    在这里插入图片描述
    

    所以此模型准确率: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()

    在这里插入图片描述

    查看回归系数【其实相当于权重系数】
    查看常数值

    在这里插入图片描述
    也就是说,这个模型的表达式:

    Y = 6.20437848 * x1+4.20811423*x2+2.20227207*x3+0.23005196*x4-1.80063617*x5+3.79333172

    简单检验一下模型:

    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的值

    在这里插入图片描述
    大致接近 标签值6.7,还行。
    其实用线性模型的目的是因为其简单和数据类型的局限,我的猜测是:那个评分模型肯定不是那么简单的,可能还会有一些用户评论的情感分析和其他的东西在里面。

  • 相关阅读:
    ABP之模块分析
    AutoMapper之ABP项目中的使用介绍
    Castle Windsor常用介绍以及其在ABP项目的应用介绍
    EasyUI实战经验总结,给有需要的人
    无法发送具有此谓词类型的内容正文
    ADO.NET 新特性之SqlBulkCopy
    SVN无法Cleanup
    Mac使用操作
    Mac下的Mysql无法登陆的问题
    mac 终端 常用命令
  • 原文地址:https://www.cnblogs.com/chenruhai/p/12464217.html
Copyright © 2011-2022 走看看