精华内容
下载资源
问答
  •        中国男女比例的失衡,再加上广大男同胞们都想着努力为自己的事业而奋斗很少能够接触到...2、本爬虫爬取的数据存入到MongoDB数据库中(提供有转换后的.xlsx文件) 3、爬虫代.

           中国男女比例的失衡,再加上广大男同胞们都想着努力为自己的事业而奋斗很少能够接触到女人,使得乎广大男同胞大都选择相亲网站来找到属于自己的另一半,,作为90的我深知广大男同胞的心情,于是乎博主通过对世纪佳缘相亲网站进行详细的可视化分析来为广大男同胞们提供相应的意见

    一、爬虫部分
    爬虫说明:
    1、本爬虫是以面向对象的方式进行代码架构的
    2、本爬虫爬取的数据存入到MongoDB数据库中(提供有转换后的.xlsx文件)
    3、爬虫代码中有详细注释
    4、爬虫爬取的数据以江苏省的小姐姐为例

    代码展示

    import json
    import re
    import time
    from pymongo import MongoClient
    import requests
    
    
    class JiaYuanSpider(object):
        def __init__(self):
            self.url_temp = 'https://search.jiayuan.com/v2/search_v2.php'
            # 构造请求头  cookie要换成自己浏览器的cookie
            self.headers = {
                # cookie信息换成自己的cookie
                'Cookie': 'guider_quick_search=on; accessID=202103150924595680; SESSION_HASH=1b565df188507bcdbdc052adb330652be6321e18; user_access=1; save_jy_login_name=15251693528; stadate1=272569046; myloc=32%7C3201; myage=21; mysex=m; myuid=272569046; myincome=50; COMMON_HASH=67e0cfc00edcb430489cc9483f1d0cd3; sl_jumper=%26cou%3D17%26omsg%3D0%26dia%3D0%26lst%3D2021-02-19; last_login_time=1615771547; user_attr=000000; pop_sj=0; PROFILE=273569046%3A%25E5%25B0%258F%25E9%25A9%25AC%25E5%2590%258C%25E5%25AD%25A6%3Am%3Aimages1.jyimg.com%2Fw4%2Fglobal%2Fi%3A0%3A%3A1%3Azwzp_m.jpg%3A1%3A1%3A50%3A10%3A3.0; pop_time=1615771579026; PHPSESSID=ae44e627844be5ef649bf6e96cc6962c; pop_avatar=1; main_search:273569046=%7C%7C%7C00; RAW_HASH=wh-OIJDeJy1X8NOMQ3aP1neiZp17TWqyx%2AyWF494yqKobfNsk8Xeysp0EBUwf6Sz6J1rmpU3wkD4PyqHj-YEgF2sPdVBm1SUFtIHk5FN1cXARdU.; is_searchv2=1',
                'Host': 'search.jiayuan.com',
                'Origin': 'https://search.jiayuan.com',
                'sec-ch-ua': '"Chromium";v="88", "Google Chrome";v="88", ";Not A Brand";v="99"',
                'sec-ch-ua-mobile': '?0',
                'Sec-Fetch-Dest': 'empty',
                'Sec-Fetch-Mode': 'cors',
                'Sec-Fetch-Site': 'same-origin'
            }
            # 构造请求体数据
            self.dat = {
                'sex': 'f',
                'key':'',
                'stc': '1:32,23:1',
                'sn': 'default',
                'sv': '1',
                'p': '1',
                'f': 'select',
                'listStyle': 'bigPhoto',
                'pri_uid': '273569046',
                'jsversion': 'v5',
            }
            # 初始化MongoDB连接
            self.client = MongoClient()
            self.collection = self.client['test']['jiayuan']
    
        # 请求并解析url
        def parse(self,url,page_num):
            dat = self.dat
            dat['p'] = page_num
            time.sleep(1)
            resp = requests.post(url,headers=self.headers,data=dat)
            return resp.content.decode()
    
        # 获取信息
        def get_content_list(self,str_html):
            json_html = re.findall(r'##(\{.*?\})##',str_html)[0]
            json_html = json.loads(json_html)
            user_list = json_html['userInfo']
            for user in user_list:
                item = {}
                item['uid'] = user['uid']
                item['nickname'] = user['nickname']
                item['sex'] = user['sex']
                item['marriage'] = user['marriage']
                item['height'] = user['height']
                item['education'] = user['education']
                item['age'] = user['age']
                item['work_location'] = user['work_location']
                item['shortnote'] = user['shortnote']
                print(item)
                self.save(item)
    
        # 数据保存
        def save(self,item):
            self.collection.insert(item)
    
        # 主程序
        def run(self):
            resp = requests.post(self.url_temp,headers=self.headers,data=self.dat)
            str_html = resp.content.decode()
            json_html = re.findall(r'##(\{.*?\})##',str_html)[0]
            json_html = json.loads(json_html)
            total_page = json_html['pageTotal']
            for i in range(1,int(total_page)+1):
                html_str = self.parse(self.url_temp,i)
                self.get_content_list(html_str)
    
    
    if __name__ == '__main__':
        jiayuan = JiaYuanSpider()
        jiayuan.run()
    
    

    二、数据分析和数据可视化部分

    数据分析和数据可视化说明:
    1、本博客通过Flask框架来进行数据分析和数据可视化
    2、项目的架构图为

    在这里插入图片描述

    代码展示

    • 数据分析代码展示(analysis.py)
    import pandas as pd
    import numpy as np
    import jieba
    import cv2 as cv
    from matplotlib import pyplot as plt
    from wordcloud import WordCloud
    from sklearn.feature_extraction.text import TfidfVectorizer,CountVectorizer
    import pymysql
    
    def pre_process(df):
        """
        数据预处理函数
        :param df:DataFrame类型
        :return:df
        """
        # 将性别为男的数据去除
        df.query('sex != "男"',inplace=True)
        x = df.copy()
        x.loc[:,'shortnote'] = x.loc[:,'shortnote'].apply(lambda x:x.strip())
    
        return x
    
    def word_cloud(df):
        """
        求偶宣言词云图
        :param df: DataFrame类型
        :return:df
        """
        shortnote_list = df['shortnote'].tolist()
        pro_shortnote_list = [' '.join(list(jieba.cut(i))) for i in shortnote_list]
        cut_text = ' '.join(pro_shortnote_list)
    
    
        # 读入图片背景
        # 对于中文词云首先使用jieba来中文分词,然后还要记得指定font_path设置字体识别
        # 想要的话还能设置词云的背景图片
        #
        background_image = cv.imread(r'../static/images/love.jpeg')  # 设置词云形状 默认为矩形
        # 排除无用的词汇 将一些常用的动词、谓语、状语去除 只需要形容词
        exclude = ['我','的','着','在','有','和'
            ,'人','我们','这里','而','能','也',
            '可以','一直','没有','请','很','这个','哪些'
            ,'说','想','需要','到','为','已经','是因为'
            ,'什么','还是','时候','你','是','就','把',
            '一个','会','了','那个','那么','还','她','都',
            '不','他','不是','更','自己','应该','对','要','看'
            ,'你们','两个','希望','来','到','只要','为了','不要'
            ,'让','找','多','吧','哪些','给','呢','但','没','个',
            '无','做','一下','还有','如果','过','中','当做','一点']
    
        word_cloud = WordCloud(font_path="C:/Windows/Fonts/simfang.ttf",collocations=False,mask=background_image,
                               background_color='#fef8ef',scale=1.2,stopwords=exclude,max_font_size=180,min_font_size=15).generate(cut_text)
        plt.figure(figsize=(10, 10))
        plt.imshow(word_cloud, interpolation="bilinear")
        plt.axis("off")
        plt.savefig(r'../static/images/wordCount.jpg')
        plt.show()
    
    def education_level_count(df):
        """
        不同学历的女性数量
        :param df: DataFrame类型
        :return:df
        """
        # 对学历进行分组
        grouped = df.groupby('education')['uid'].count().reset_index()
    
        # 修改列索引名称 把uid改成count
        grouped.rename(columns={'uid':'count'},inplace=True)
    
        # 构造列表嵌套列表的形式 方便后续批量插入到mysql数据库中
        data = [[i['education'],i['count']] for i in grouped.to_dict(orient='records')]
    
        print(data)
        return data
    
    def area_count(df):
        """
        不同地区的女性数量
        :param df: DataFrame类型
        :return:df
        """
        # 对工作场所进行分组
        grouped = df.groupby('work_location')['uid'].count().reset_index()
    
        # 修改列索引名称 把uid改成count
        grouped.rename(columns={'uid':'count'},inplace=True)
    
        # 构造列表嵌套列表的形式 方便后续批量插入到mysql数据库中
        data = [[i['work_location'],i['count']] for i in grouped.to_dict(orient='records')]
    
        print(data)
        return data
    
    def marry_status(df):
        """
        女性的婚姻状况
        :param df: DataFrame类型
        :return: df
        """
        # 对婚姻状况进行分组
        grouped = df.groupby('marriage')['uid'].count().reset_index()
    
        # 修改列索引名称 把uid改成count
        grouped.rename(columns={'uid': 'count'}, inplace=True)
    
        # 构造列表嵌套列表的形式 方便后续批量插入到mysql数据库中
        data = [[i['marriage'],i['count']] for i in grouped.to_dict(orient='records')]
    
        print(data)
        return data
    
    def height_area_count(df):
        """
        不同身高区间的女性数量
        :param df: DataFrame类型
        :return: df
        """
        # 对身高划分区间
        low = df['height'].apply(lambda x:'<160' if x <160 else np.nan).dropna()
        medium = df['height'].apply(lambda x:'160~170' if all((x>=160,x<170)) else np.nan).dropna()
        heigh = df['height'].apply(lambda x:'170~180' if all((x>=170,x<=180)) else np.nan).dropna()
    
        # 合并身高区间
        height_area = pd.concat([low,medium,heigh])
        grouped = height_area.groupby(height_area).count()
    
        data = [[k,v] for k,v in grouped.to_dict().items()]
        print(data)
        return data
    
    def age_area_count(df):
        """
        不同年龄区间的女性数量
        :param df: DataFrame类型
        :return: df
        """
        # 对年龄划分区间
        one = df['age'].apply(lambda x:'20~30' if all((x>=20,x<30)) else np.nan).dropna()
        two = df['age'].apply(lambda x:'30~40' if all((x>=30,x<=40)) else np.nan).dropna()
        three = df['age'].apply(lambda x:'>40' if x>40 else np.nan).dropna()
    
        # 合并年龄区间
        age_area = pd.concat([one,two,three])
        grouped = age_area.groupby(age_area).count()
    
        data = [[k,v] for k,v in grouped.items()]
        print(data)
        return data
    
    
    def save_to_mysql(cursor,sql,data):
        result = cursor.executemany(sql,data)
        if result:
            print('插入成功')
    
    
    if __name__ == '__main__':
        # 读取xlsx文件
        df = pd.read_excel('./jiayuan.xlsx',engine='openpyxl')
        print(df.head())
        print(df.info())
    
        # 对数据进行预处理
        df = pre_process(df)
    
        # 生成词云图
        word_cloud(df)
        raise Exception
        # 不同学历的女性数量
        data1 = education_level_count(df)
    
        # 不同地区的女性数量
        data2 = area_count(df)
    
        # 不同身高区间的女性数量
        data3 = height_area_count(df)
    
        # 不同年龄区间的女性数量
        data4 = age_area_count(df)
    
        # mysql存储数据
        conn = pymysql.Connect(host='localhost',user='root',password='123456',port=3306,database='jiayuan',charset='utf8')
        with conn.cursor() as cursor:
            try:
                sql1 = 'insert into db_edu_level_count(edu_level,count) values(%s,%s)'
                sql2 = 'insert into db_area_count(area,count) values(%s,%s)'
                sql3 = 'insert into db_height_area_count(height_area,count) values(%s,%s)'
                sql4 = 'insert into db_age_area_count(age_area,count) values(%s,%s)'
                save_to_mysql(cursor,sql1,data1)
                save_to_mysql(cursor,sql2,data2)
                save_to_mysql(cursor,sql3,data3)
                save_to_mysql(cursor,sql4,data4)
                conn.commit()
            except pymysql.MySQLError as e:
                print(e)
                conn.rollback()
    
    
    • 数据转换文件MongoDB数据转xlsx(to_excle.py)
    import pandas as pd
    import numpy as np
    from pymongo import MongoClient
    
    def export_excel(export):
        # 将字典列表转换为DataFrame
        df = pd.DataFrame(list(export))
        # 指定生成的Excel表格名称
        file_path = pd.ExcelWriter('jiayuan.xlsx')
        # 替换空单元格
        df.fillna(np.nan, inplace=True)
        # 输出
        df.to_excel(file_path, encoding='utf-8', index=False)
        # 保存表格
        file_path.save()
    
    
    if __name__ == '__main__':
        # 将MongoDB数据转成xlsx文件
        client = MongoClient()
        connection = client['test']['jiayuan_plus']
        ret = connection.find({}, {'_id': 0})
        data_list = list(ret)
        export_excel(data_list)
    
    
    • 数据库模型文件展示(models.py)
    from jiayuan import db
    
    
    class EducationLevelCount(db.Model):
        __tablename__ = 'db_edu_level_count'
        id = db.Column(db.Integer,primary_key=True,autoincrement=True)
        edu_level = db.Column(db.String(20),unique=True)
        count = db.Column(db.Integer)
    
    class AreaCount(db.Model):
        __tablename__ = 'db_area_count'
        id = db.Column(db.Integer,primary_key=True,autoincrement=True)
        area = db.Column(db.String(20),unique=True)
        count = db.Column(db.Integer)
    
    class HeightAreaCount(db.Model):
        __tablename__ = 'db_height_area_count'
        id = db.Column(db.Integer, primary_key=True, autoincrement=True)
        height_area = db.Column(db.String(20),unique=True)
        count = db.Column(db.Integer)
    
    class AgeAreaCount(db.Model):
        __tablename__ = 'db_age_area_count'
        id = db.Column(db.Integer, primary_key=True, autoincrement=True)
        age_area = db.Column(db.String(20), unique=True)
        count = db.Column(db.Integer)
    
    
    
    • 配置文件代码展示(config.py)
    
    # 基本配置
    class Config(object):
        # 配置通用密钥
        SECRET_KEY = 'msqaidongyuqing'
    
        # 配置Mysql连接
        # 指定连接的数据库要提前创建好
        SQLALCHEMY_DATABASE_URI = 'mysql://root:123456@localhost:3306/jiayuan'
        SQLALCHEMY_TRACK_MODIFICATIONS = True
    
    
    class DevelopmentConfig(Config):
        DEBUG=True
    
    class ProductConfig(Config):
        pass
    
    # 创建配置类映射
    config_map = {
        'develop':DevelopmentConfig,
        'product':ProductConfig
    }
    
    • 主工程目录代码展示(api_1_0/_init_.py)
    from flask import Flask
    from config import config_map
    from flask_sqlalchemy import SQLAlchemy
    import pymysql
    
    pymysql.install_as_MySQLdb()
    db = SQLAlchemy()
    
    # 通过工厂模式来创建实例化app对象
    def create_app(config_name='develop'):
        app = Flask(__name__)
        config  = config_map[config_name]
        app.config.from_object(config)
    
        # 初始化数据库
        db.init_app(app)
    
        # 注册蓝图
        from .api_1_0 import show
        app.register_blueprint(show.api,url_prefix='/show')
    
        return app
    
    
    • 主程序文件代码展示(manager.py)
    from jiayuan import create_app,db
    from flask_script import Manager
    from flask_migrate import Migrate,MigrateCommand
    from flask import render_template
    
    app = create_app()
    
    manager = Manager(app)
    
    Migrate(app,db)
    
    manager.add_command('db',MigrateCommand)
    
    # 首页
    @app.route('/')
    def index():
        return render_template('index.html')
    
    if __name__ == '__main__':
        manager.run()
    
    
    
    • 视图文件代码展示(api_1_0/views/_init_.py,show.py)

    _init_.py

    from flask import Blueprint
    from jiayuan import db,models
    
    api = Blueprint('api_1_0',__name__)
    
    from . import show
    

    show.py

    from . import api
    from jiayuan.models import AreaCount,EducationLevelCount,AgeAreaCount,HeightAreaCount
    from flask import render_template
    
    # 绘制不同地区的女性数量
    @api.route('/drawBar')
    def drawBar():
        area_count = AreaCount.query.all()
        area = [i.area for i in area_count]
        count = [i.count for i in area_count]
        return render_template('drawBar.html', **locals())
    
    # 绘制不同学历的女性数量
    @api.route('/drawPie')
    def drawPie():
        height_area_count = HeightAreaCount.query.all()
        height_area_count_data = [{'name':i.height_area,'value':i.count} for i in height_area_count]
    
        age_area_count = AgeAreaCount.query.all()
        age_area_count_data = [{'name':i.age_area,'value':i.count} for i in age_area_count]
    
        return render_template('drawPie.html',**locals())
    
    # 绘制不同身高区间的女性数量&不同年龄区间的女性数量
    @api.route('/drawSignlePie')
    def drawSignlePie():
        edu_level_count  = EducationLevelCount.query.all()
        edu_level_count_data = [{'name':i.edu_level,'value':i.count} for i in edu_level_count]
        return render_template('drawSignalPie.html',**locals())
    
    # 展示词云图
    @api.route('/drawWordCloud')
    def drawWordCloud():
        return render_template('wordCloud.html')
    
    • 主页展示(index.html)

    主页简单创建了四个超链接指向对应的图表

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>
            世界佳缘可视化分析
        </title>
        <style>
            ul{
                width: 800px;
                height: 600px;
                {#list-style: none;#}
                line-height: 60px;
                padding: 40px;
                margin: auto;
            }
            ul li{
                margin-bottom: 20px;
            }
        </style>
    </head>
    <body>
    <ul>
        <li><a href="{{ url_for('api_1_0.drawWordCloud') }}"><h3>择偶宣言词云图</h3></a></li>
        <li><a href="{{ url_for('api_1_0.drawBar') }}"><h3>不同地区的女性数量</h3></a></li>
        <li><a href="{{ url_for('api_1_0.drawPie') }}"><h3>不同身高区间的女性数量&不同年龄区间的女性数量</h3></a></li>
        <li><a href="{{ url_for('api_1_0.drawSignlePie') }}"><h3>不同学历的女性数量</h3></a></li>
    </ul>
    </body>
    </html>
    

    在这里插入图片描述

    • 模板文件代码展示(drawBar.html,wordCloud.html,drawSignalPie.html,drawPie.html)

    wordCloud.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>择偶宣言词云图</title>
    </head>
    <body>
    <div style="width:800px;margin: auto">
        {#此图片路径是根据生成词云图的路径所决定的#}
        <img src="../static/images/wordCount.jpg" style="width: 100%">
    </div>
    </body>
    </html>
    

    在这里插入图片描述

    结论:通过观察词云图,可以看出江苏的求爱小姐姐找对象的一些品质要求,比如说真诚、成熟、责任心、善良的等品质,同时也可以看出江苏省的求爱小姐姐希望能够和喜欢的爱的人一起幸福的生活

    drawBar.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>不同地区的女性数量</title>
        <script src="../static/js/echarts.min.js"></script>
        <script src="../static/js/vintage.js"></script>
    </head>
    <body>
    <div class="cart" style="height: 600px;width: 800px;margin: auto"></div>
    <script>
        var area = {{ area|tojson }}
        var count = {{ count|tojson }}
    
        var MyCharts = echarts.init(document.querySelector('.cart'),'vintage')
        var option = {
            title:{
                text:'不同地区的女性数量',
                textStyle:{
                    fontSize:21,
                    fontFamily:'楷体'
                },
                top:5,
                left:5
            },
            xAxis:{
                type:'category',
                data:area,
                axisLabel:{
                    interval:0,
                    rotate:30,
                    margin:20
                }
            },
            yAxis:{
                type:'value',
                scale:true
            },
            grid:{
                width:640,
                height:480,
                left: 100
            },
            legend:{
                name: area,
                top: 10
            },
            tooltip:{
                trigger:'item',
                triggerOn: 'mousemove',
                formatter:function(arg)
                {
                    return '地区:'+arg.name+'<br/>'+'人数:'+arg.value
                }
            },
            series:[
                {
                    type:'bar',
                    data:count,
                    name:'人数',
                    showBackground: true,
                    backgroundStyle: {
                        color:'rgba(180, 180, 180, 0.2)'
                    },
                    label:{
                        show:true,
                        position:'top',
                        rotate:30,
                        distance:10
                    }
                }
            ]
        }
        MyCharts.setOption(option)
    </script>
    </body>
    </html>
    

    在这里插入图片描述

    结论:通过观察柱状图可以看出江苏省的求爱小姐姐大都分布在南京、苏州、无锡等一些江苏省较发达的城市,可以从侧面反映出城市越发达对寻找另一半的需求越多。

    drawPie.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>不同身高区间的女性数量&不同年龄区间的女性数量</title>
        <script src="../static/js/echarts.min.js"></script>
        <script src="../static/js/vintage.js"></script>
        <style>
            .group{
                margin: auto;
                display: flex;
                justify-content: space-between;
                width: 1300px;
                height: 500px;
            }
        </style>
    </head>
    <body>
    <div class="group">
        <div class="cart1" style="width: 600px;height: 500px;"></div>
        <div class="cart2" style="width: 600px;height: 500px;"></div>
    </div>
    <script>
        var data1 = {{ height_area_count_data|tojson }}
        var data2 = {{ age_area_count_data|tojson }}
    
        var MyCharts1 = echarts.init(document.querySelector('.cart1'),'vintage')
        var MyCharts2 = echarts.init(document.querySelector('.cart2'),'vintage')
    
        function getOption(title_text,data,sign){
            var option = {
                title:{
                    text:title_text,
                    textStyle:{
                        fontSize:21,
                        fontFamily:'楷体'
                    },
                    left: 'center'
                },
                legend:{
                    name:['人数'],
                    left: 20,
                    bottom:20,
                    orient:'vertical'
                },
                tooltip:{
                    trigger:'item',
                    triggerOn:'mousemove',
                    formatter:function (arg)
                    {
                        return sign+':'+arg.name+'<br/>'+'人数:'+arg.value+'<br/>'+'占比:'+arg.percent+'%'
                    }
                },
                series:[
                    {
                        type:'pie',
                        name:'人数',
                        data:data,
                        label:{
                            show:true
                        },
                        itemStyle:{
                            borderColor:'white',
                            borderRadius:10,
                            borderWidth:5
                        },
                        selectedMode:'multiple',
                        selectedOffset:10,
                        radius:['50%','80%'],
                        bottom: -10
                    }
                ]
            }
            return option
        }
        var option1 = getOption('不同身高区间的女性数量',data1,'身高')
        var option2 = getOption('不同年龄区间的女性数量',data2,'年龄')
        MyCharts1.setOption(option1)
        MyCharts2.setOption(option2)
    </script>
    </body>
    </html>
    

    在这里插入图片描述

    结论:通过观察圆环图可以看出,江苏省的求爱小姐姐身高大都在160-170,同时江苏省的求爱小姐姐大都在30岁以上,这就不能叫小姐姐了,改成大姐姐好了,看来都是人到中年才发现另一半的重要性。

    drawSignalPie.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>不同学历的女性数量</title>
        <script src="../static/js/echarts.min.js"></script>
        <script src="../static/js/vintage.js"></script>
    </head>
    <body>
    <div class="cart" style="height: 600px;width: 800px;margin: auto"></div>
    <script>
        var edu_level_count_data = {{ edu_level_count_data|tojson }}
        var MyCharts = echarts.init(document.querySelector('.cart'),'vintage')
        var option = {
            title:{
                text:'不同学历的女性数量',
                textStyle:{
                    fontSize:21,
                    fontFamily:'楷体'
                },
                top:10,
                left:10
            },
            legend:{
                name:['人数'],
                left:20,
                bottom:20,
                orient:'vertical',
                itemWidth:40,
                itemHeight:20
            },
            tooltip:{
                trigger:'item',
                triggerOn:'mousemove',
                formatter:function(arg)
                {
                    return '学历:'+arg.name+'<br/>'+'人数:'+arg.value+'<br/>'+'占比:'+arg.percent+'%'
                }
            },
            series:[
                {
                    type:'pie',
                    data:edu_level_count_data,
                    name:'数量',
                    label:{
                        show:true,
                    },
                    itemStyle: {
                        borderRadius: 10,
                        borderColor: '#fff',
                        borderWidth: 2
                    },
                    labelLine: {
                    show: false
                    },
                    roseType:'radius', // 南丁格尔图玫瑰图
                    {#radius:['50%','80%'],#}
                    selectedMode:'multiple',
                    selectedOffset:20
                }
            ]
        }
        MyCharts.setOption(option)
    </script>
    </body>
    </html>
    

    在这里插入图片描述

    结论:通过观察饼图可以看出,江苏省的求爱大姐姐大学历大都在本科学历或以下,这不禁让我发出这么一个疑问,是不是学历高的江苏大姐姐不需要对象,还是学历高包分配对象,这就不得而知了

    以下是项目源码,希望能够帮助你们,如有疑问,下方评论
    flask项目代码链接

    展开全文
  • 2、本爬虫爬取的数据存入到MongoDB数据库中 3、爬虫代码中有详细注释 代码展示 import re import time from pymongo import MongoClient import requests from lxml import html class BaBaiSpider(): def __init_...

    一、爬虫部分

    爬虫说明:
    1、本爬虫是以面向对象的方式进行代码架构的
    2、本爬虫爬取的数据存入到MongoDB数据库中
    3、爬虫代码中有详细注释

    代码展示

    import re
    import time
    from pymongo import MongoClient
    import requests
    from lxml import html
    
    class BaBaiSpider():
        def __init__(self):
            self.start_url = 'https://movie.douban.com/subject/26754233/reviews'
            self.url_temp = 'https://movie.douban.com/subject/26754233/reviews?start={}'
            # 由于豆瓣有ip地址访问的反爬机制 需要登录账户后获取Cookie信息
            # 有条件的可以使用ip代理池
            self.headers = {
                "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36",
                'Cookie': 'll="118160"; bid=jBJGzgkqoW0; _ga=GA1.2.299310750.1603415173; _vwo_uuid_v2=D02C810B09B328A9291DA2DE0215B1F4E|7b20627b7b4770d357d6251faaad13b7; __yadk_uid=NVdS10Z9dQ70V1AkBBbqmLR6Ny6AQC6R; UM_distinctid=175530c360058f-0cd5eb2121026b-3e604000-144000-175530c3601502; Hm_lvt_19fc7b106453f97b6a84d64302f21a04=1603416111; __utmv=30149280.22554; douban-fav-remind=1; __gads=ID=9b3fe7aa29748925-22a3ff1066c400c6:T=1603618426:RT=1603618426:S=ALNI_MZdkcEBUdorLQd-nNQm0ECaz6aPgQ; __utmc=30149280; __utmc=223695111; ap_v=0,6.0; _pk_ref.100001.4cf6=%5B%22%22%2C%22%22%2C1610800679%2C%22https%3A%2F%2Faccounts.douban.com%2F%22%5D; _pk_ses.100001.4cf6=*; push_doumail_num=0; push_noty_num=0; dbcl2="225547599:+KzDIeqUyH8"; ck=S_qd; __utmt=1; douban-profile-remind=1; __utma=30149280.299310750.1603415173.1610800679.1610803327.13; __utmb=30149280.0.10.1610803327; __utmz=30149280.1610803327.13.11.utmcsr=baidu|utmccn=(organic)|utmcmd=organic|utmctr=%E8%B1%86%E7%93%A3%E7%94%B5%E5%BD%B1; __utma=223695111.299310750.1603415173.1610800679.1610803327.7; __utmb=223695111.0.10.1610803327; __utmz=223695111.1610803327.7.6.utmcsr=baidu|utmccn=(organic)|utmcmd=organic|utmctr=%E8%B1%86%E7%93%A3%E7%94%B5%E5%BD%B1; _pk_id.100001.4cf6=77003652978e8b92.1603415561.6.1610803542.1610797625.'
            }
            # 初始化MongoDB数据库
            self.client = MongoClient()
            self.collection = self.client['test']['babai']
    
        # 构造列表页url
        def get_url_list(self,total_page):
            return [self.url_temp.format(i*20) for i in range(int(total_page)+1)]
    
        # 请求并解析url地址
        def parse_url(self,url):
            rest = requests.get(url,headers=self.headers)
            time.sleep(2)
            return rest.content.decode()
    
        # 获取并解析列表页评论数据
        def get_item(self,str_html):
            new_html = html.etree.HTML(str_html)
            div_list = new_html.xpath('//div[@class="review-list  "]/div')
            # 获取信息多采用三目运算符的方式 防止因获取的内容不存在而报异常
            # 通过三目运算符进行多重判断可以增加程序的稳定性
            for i in div_list:
                item = {}
                title = i.xpath('.//div[@class="main-bd"]/h2/a/text()')
                item['评论标题'] = title[0] if len(title)>0 else None
                name = i.xpath('.//a[@class="name"]/text()')
                item['评论人姓名'] = name[0] if len(name)>0 else None
                rate = i.xpath('.//span[contains(@class,"main-title-rating")]/@title')
                item['评价'] = rate[0] if len(rate)>0 else None
                time = i.xpath('.//span[@class="main-meta"]/text()')
                item['评论时间'] = time[0] if len(time) > 0 else None
                favor = i.xpath('.//div[@class="action"]/a[1]/span/text()')
                item['赞成数'] = favor[0].strip() if len(favor)>0 else None
                oppose = i.xpath('.//div[@class="action"]/a[2]/span/text()')
                item['反对数'] = oppose[0].strip() if len(oppose)>0 else None
                reply = i.xpath('.//a[@class="reply "]/text()')
                item['回复数'] = reply[0].split('回应')[0] if len(reply)>0 else None
                star = i.xpath('.//span[contains(@class,"main-title-rating")]/@class')
                item['评论得分'] = re.findall(r'allstar(\d)0 main-title-rating',star[0])[0] if len(star)>0 else None
                print(item)
                self.save(item)
                
        # 保存评论数据
        def save(self,item):
            self.collection.insert(item)
    
        def run(self):
            # 获取数据总页码数
            rest = requests.get(self.start_url,headers=self.headers)
            str_html = html.etree.HTML(rest.content.decode())
            total_page= str_html.xpath('//div[@class="paginator"]/a[last()]/text()')[0]
            url_list = self.get_url_list(total_page)
            for url in url_list:
                old_html = self.parse_url(url)
                self.get_item(old_html)
    
    if __name__ == '__main__':
        babai = BaBaiSpider()
        babai.run()
    

    二、数据分析和数据可视化部分

    数据分析和数据可视化说明:
    1、本博客通过Flask框架来进行数据分析和数据可视化
    2、项目的架构图为
    在这里插入图片描述

    代码展示

    • 数据分析代码展示(analysis.py)
    from pymongo import MongoClient
    import pandas as pd
    import jieba
    import pymysql
    from wordcloud import WordCloud
    from matplotlib import pyplot as plt
    import cv2 as cv
    import numpy as np
    
    # 评论标题词云
    def word_cloud(df):
        title_list = df['评论标题'].tolist()
        pro_title_list = [' '.join(list(jieba.cut(i))) for i in title_list]
        cut_text = ' '.join(pro_title_list)
    
        # 读入图片背景
        # 对于中文词云首先使用jieba来中文分词,然后还要记得指定font_path设置字体识别
        # 想要的话还能设置词云的背景图片
    
        background_image = cv.imread(r'../static/images/love.jpeg')  # 不设置background_image可以不加这行,得到的词云就是矩形了
    
        word_cloud = WordCloud(font_path="C:/Windows/Fonts/simfang.ttf", mask=background_image,
                              background_color='white').generate(cut_text)
        plt.figure(figsize=(10,10))
        plt.imshow(word_cloud,interpolation="bilinear")
        plt.axis("off")
        # 将词云图保存到静态文件的images目录下 方便后续的展示
        plt.savefig(r'../static/images/wordCount.jpg')
        plt.show()
    
    # 评论数量随时间的变化
    def hour_count(df):
        # 按照小时进行分组求出不同时刻的评论数量
        grouped = df.groupby('评论小时')['评论标题'].count().reset_index()
        data = [[i['评论小时'],i['评论标题']] for i in grouped.to_dict(orient='records')]
        print(data)
        return data
    
    # 不同评价星级的数量
    def star_count(df):
        # 按照评论星级进行分组求不同星级评价的数量
        grouped = df.groupby('评论得分')['评论标题'].count().reset_index()
        data = [[i['评论得分'],i['评论标题']] for i in grouped.to_dict(orient='records')]
        return data
    
    # 评分均值随时间的变化
    def star_avg(df):
        # 将评论小时列数据转换成int类型 方面后续求均值
        df['评论得分'] = df['评论得分'].apply(lambda x:int(x))
        grouped = df.groupby('评论小时')['评论得分'].mean().reset_index()
        data = [[i['评论小时'],round(i['评论得分'],1)] for i in grouped.to_dict(orient='records')]
        return data
    
    
    if __name__ == '__main__':
        client = MongoClient()
        collection = client['test']['babai']
        comments = collection.find({},{'_id':0})
    
        df = pd.DataFrame(comments)
        print(df.info())
        print(df.head(1))
    
        # 删除评论或评论得分中为NaN的数据
        df.dropna(how='any',inplace=True)
    
        # 将赞成数、反对数中为空的值转变成0
        df['赞成数'] = df['赞成数'].apply(lambda x:int(x)if len(x)>0 else 0)
        df['反对数'] = df['反对数'].apply(lambda x:int(x)if len(x)>0 else 0)
    
        # 转换时间类型为pandas时间类型
        df['评论时间'] = pd.to_datetime(df['评论时间'])
        date = pd.DatetimeIndex(df['评论时间'])
        # 增加小时字段
        df['评论小时'] = date.hour
    
        # 评论标题词云
        # word_cloud(df)
    
        # 评论数量随时间的变化
        # data = hour_count(df)
    
        # 不同星级评价的数量
        # data = star_count(df)
    
        # 评分均值随时间的变化
        data = star_avg(df)
    
    
        # 创建数据库连接
        conn = pymysql.connect(host='localhost',user='root',password='123456',port=3306,database='babai',charset='utf8')
        with conn.cursor() as cursor:
            # 评论数量随时间的变化
            # sql = 'insert into db_hour_count(hour,count) values(%s,%s)'
    
            # 不同星级评价的数量
            # sql = 'insert into db_star_count(star,count) values(%s,%s)'
    
            # 评分均值随时间的变化
            sql = 'insert into db_star_avg(hour,star_avg) values(%s,%s)'
            try:
                result = cursor.executemany(sql,data)
                if result:
                    print('插入数据成功')
                    conn.commit()
            except pymysql.MySQLError as error:
                print(error)
                conn.rollback()
            finally:
                conn.close()
    
    
    
    • 数据库模型文件展示(models.py)
    from . import db
    
    # 时刻与评论数量关系模型
    class HourCount(db.Model):
        __tablename__ = 'db_hour_count'
        id = db.Column(db.Integer,primary_key=True,autoincrement=True)
        hour = db.Column(db.Integer,nullable=False)
        count = db.Column(db.Integer,nullable=False)
    
    # 评价星级与评价数量关系模型
    class StarCount(db.Model):
        __tablename__ = 'db_star_count'
        id = db.Column(db.Integer,primary_key=True,autoincrement=True)
        star = db.Column(db.Integer,nullable=False)
        count = db.Column(db.Integer,nullable=False)
    
    # 评分均值与随时间关系模型
    class StarAvg(db.Model):
        __tablename__ = 'db_star_avg'
        id = db.Column(db.Integer,primary_key=True,autoincrement=True)
        hour = db.Column(db.Integer,nullable=False)
        star_avg = db.Column(db.Float,nullable=False)
    
    
    
    • 配置文件代码展示(config.py)
    
    class Config(object):
        SECRET_KEY = 'ma5211314'
        SQLALCHEMY_DATABASE_URI = 'mysql://root:123456@localhost:3306/cateye'
        SQLALCHEMY_TRACK_MODIFICATIONS = True
    
    class DevelopmentConfig(Config):
        DEBUG = True
    
    class ProjectConfig(Config):
        pass
        
    # 采用映射方式方便后续调用配置类
    config_map = {
        'develop':DevelopmentConfig,
        'project':ProjectConfig
    }
    
    
    • 主工程目录代码展示(api_1_0/init.py)
    from flask import Flask
    from flask_sqlalchemy import SQLAlchemy
    import pymysql
    from config import config_map
    # python3的pymysql取代了mysqldb库 为了防止出现 ImportError: No module named ‘MySQLdb’的错误
    pymysql.install_as_MySQLdb()
    
    db = SQLAlchemy()
    # 采用工厂模式创建app实例
    def create_app(mode='develop'):
        app = Flask(__name__)
        # 加载配置类
        config = config_map[mode]
        app.config.from_object(config)
    
        # 加载数据库
        db.init_app(app)
    
        # 导入蓝图
        from . import view
        app.register_blueprint(view.blue,url_prefix='/show')
    
        return app
    
    
    • 主程序文件代码展示(manager.py)
    from api_1_0 import create_app,db
    from flask_script import Manager
    from flask_migrate import Migrate,MigrateCommand
    from flask import render_template
    
    app = create_app()
    
    manager = Manager(app)
    Migrate(app,db)
    
    manager.add_command('db',MigrateCommand)
    
    # 首页
    @app.route('/')
    def index():
        return render_template('index.html')
    
    if __name__ == '__main__':
        manager.run()
    
    
    • 视图文件代码展示(api_1_0/views/_init_.py,show.py)

    _init_.py

    from flask import Blueprint
    # 为了在主程序运行时能够加载到模型类
    from api_1_0 import model
    blue = Blueprint('show',__name__)
    
    # 导入定义的视图函数
    from . import show
    

    show.py

    from . import blue
    from api_1_0.models import HourCount,StarCount,StarAvg
    from flask import render_template
    
    # 词云图
    @blue.route('/drawCloud')
    def drawCloud():
        return render_template('drawCloud.html')
    
    # 评论数量随时间的变化折线图和评论均值随时间的变化折线图
    @blue.route('/drawLine')
    def drawLine():
        hour_count = HourCount.query.all()
        hour_star_avg = StarAvg.query.all()
        # 构造折线图所需数据 两个数组
        hour = [i.hour for i in hour_count]
        count = [i.count for i in hour_count]
        star_avg = [i.star_avg for i in hour_star_avg]
    
        return render_template('drawLine.html',**locals())
    
    # 不同星级评价的数量占比图
    @blue.route('/drawPie')
    def drawPie():
        star_count = StarCount.query.all()
        # 构造画饼图所需数据格式数组嵌套字典
        data = [{'name':i.star,'value':i.count} for i in star_count]
        return render_template('drawPie.html',**locals())
    
    
    
    • 主页展示(index.html)

    主页简单创建了三个超链接指向对应的图表

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>首页说明</title>
        <style>
            .container{
                width: 100%;
                height: 600px;
                padding: 40px;
                line-height: 60px;
            }
            ul{
                margin: auto;
                width: 60%;
            }
        </style>
    </head>
    <body>
        <div class="container">
            <ul>
                <li><a href="http://127.0.0.1:5000/show/drawCloud" target="_blank"><h3>评论标题词云                                                                                                                                                                                </h3></a></li>
                <li><a href="http://127.0.0.1:5000/show/drawLine" target="_blank"><h3>评论数量随时间的变化折线图&评论均值随时间的变化折线图</h3></a></li>
                <li><a href="http://127.0.0.1:5000/show/drawPie" target="_blank"><h3>不同星级评价的数量占比图</h3></a></li>
            </ul>
        </div>
    </body>
    </html>
    

    • 模板文件代码展示(drawCloud.html,drawLine.htm,drawPie.html)

    drawCloud.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>词云图</title>
        <style>
            .container{
                width: 1000px;
                margin: auto;
                padding-top: 50px;
            }
            img{
                width: 800px;
                height: 600px;
            }
    
        </style>
    </head>
    <body>
    <div class="container">
    	# 图片地址为数据分析中生成的保存的词云图
        <img src="../static/images/wordCount.jpg">
    </div>
    </body>
    </html>
    

    在这里插入图片描述

    结论:
    除了电影和一些常用词之后,英雄、历史、战争的词频最高,所以可以初步判断八佰是以历史战争为题材的电影

    drawLine.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>评论数量随时间的变化折线图和评论均值随时间的变化折线图</title>
        <script src="../static/js/echarts.min.js"></script>
        <script src="../static/theme/vintage.js"></script>
        <style>
            .chart_group{
                width: 100%;
                display: flex;
                justify-content: space-between;
                padding: 50px;
                box-sizing: border-box;
            }
        </style>
    </head>
    <body>
    <div class="chart_group">
        <div class="chat1" style="width: 700px;height: 500px"></div>
        <div class="chat2" style="width: 700px;height: 500px"></div>
    </div>
    <script>
        var myCharts1 = echarts.init(document.querySelector('.chat1'),'vintage')
        var myCharts2 = echarts.init(document.querySelector('.chat2'),'vintage')
        var hour = {{ hour|tojson }}
        var count = {{ count|tojson }}
        var star_avg = {{star_avg|tojson }}
    
    function getOptions(category,data,title_text,desc){
            var option  = {
            title:{
                text:title_text,
                textStyle:{
                    fontFamily:'楷体',
                    fontSize:21
                }
            },
            xAxis:{
                type:'category',
                data: category,
                axisLabel:{
                    interval:0,
                    rotate:40,
                    margin:10
                }
            },
            yAxis:{
                type:'value',
                scale:true
            },
            legend:{
                name:[desc],
                top:20
            },
            tooltip:{
              trigger:'axis',
              triggerOn:'mousemove',
              formatter:function(arg){
                  return '评论时刻:'+arg[0].name+':00'+'<br>'+'评论数量:'+arg[0].value
              }
            },
            series:[
                {
                    name:desc,
                    type:'line',
                    data:data,
                    label:{
                        show:true
                    },
                    smooth:true,
                    markLine:{
                        data:[
                            {
                                name:'平均值',
                                type:'average',
                                label: {
                                    show:true,
                                    formatter:function(arg)
                                    {
                                        return arg.name+':\n'+arg.value
                                    }
                                }
                            }
                        ]
                    },
                    markPoint:{
                        data:[
                            {
                                name:'最大值',
                                type:'max',
                                symbolSize:[40,40],
                                symbolOffset:[0,-20],
                                label:{
                                    show:true,
                                    formatter:function (arg)
                                    {
                                        return arg.name
                                    }
                                }
                            },
                            {
                                name:'最小值',
                                type:'min',
                                symbolSize:[40,40],
                                symbolOffset:[0,-20],
                                label:{
                                    show:true,
                                    formatter:function (arg)
                                    {
                                        return arg.name
                                    }
                                }
                            }
                        ]
                    }
                }
            ]
        }
        return option
        }
    
        var option1 = getOptions(hour,count,'评论数量随时间的变化','评论数量')
        var option2 = getOptions(hour,star_avg,'评论均值随时间的变化','评论均值')
        myCharts1.setOption(option1)
        myCharts2.setOption(option2)
    </script>
    </body>
    </html>
    

    在这里插入图片描述
    结论:
    影迷们大都在21点至凌晨1点左右观影评论,可见影迷们大都是夜猫子,而凌晨1点至中午11点影评的评分普遍低于平均分,熬夜和中午吃饭之前影迷们的大都处在一个心情不大好的状态,所以一点要少熬夜多吃饭

    draw.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>不同星级评价的数量占比图</title>
        <script src="../static/js/echarts.min.js"></script>
        <script src="../static/theme/vintage.js"></script>
    </head>
    <body>
    <div class="chat" style="width: 800px;height: 600px;margin: auto"></div>
    <script>
        var myCharts = echarts.init(document.querySelector('.chat'),'vintage')
        var data = {{ data|tojson }}
        var option = {
            title:{
                text:'不同星级评价的数量占比',
                textStyle:{
                    fontFamily:'楷体',
                    fontSize:21
                }
            },
            legend:{
                name:['星级'],
                left:40,
                bottom:40,
                orient:'verticals',
                formatter:function(arg)
                {
                    return arg+'星'
                }
            },
            tooltip:{
              trigger:'item',
              triggerOn:'mousemove',
              formatter:function(arg)
              {
                  return '评价星级:'+arg.name+'星'+'<br>'+'评价数量:'+arg.value+'<br>'+'评价占比:'+arg.percent+"%"
              },
            },
            series:[
                {
                    name:'星级',
                    type:'pie',
                    data:data,
                    label:{
                        show:true,
                        formatter:function (arg)
                        {
                            return arg.name+'星'
                        }
                    },
                    {#roseType:'radius',#} //南丁格尔玫瑰图
                    radius:['50%','80%'],
                    selectedMode:'multiple',
                    selectedOffset:20
                }
            ]
        }
        myCharts.setOption(option)
    </script>
    </body>
    </html>
    

    在这里插入图片描述

    结论:
    影迷们对八佰这部电影的评价普遍很高,5星和4星评论占总评分的80%左右,可见这部电影的受欢迎程度。

    以下是项目源码,希望能够帮助你们,如有疑问,下方评论
    flask项目代码链接

    展开全文
  • 零基础学Python爬虫数据分析与可视化从入门到精通作者:孟兵,李杰臣出版日期:2020年11月文件大小:49.45M支持设备:¥60.00在线试读适用客户端:言商书局iPad/iPhone客户端:下载 Android客户端:下载PC客户端:...

    零基础学Python爬虫、数据分析与可视化从入门到精通

    作者:孟兵,李杰臣

    出版日期:2020年11月

    文件大小:49.45M

    支持设备:

    ¥60.00在线试读

    适用客户端:

    言商书局

    iPad/iPhone客户端:下载 Android客户端:下载PC客户端:下载更多详情:查看

    ?对图书下载、阅读卡购买有疑问:立即进入帮助中心>>

    图书简介

    目录

    Python语言功能强大而灵活,具有很强的扩展性,同时它的语法又相对简洁易懂,没有编程基础的普通办公人员经过适当的学习也能轻松上手。本书以Python语言为工具,从编程新手的角度和日常办公的需求出发,深入浅出地讲解如何通过Python编程高效地完成数据的获取、处理、分析与可视化。

    全书共13章。第1章和第2章主要讲解Python编程环境的搭建和Python语言的基础语法知识。第3~6章以数据处理与分析为主题,讲解NumPy模块和pandas模块的基本用法和实际应用。第7~9章以数据获取为主题,由浅入深地讲解如何通过编写爬虫程序从网页上采集数据,并保存到数据库中。第10章主要讲解自然语言处理技术在文本分词中的应用。第11章和第12章以数据可视化为主题,讲解如何使用Matplotlib模块和pyecharts模块绘制图表。第13章通过量化金融案例对前面所学的知识进行了综合应用。

    本书适合想要提高数据处理和分析效率的职场人士和办公人员阅读,也可供Python编程爱好者参考。

    前言

    如何获取学习资源

    第1章 Python快速上手

    1.1 Python编程环境的搭建

    1.2 Python的模块

    1.2.1 初识模块

    1.2.2 模块的安装

    第2章 Python的基础语法知识

    2.1 变量

    2.2 数据类型:数字与字符串

    2.2.1 数字

    2.2.2 字符串

    2.2.3 数据类型的查询

    2.2.4 数据类型的转换

    2.3 数据类型:列表、字典、元组与集合

    2.3.1 列表

    2.3.2 字典

    2.3.3 元组和集合

    2.4 运算符

    2.4.1 算术运算符和字符串运算符

    2.4.2 比较运算符

    2.4.3 赋值运算符

    2.4.4 逻辑运算符

    2.5 编码基本规范

    2.5.1 缩进

    2.5.2 注释

    2.6 控制语句

    2.6.1 if语句

    2.6.2 for语句

    2.6.3 while语句

    2.6.4 控制语句的嵌套

    2.7 函数

    2.7.1 内置函数

    2.7.2 自定义函数

    2.8 模块的导入

    2.8.1 import语句导入法

    2.8.2 from语句导入法

    第3章 数组的存储和处理——NumPy模块

    3.1 创建数组

    3.1.1 使用array()函数创建数组

    3.1.2 创建等差数组

    3.1.3 创建随机数组

    3.2 查看数组的属性

    3.3 选取数组元素

    3.3.1 一维数组的元素选取

    3.3.2 二维数组的元素选取

    3.4 数组的重塑与转置

    3.4.1 一维数组的重塑

    3.4.2 多维数组的重塑

    3.4.3 数组的转置

    3.5 数组的处理

    3.5.1 添加数组元素

    3.5.2 删除数组元素

    3.5.3 处理数组的缺失值

    3.5.4 处理数组的重复值

    3.5.5 拼接数组

    3.5.6 拆分数组

    3.6 数组的运算

    3.6.1 数组之间的四则运算

    3.6.2 数组元素的统计运算

    第4章 数据的简单处理——pandas模块入门

    4.1 数据结构

    4.1.1 Series对象

    4.1.2 DataFrame对象

    4.2 读取数据

    4.2.1 读取Excel工作簿数据

    4.2.2 读取csv文件数据

    4.3 查看数据

    4.3.1 查看数据的前几行

    4.3.2 查看数据的行数和列数

    4.3.3 查看数据的类型

    4.4 选择数据

    4.4.1 选择行数据

    4.4.2 选择列数据

    4.4.3 同时选择行列数据

    4.5 修改行标签和列标签

    第5章 数据的高级处理——pandas模块进阶

    5.1 数据的查找和替换

    5.1.1 查找数据

    5.1.2 替换数据

    5.2 数据的处理

    5.2.1 插入数据

    5.2.2 删除数据

    5.2.3 处理缺失值

    5.2.4 处理重复值

    5.2.5 排序数据

    5.2.6 筛选数据

    5.3 数据表的处理

    5.3.1 转置数据表的行列

    5.3.2 将数据表转换为树形结构

    5.3.3 数据表的拼接

    5.4 数据的运算

    5.4.1 数据的统计运算

    5.4.2 获取数值分布情况

    5.4.3 计算相关系数

    5.4.4 分组汇总数据

    5.4.5 创建数据透视表

    5.5 案例:获取并分析股票历史数据

    第6章 使用Python进行数据分析

    6.1 相关性分析

    6.1.1 获取股价数据

    6.1.2 合并股价数据

    6.1.3 股价数据相关性分析

    6.2 假设检验

    6.3 方差分析

    6.3.1 方差分析的基本步骤

    6.3.2 单因素方差分析的代码实现

    6.3.3 双因素方差分析的代码实现

    6.3.4 利用第三方模块快速完成方差分析

    6.4 描述性统计分析

    6.4.1 描述性统计指标的计算

    6.4.2 数据的分布状态分析

    6.4.3 数据的频数和频率分析

    6.5 线性回归分析

    6.5.1 线性回归分析的数学原理

    6.5.2 线性回归分析的思路

    6.5.3 广告费与销量的一元线性回归分析

    6.5.4 不同渠道的广告费与销量的多元线性回归分析

    第7章 Python爬虫基础

    7.1 认识网页结构

    7.1.1 查看网页的源代码

    7.1.2 网页结构的组成

    7.1.3 百度新闻页面结构剖析

    7.2 requests模块

    7.2.1 requests模块获取数据的方式

    7.2.2 get()函数的参数介绍

    7.3 案例:爬取豆瓣电影动画排行榜

    7.4 正则表达式

    7.4.1 正则表达式基础

    7.4.2 用正则表达式提取数据

    7.5 BeautifulSoup模块

    7.5.1 实例化BeautifulSoup对象

    7.5.2 用BeautifulSoup对象定位标签

    7.5.3 从标签中提取文本内容和属性值

    7.6 XPath表达式

    7.6.1 实例化etree对象

    7.6.2 用XPath表达式定位标签并提取数据

    7.6.3 快速获取标签节点的XPath表达式

    7.7 数据清洗

    7.8 案例:爬取当当网的图书销售排行榜

    第8章 Python爬虫进阶

    8.1 Selenium模块基础

    8.1.1 Selenium模块的安装与基本用法

    8.1.2 Selenium模块的标签定位

    8.1.3 Selenium模块的标签操作

    8.2 Selenium模块进阶

    8.2.1 模拟鼠标操作

    8.2.2

    展开全文
  • Python爬虫以及数据可视化分析

    万次阅读 多人点赞 2020-12-25 17:43:30
    Python爬虫以及数据可视化分析之B站动漫排行榜信息爬取分析 简书地址:https://www.jianshu.com/u/40ac87350697 简单几步,通过Python对B站番剧排行数据进行爬取,并进行可视化分析 源码文件可以参考Github上传的...

    Python爬虫以及数据可视化分析之Bilibili动漫排行榜信息爬取分析

    简书地址:https://www.jianshu.com/u/40ac87350697

    简单几步,通过Python对B站番剧排行数据进行爬取,并进行可视化分析

    源码文件可以参考Github上传的项目:https://github.com/Lemon-Sheep/Py/tree/master

    下面,我们开始吧!

    PS: 作为Python爬虫初学者,如有不正确的地方,望各路大神不吝赐教[抱拳]

    本项目将会对B站番剧排行的数据进行网页信息爬取以及数据可视化分析
    image.png

    首先,准备好相关库

    requests、pandas、BeautifulSoup、matplotlib等

    因为这是第三方库,所以我们需要额外下载
    下载有两种方法(以requests为例,其余库的安装方法类似):

    (一)在命令行输入

    前提:装了pip( Python 包管理工具,提供了对Python 包的查找、下载、安装、卸载的功能。 )

    pip install requests

    (二)通过PyCharm下载

    第一步:编译器左上角File–>Settings…
    image.png
    第二步:找到Project Interpreter 点击右上角加号按钮,弹出界面上方搜索库名:requests,点击左下角Install ,当提示successfully时,即安装完成。
    2.png

    image.png

    准备工作做好后,开始项目的实行

    一、获取网页内容

    def get_html(url):
        try:
            r = requests.get(url)             # 使用get来获取网页数据
            r.raise_for_status()              # 如果返回参数不为200,抛出异常
            r.encoding = r.apparent_encoding  # 获取网页编码方式
            return r.text                     # 返回获取的内容
        except:
            return '错误'
    

    我们来看爬取情况,是否有我们想要的内容:

    def main():
        url = 'https://www.bilibili.com/v/popular/rank/bangumi'    # 网址
        html = get_html(url)                                       # 获取返回值
        print(html)                                              # 打印
    
    if __name__ == '__main__':                        #入口
        main()
    

    爬取结果如下图所示:
    image.png
    成功!

    二、信息解析阶段:

    第一步,先构建BeautifulSoup实例

    soup = BeautifulSoup(html, 'html.parser') # 指定BeautifulSoup的解析器
    

    第二步,初始化要存入信息的容器

    # 定义好相关列表准备存储相关信息
        TScore = []  # 综合评分
        name = []  # 动漫名字
        play= []  # 播放量
        review = []  # 评论数
        favorite= []  # 收藏数
    

    第三步,开始信息整理
    我们先获取番剧的名字,并将它们先存进列表中

    # ********************************************  动漫名字存储
        for tag in soup.find_all('div', class_='info'):
            # print(tag)
            bf = tag.a.string
            name.append(str(bf))
        print(name)
    

    此处我们用到了beautifulsoup的find_all()来进行解析。在这里,find_all()的第一个参数是标签名,第二个是标签中的class值(注意下划线哦(class_=‘info’))。

    我们在网页界面按下F12,就能看到网页代码,找到相应位置,就能清晰地看见相关信息:
    image.png

    接着,我们用几乎相同的方法来对综合评分、播放量,评论数和收藏数来进行提取

    # ********************************************  播放量存储
        for tag in soup.find_all('div', class_='detail'):
            # print(tag)
            bf = tag.find('span', class_='data-box').get_text()
            # 统一单位为‘万’
            if '亿' in bf:
                num = float(re.search(r'\d(.\d)?', bf).group()) * 10000
                # print(num)
                bf = num
            else:
                bf = re.search(r'\d*(\.)?\d', bf).group()
            play.append(float(bf))
        print(play)
        # ********************************************  评论数存储
        for tag in soup.find_all('div', class_='detail'):
            # pl = tag.span.next_sibling.next_sibling
            pl = tag.find('span', class_='data-box').next_sibling.next_sibling.get_text()
            # *********统一单位
            if '万' not in pl:
                pl = '%.1f' % (float(pl) / 10000)
                # print(123, pl)
            else:
                pl = re.search(r'\d*(\.)?\d', pl).group()
            review.append(float(pl))
        print(review)
        # ********************************************  收藏数
        for tag in soup.find_all('div', class_='detail'):
            sc = tag.find('span', class_='data-box').next_sibling.next_sibling.next_sibling.next_sibling.get_text()
            sc = re.search(r'\d*(\.)?\d', sc).group()
            favorite.append(float(sc))
        print(favorite)
        # ********************************************  综合评分
        for tag in soup.find_all('div', class_='pts'):
            zh = tag.find('div').get_text()
            TScore.append(int(zh))
        print('综合评分', TScore)
    

    其中有个.next_sibling是用于提取同级别的相同标签信息,如若没有这个方法,当它找到第一个’span’标签之后,就不会继续找下去了(根据具体情况来叠加使用此方法);
    还用到了正则表达式来提取信息(需要导入库‘re’)

    最后我们将提取的信息,存进excel表格之中,并返回结果集

    # 存储至excel表格中
        info = {'动漫名': name, '播放量(万)': play, '评论数(万)': review,'收藏数(万)': favorite, '综合评分': TScore}
        dm_file = pandas.DataFrame(info)
        dm_file.to_excel('Dongman.xlsx', sheet_name="动漫数据分析")
        # 将所有列表返回
        return name, play, review, favorite, TScore
    

    我们可以打开文件看一看存储的信息格式(双击打开)
    image.png
    image.png
    成功!

    三、数据可视化分析

    我们先做一些基础设置
    要先准备一个文件: STHeiti Medium.ttc [注意存放在项目中的位置]
    image.png

    my_font = font_manager.FontProperties(fname='./data/STHeiti Medium.ttc')  # 设置中文字体(图表中能显示中文)
    
     # 为了坐标轴上能显示中文
        plt.rcParams['font.sans-serif'] = ['SimHei']
        plt.rcParams['axes.unicode_minus'] = False
    
        dm_name = info[0]  # 番剧名
        dm_play = info[1]  # 番剧播放量
        dm_review = info[2]  # 番剧评论数
        dm_favorite = info[3]  # 番剧收藏数
        dm_com_score = info[4]  # 番剧综合评分
        # print(dm_com_score)
    

    然后,开始使用matplot来绘制图形,实现数据可视化分析
    文中有详细注释,这里就不再赘述了,聪明的你一定一看就懂了~

    # **********************************************************************综合评分和播放量对比
        # *******综合评分条形图
        fig, ax1 = plt.subplots()
        plt.bar(dm_name, dm_com_score, color='red')  #设置柱状图
        plt.title('综合评分和播放量数据分析', fontproperties=my_font)  # 表标题
        ax1.tick_params(labelsize=6)  
        plt.xlabel('番剧名')  # 横轴名
        plt.ylabel('综合评分')  # 纵轴名
        plt.xticks(rotation=90, color='green')  # 设置横坐标变量名旋转度数和颜色
    
        # *******播放量折线图
        ax2 = ax1.twinx()  # 组合图必须加这个
        ax2.plot(dm_play, color='cyan')  # 设置线粗细,节点样式
        plt.ylabel('播放量')  # y轴
    
        plt.plot(1, label='综合评分', color="red", linewidth=5.0)  # 图例
        plt.plot(1, label='播放量', color="cyan", linewidth=1.0, linestyle="-")  # 图例
        plt.legend()
    
        plt.savefig(r'E:1.png', dpi=1000, bbox_inches='tight')  #保存至本地
    
        plt.show()
    

    来看看效果

    有没有瞬间就感觉高~大~上~~了(嘿嘿~)

    然后我们用相同的方法来多绘制几个对比图:

    # **********************************************************************评论数和收藏数对比
        # ********评论数条形图
        fig, ax3 = plt.subplots()
        plt.bar(dm_name, dm_review, color='green')
        plt.title('番剧评论数和收藏数分析')
        plt.ylabel('评论数(万)')
        ax3.tick_params(labelsize=6)
        plt.xticks(rotation=90, color='green')
    
        # *******收藏数折线图
        ax4 = ax3.twinx()  # 组合图必须加这个
        ax4.plot(dm_favorite, color='yellow')  # 设置线粗细,节点样式
        plt.ylabel('收藏数(万)')
    
        plt.plot(1, label='评论数', color="green", linewidth=5.0)
        plt.plot(1, label='收藏数', color="yellow", linewidth=1.0, linestyle="-")
        plt.legend()
        plt.savefig(r'E:2.png', dpi=1000, bbox_inches='tight')
    
        # **********************************************************************综合评分和收藏数对比
        # *******综合评分条形图
        fig, ax5 = plt.subplots()
        plt.bar(dm_name, dm_com_score, color='red')
        plt.title('综合评分和收藏数量数据分析')
        plt.ylabel('综合评分')
        ax5.tick_params(labelsize=6)
        plt.xticks(rotation=90, color='green')
    
        # *******收藏折线图
        ax6 = ax5.twinx()  # 组合图必须加这个
        ax6.plot(dm_favorite, color='yellow')  # 设置线粗细,节点样式
        plt.ylabel('收藏数(万)')
        plt.plot(1, label='综合评分', color="red", linewidth=5.0)
        plt.plot(1, label='收藏数', color="yellow", linewidth=1.0, linestyle="-")
        plt.legend()
    
        plt.savefig(r'E:3.png', dpi=1000, bbox_inches='tight')
    
        # **********************************************************************播放量和评论数对比
        # *******播放量条形图
        fig, ax7 = plt.subplots()
        plt.bar(dm_name, dm_play, color='cyan')
        plt.title('播放量和评论数 数据分析')
        plt.ylabel('播放量(万)')
        ax7.tick_params(labelsize=6)
        plt.xticks(rotation=90, color='green')
    
        # *******评论数折线图
        ax8 = ax7.twinx()  # 组合图必须加这个
        ax8.plot(dm_review, color='green')  # 设置线粗细,节点样式
        plt.ylabel('评论数(万)')
        plt.plot(1, label='播放量', color="cyan", linewidth=5.0)
        plt.plot(1, label='评论数', color="green", linewidth=1.0, linestyle="-")
        plt.legend()
        plt.savefig(r'E:4.png', dpi=1000, bbox_inches='tight')
    
        plt.show()
    

    我们来看看最终效果
    image.png
    image.png

    Nice!很完美~ 大家可以根据自己的想法按照相同的方法进行数据组合分析。

    最后,附上全部代码

    import re
    import pandas
    import requests
    from bs4 import BeautifulSoup
    import matplotlib.pyplot as plt
    from matplotlib import font_manager
    
    
    def get_html(url):
        try:
            r = requests.get(url)  # 使用get来获取网页数据
            r.raise_for_status()  # 如果返回参数不为200,抛出异常
            r.encoding = r.apparent_encoding  # 获取网页编码方式
            return r.text  # 返回获取的内容
        except:
            return '错误'
    
    
    def save(html):
        # 解析网页
        soup = BeautifulSoup(html, 'html.parser')  # 指定Beautiful的解析器为“html.parser”
    
        with open('./data/B_data.txt', 'r+', encoding='UTF-8') as f:
            f.write(soup.text)
    
        # 定义好相关列表准备存储相关信息
        TScore = []  # 综合评分
        name = []  # 动漫名字
        bfl = []  # 播放量
        pls = []  # 评论数
        scs = []  # 收藏数
    
        # ********************************************  动漫名字存储
        for tag in soup.find_all('div', class_='info'):
            # print(tag)
            bf = tag.a.string
            name.append(str(bf))
        print(name)
    
        # ********************************************  播放量存储
        for tag in soup.find_all('div', class_='detail'):
            # print(tag)
            bf = tag.find('span', class_='data-box').get_text()
            # 统一单位为‘万’
            if '亿' in bf:
                num = float(re.search(r'\d(.\d)?', bf).group()) * 10000
                # print(num)
                bf = num
            else:
                bf = re.search(r'\d*(\.)?\d', bf).group()
            bfl.append(float(bf))
        print(bfl)
        # ********************************************  评论数存储
        for tag in soup.find_all('div', class_='detail'):
            # pl = tag.span.next_sibling.next_sibling
            pl = tag.find('span', class_='data-box').next_sibling.next_sibling.get_text()
            # *********统一单位
            if '万' not in pl:
                pl = '%.1f' % (float(pl) / 10000)
                # print(123, pl)
            else:
                pl = re.search(r'\d*(\.)?\d', pl).group()
            pls.append(float(pl))
        print(pls)
        # ********************************************  收藏数
        for tag in soup.find_all('div', class_='detail'):
            sc = tag.find('span', class_='data-box').next_sibling.next_sibling.next_sibling.next_sibling.get_text()
            sc = re.search(r'\d*(\.)?\d', sc).group()
            scs.append(float(sc))
        print(scs)
        # ********************************************  综合评分
        for tag in soup.find_all('div', class_='pts'):
            zh = tag.find('div').get_text()
            TScore.append(int(zh))
        print('综合评分', TScore)
    
        # 存储至excel表格中
        info = {'动漫名': name, '播放量(万)': bfl, '评论数(万)': pls, '收藏数(万)': scs, '综合评分': TScore}
        dm_file = pandas.DataFrame(info)
        dm_file.to_excel('Dongman.xlsx', sheet_name="动漫数据分析")
        # 将所有列表返回
        return name, bfl, pls, scs, TScore
    
    
    def view(info):
        my_font = font_manager.FontProperties(fname='./data/STHeiti Medium.ttc')  # 设置中文字体(图标中能显示中文)
        dm_name = info[0]  # 番剧名
        dm_play = info[1]  # 番剧播放量
        dm_review = info[2]  # 番剧评论数
        dm_favorite = info[3]  # 番剧收藏数
        dm_com_score = info[4]  # 番剧综合评分
        # print(dm_com_score)
    
        # 为了坐标轴上能显示中文
        plt.rcParams['font.sans-serif'] = ['SimHei']
        plt.rcParams['axes.unicode_minus'] = False
    
        # **********************************************************************综合评分和播放量对比
        # *******综合评分条形图
        fig, ax1 = plt.subplots()
        plt.bar(dm_name, dm_com_score, color='red')  #设置柱状图
        plt.title('综合评分和播放量数据分析', fontproperties=my_font)  # 表标题
        ax1.tick_params(labelsize=6)
        plt.xlabel('番剧名')  # 横轴名
        plt.ylabel('综合评分')  # 纵轴名
        plt.xticks(rotation=90, color='green')  # 设置横坐标变量名旋转度数和颜色
    
        # *******播放量折线图
        ax2 = ax1.twinx()  # 组合图必须加这个
        ax2.plot(dm_play, color='cyan')  # 设置线粗细,节点样式
        plt.ylabel('播放量')  # y轴
    
        plt.plot(1, label='综合评分', color="red", linewidth=5.0)  # 图例
        plt.plot(1, label='播放量', color="cyan", linewidth=1.0, linestyle="-")  # 图例
        plt.legend()
    
        plt.savefig(r'E:1.png', dpi=1000, bbox_inches='tight')  #保存至本地
    
        # plt.show()
    
        # **********************************************************************评论数和收藏数对比
        # ********评论数条形图
        fig, ax3 = plt.subplots()
        plt.bar(dm_name, dm_review, color='green')
        plt.title('番剧评论数和收藏数分析')
        plt.ylabel('评论数(万)')
        ax3.tick_params(labelsize=6)
        plt.xticks(rotation=90, color='green')
    
        # *******收藏数折线图
        ax4 = ax3.twinx()  # 组合图必须加这个
        ax4.plot(dm_favorite, color='yellow')  # 设置线粗细,节点样式
        plt.ylabel('收藏数(万)')
    
        plt.plot(1, label='评论数', color="green", linewidth=5.0)
        plt.plot(1, label='收藏数', color="yellow", linewidth=1.0, linestyle="-")
        plt.legend()
        plt.savefig(r'E:2.png', dpi=1000, bbox_inches='tight')
    
        # **********************************************************************综合评分和收藏数对比
        # *******综合评分条形图
        fig, ax5 = plt.subplots()
        plt.bar(dm_name, dm_com_score, color='red')
        plt.title('综合评分和收藏数量数据分析')
        plt.ylabel('综合评分')
        ax5.tick_params(labelsize=6)
        plt.xticks(rotation=90, color='green')
    
        # *******收藏折线图
        ax6 = ax5.twinx()  # 组合图必须加这个
        ax6.plot(dm_favorite, color='yellow')  # 设置线粗细,节点样式
        plt.ylabel('收藏数(万)')
        plt.plot(1, label='综合评分', color="red", linewidth=5.0)
        plt.plot(1, label='收藏数', color="yellow", linewidth=1.0, linestyle="-")
        plt.legend()
    
        plt.savefig(r'E:3.png', dpi=1000, bbox_inches='tight')
    
        # **********************************************************************播放量和评论数对比
        # *******播放量条形图
        fig, ax7 = plt.subplots()
        plt.bar(dm_name, dm_play, color='cyan')
        plt.title('播放量和评论数 数据分析')
        plt.ylabel('播放量(万)')
        ax7.tick_params(labelsize=6)
        plt.xticks(rotation=90, color='green')
    
        # *******评论数折线图
        ax8 = ax7.twinx()  # 组合图必须加这个
        ax8.plot(dm_review, color='green')  # 设置线粗细,节点样式
        plt.ylabel('评论数(万)')
        plt.plot(1, label='播放量', color="cyan", linewidth=5.0)
        plt.plot(1, label='评论数', color="green", linewidth=1.0, linestyle="-")
        plt.legend()
        plt.savefig(r'E:4.png', dpi=1000, bbox_inches='tight')
    
        plt.show()
    
    
    def main():
        url = 'https://www.bilibili.com/v/popular/rank/bangumi'  # 网址
        html = get_html(url)  # 获取返回值
        # print(html)
        info = save(html)
        view(info)
    
    
    if __name__ == '__main__':
        main()
    

    关于图表的分析和得出的结论,这里就不描述了,一千个读者就有一千个哈姆雷特,每个人有每个人的分析描述方法,相信你们能有更加透彻的见解分析。

    以上就是关于爬虫以及数据可视化分析的内容,希望能帮到你们!
    伙伴们可以到github上查看源码文件:https://github.com/Lemon-Sheep/Py/tree/master

    喜欢记得点个赞哦~

    展开全文
  • 全网最全python爬虫数据分析资源整理

    千次阅读 多人点赞 2021-04-29 14:08:36
    你为什么需要数据分析能力? 第一模块:数据分析基础篇 (16讲) 01丨数据分析全景图及修炼指南 02丨学习数据挖掘的最佳路径是什么? 03丨Python基础语法:开始你的Python之旅 04丨Python科学计算:用NumPy快速处理...
  • 爬取全国城市名 聚焦爬虫是指在拿到一个网页的响应后,对这个网页复杂的信息进行聚焦式的提取,这个提取关键信息的过程往往是爬虫中最核心的部分,我们也把这个提取的过程叫做数据解析,数据解析中最常用的办法有三...
  • Python爬虫实战+数据分析+数据可视化(猫眼电影)

    千次阅读 多人点赞 2021-01-16 16:26:48
    2、本爬虫爬取的数据存入到MongoDB数据库中 3、爬虫代码中有详细注释 代码展示 import re import time from pymongo import MongoClient import requests from lxml import html from urllib import parse class ...
  • Python爬虫以及数据可视化分析

    千次阅读 2020-12-27 14:12:59
    PS: 作为Python爬虫初学者,如有不正确的地方,望各路大神不吝赐教[抱拳] 本项目将会对B站番剧排行的数据进行网页信息爬取以及数据可视化分析 首先,准备好相关库 requests、pandas、BeautifulSoup、...
  • 2、本爬虫爬取的数据存入到MongoDB数据库中 3、爬虫代码中有详细注释 4、爬虫爬取的美食是以无锡为例 5、博客末尾附有源码+数据库文件 代码展示 import re import requests import json from pymongo import ...
  • python爬虫案例汇总

    2021-02-04 06:17:24
    python爬虫入门之request模块爬虫爬虫概念爬虫呢,就是编写一个程序去模仿上网过程,让其去互联网上获取数据的过程。爬虫分类爬虫大致分为四种:通用爬虫:爬取整个页面。聚焦爬虫:只爬取页面中你需要的部分内容。...
  • 项目描述基础环境:python + flask + vue + element-ui + echartspython_spiders -- 爬虫后台项目python_spiders_web -- 爬虫前台项目运行环境python 3.8.3 + nginx + mysql项目技术(必填)Python 3.8.3 +flask+ vue ...
  • Python爬虫数据可视化总结

    千次阅读 2021-09-15 19:43:41
    工具: Python,Flask,JS,CSS,HTML,WordCloud 爬取数据并存入数据库 一.导入需要的包 from bs4 import BeautifulSoup # 网页解析,获取数据 import re # 正则表达式,进行文字匹配 import xlwt # 进行excel操作 import ...
  • python爬虫数据可视化分析

    千次阅读 2021-03-06 17:01:26
    python爬虫数据可视化分析1.前言2.数据爬取2.1定位到爬取数据2.2爬虫实现方法3.数据可视化分析3.1将短文学网的各类文章做一个统计3.2对某一类文章进行分析1.前言2.数据爬取2.1定位到爬取数据打开我们要爬取的网页...
  • Python 股票数据采集并做数据可视化(爬虫 + 数据分析) 课题介绍: 我国股票投资者数量为15975.24万户, 如此多的股民热衷于炒股, 首先抛开炒股技术不说, 那么多股票数据是不是非常难找, 找到之后是不是看着密密麻麻的...
  • Python编程基础11.1 搭建Python开发环境11.1.1 安装Python解释器11.1.2 安装Python第三方开发包21.1.3 在PyCharm里新建项目和文件31.1.4 在PyCharm里更换Python解释器51.2 实践Python基本语法51.2.1 针对基本数据...
  • 简单的来说,数据提取就是从响应中获取我们想要的数据的过程1.1 数据分类非结构化数据: html , 文本等 处理方法:正则表达式,xpath语法结构化数据:json,xml等 处理方法:转换为python数据类型2 复习JSON知识JSON...
  • 爬虫请求解析后的数据,需要保存下来,才能进行下一步的处理,一般保存数据的方式有如下几种: 文件:txt、csv、excel、json等,保存数据量小。 关系型数据库:mysql、oracle等,保存数据量大。 非关系型数据库:...
  • python爬虫爬取数据真的很简单,只要掌握这六步就好,也不复杂。以前还以为爬虫很难,结果一上手,从初学到把东西爬下来,一个小时都不到就解决了。 python爬出六部曲 第一步:安装requests库和BeautifulSoup...
  • 题目:股票数据的定向爬虫。 目标:获取美股所有股票的代码和美股个股的链接。 材料:需要网站东方财富网。 东方财富网:股票代码查询一览表 _ 股票行情 _ 东方财富网 步骤1:访问东方财富网查看股票信息...
  • python实现词云(WorldCloud)--让你的数据可视化
  • 文章目录Python基础知识Python基础变量及类型标识符和关键字格式化输出输入import导入包判断语句和循环语句条件判断语句循环语句字符串、列表、元组、字典字符串字符串的常见操作列表常见操作元组字典常用操作集合小...
  • 毕业设计:爬虫数据分析

    千次阅读 2021-01-14 09:44:30
    我选择的毕业设计题目是网络爬虫数据分析,在当下可以说很时髦,很流行。我将我的毕业设计分为四部分。每一部分都会有具体代码与注释,也会有一些外延知识的提及与讨论,欢迎大家一起学习进步。爬虫简单介绍所谓...
  • python爬虫---爬虫的数据解析的流程和解析数据的几种方式一丶爬虫数据解析概念:将一整张页面中的局部数据进行提取/解析作用:用来实现聚焦爬虫的吧实现方式:正则 (针对字符串)bs4xpath (最常用)pyquery " ...
  • 简介: 想在1天内快速搞定实时业务数据大屏吗?想用最短路径逆袭成为数据可视化大神吗?想在除了PRD外什么都没有的情况下,体验职场真人版绝境求生吗?概念:LADV是以上例子中,生成的可视化图表,均可以在DataV的...
  • Python网络爬虫实现数据爬取实例1.环境准备:2.准备User Agent:3.网站分析:4.代码编写5.完整代码 1.环境准备: 由于我无法访问到Python的官网,于是在网上随便下载了一个.exe文件,安装时可以勾选配置环境路径,就...
  • Python 气象数据分析

    2021-01-29 20:09:29
    import matplotlib.dates as mdatesfrom dateutil import parser# 把日期数据转换成 datetime 的格式# 把日期从 string 类型转化为标准的 datetime 类型day_milano = [parser.parse(x) for x in x1] #x是string# ...
  • 前言目标:获取成都近十年的人口以及房价数据分析其相关性和趋势。目标网站:国家统计局使用工具:selenium+numpyIDE:spyder代码部分from selenium import webdriverimport matplotlib.pyplot as plt#导入绘图库...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 29,283
精华内容 11,713
关键字:

python爬虫数据分析案例

python 订阅
爬虫 订阅