发布作品

    Python 汽车数据采集可视化分析系统

    简介

    运用Python爬虫技术对汽车网站进行汽车价格、品牌和销量等数据进行爬取,对爬取到的数据进行分析和加工,再利用可视化库对数据信息进行可视化分析,并以图标的形式直观地展示,为选择汽车的用户提供一个参考


    架构


    技术

    • 前端 html css js juery bootstrap echarts
    • 后端 flask
    • 爬虫 selenium,bs4
    • 数据库 mysql

    系统展示

    数据采集页面

    排行页面

    数据分析页面


    实现过程

    1. 数据采集

    销量榜页面查看

    由此可见能采集到 车名,品牌,车型,价格,销量以及排名

    开发者信息

    使用selenium 抓取网页,用bs4定位元素就可以取到相关信息

    点击销量趋势,可以看到这个款车型每个地区销量

    使用request 获取该信息

    模拟浏览器

    取到全国销量

    取到销量排行信息


    1. 数据库设计

    配置文件config.py

    class BaseConfig(object):
        """所有配置类的基类"""
        SECRET_KEY = "LOVE"
        DEBUG = True
        TESTING = False
        VISIT_TIME = 0  # 网站访问次数
        # 数据库配置
        SQLALCHEMY_DATABASE_URI = "mysql+pymysql://root:自己的MySql密码@localhost/personalwebsite"
        SQLALCHEMY_TRACK_MODIFICATIONS = False  # 是否追踪数据库的修改
    
    class ProductionConfig(BaseConfig):
        """生产环境下的配置类"""
        DEBUG = False
    
    class DevelopmentConfig(BaseConfig):
        """开发模式下的配置类"""
        DEBUG = True
        TESTING = True
    1. 网页设计
    • 注册页面

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <link rel="stylesheet" type="text/css" href="../static/css/login.css"/>
        <script src="../static/js/register.js" type="text/javascript"></script>
     
    </head>
    <body>
    <div class="login-box">
        <h2>注册</h2>
        <form action="/register" method="post">
            <div class="login-field">
                <span style="color: aqua(图片); size: 12px">账号</span>
                <input type="text" name="count" required=""/>
            </div>
            <div class="login-field">
                <spqn style="color: aqua; size: 12px">密码</spqn>
                <input type="password" name="password" required=""/>
            </div>
            <div class="login-field">
                <spqn style="color: aqua; size: 12px">确认密码</spqn>
                <input type="password" name="repassword" required=""/>
            </div>
            <input type="submit" value="提交" id="myloginlabel">
            <p style="color: #101113">已有账号?<a href="./login" style="color: rgba(22,180,166,0.58)" onclick="topggleForm();">登录</a></p>
        </form>
    </div>
    </body>
    </html>
     # 如果请求为post
        if request.method == 'POST':
            count = request.form.get('count')
            password = request.form.get('password')
            repassword = request.form.get('repassword')
            print(count, password)
            #检查信息完整
            if len(count)==0  or len(password)==0 or len(repassword)==0:
                msg = '信息不能为空'
                print(msg)
    
                return render_template('register.html',err="信息不能为空!")
            #检查用户是否存在
            if User.query.filter_by(name=count).first() is not None:
                msg = '用户已存在'
                print(msg)
                return render_template('register.html',err="用户已存在!")
            if password == repassword:
                user = User(count, password)
                #user.set_password(password)
                db.session.add(user)
                db.session.commit()
    
                return render_template('login.html', )
            else:
                msg = '两次密码不一致'
                print(msg)
                return render_template('register.html',err="两次密码不一致!")
    • 登录页面

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title>登录页面</title>
        <link rel="stylesheet" type="text/css" href="../static/css/login.css"/>
        <script src="../static/js/register.js" type="text/javascript"></script>
     
    </head>
    <body>
     
    <div class="login-box">
        <h2>入口</h2>
        <form action="/login" method="post">
            <div class="login-field">
                <span style="color: aqua; size: 12px">账号</span>
                <input type="text" name="count" required=""/>
            </div>
            <div class="login-field">
                <spqn style="color: aqua; size: 12px">密码</spqn>
                <input type="password" name="password" required=""/>
            </div>
            <input type="submit" value="点击进入" id="myloginlabel">
            <p style="color: #101113">没有账号?<a href="./register" style="color: rgba(22,180,166,0.58)" onclick="topggleForm();">注册</a></p>
        </form>
    </div>
    </body>
    </html>
    # 如果请求为post
        if request.method == 'POST':
            count = request.form.get('name')
            password = request.form.get('password')
            print(count, password)
            # 检查信息完整
            if len(count) == 0 or len(password) == 0 :
                msg = '信息不能为空'
                print(msg)
                return render_template('login.html', err="信息不能为空!")
    
            user = User.query.filter_by(name=count).first()
            #print(user)
            if not user:
    
                msg = '用户不存在'
                return render_template('login.html',err=msg)
    
            elif password != user.password:
                msg = '密码错误!'
                return render_template('login.html',err=msg)
            else:
                print("登录成功")
                return render_template('index.html')
    1. 数据分析

    读取数据

    # 执行查询并将结果转换为DataFrame
    data = pd.read_sql_query('SELECT * FROM dongchecar', engine)

    数据清洗

    #删除暂无报价
    data=data[data["cardprice"]!='暂无报价']
    data.reset_index(inplace=True)
    
    #价格拆分
    data["lowprice"]=data["cardprice"].apply(lambda  x:x.split("-")[0] )
    data["lowprice"]=data["lowprice"].apply(lambda  x:x.replace("万","") )
    data["lowprice"]=data["lowprice"].astype("float")
    
    
    # 定义大品牌的列表
    big_brands = ['奥迪', '通用', '日产', '本田', '奇瑞汽车', '现代', '吉利', '大众', '保时捷', '奔驰', '宝马', '小鹏', '捷豹', '极氪',  '特斯拉', '理想', '腾势', '蔚来', '赛力斯', '起亚', '路虎', '长城', '长安汽车', '零跑',"沃尔沃","领克","丰田","红旗","英菲尼迪","北京","福特","马自达"]
    
    # 将 'brand' 列中包含大品牌的行标记为 True
    #data['is_big_brand'] = data['cardbrand'].str.contains('|'.join(big_brands))
    # 创建新列 'big_brand',将品牌直接写成大品牌
    data['big_brand'] = data['cardbrand'].apply(lambda x: next((b for b in big_brands if b in x), x))
    
    #统计品牌数量
    brand=data["big_brand"].value_counts().reset_index()

    汽车品牌数量TOP分布图

    汽车数量TOP 20

    xiaoliang=data[data["type"]==1]
    xiaoliang=xiaoliang.head(30)
    #柱状图
    bar = (
        Bar(init_opts=opts.InitOpts(width="900px", height="400px",))
        .add_xaxis(xiaoliang["carname"].tolist())
        .add_yaxis("销售数量", xiaoliang["carsales"].tolist(), label_opts=opts.LabelOpts(is_show=False))
        .set_global_opts(
            title_opts=opts.TitleOpts(title="2023年汽车数量TOP 30"),
            xaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(rotate=45)),
        )
        # .render("guiyang_wind_count_bar_chart.html")
    )
    bar.render_notebook()

    2023年新能源汽车续航排行

    xuhang=data[data["type"]==2]
    xuhang=xuhang.head(30)
    #排序
    xuhang.sort_values(by=["carxuhang"],inplace=True,ascending=True)
    #  创建横向条形图
    bar_chart = (
        Bar(init_opts=opts.InitOpts(width="900px", height="600px",))
        .add_yaxis("续航里程",xuhang["carxuhang"].tolist())
        .add_xaxis( xuhang["carname"].tolist())
        
        .reversal_axis()  # 设置为水平显示
        .set_global_opts(
            title_opts=opts.TitleOpts(title="2023年新能源汽车续航排行"),
            xaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(rotate=45)),
        )
    )
    
    
    # 渲染成 HTML 文件
    bar_chart.render_notebook()

    2023年汽车降价排行

    查看单个车型全国销量:

     # 提取城市和销量的列表
            cities = city_lst
            sales = sales_lst
            # 创建 Geo 图
            geo_chart = (
                Geo()
                .add_schema(maptype="china")
                .add(dict1["data"]["title"], [list(z) for z in zip(cities, sales)])
                .set_series_opts(label_opts=opts.LabelOpts(is_show=False))
                .set_global_opts(
                    visualmap_opts=opts.VisualMapOpts(max_=max(sales), min_=min(sales)),
                    title_opts=opts.TitleOpts(title=dict1["data"]["title"] + "汽车销量分布图"),
                )
            )
    

    问题记录:

    HTML Img标签 src为网络地址(https)无法显示图片问题解决


    解决方案: 只需要在<head>标签内添加

    <meta name="referrer" content="no-referrer">

    就可以了


    以上就是项目部分内容,欢迎批评指正,感兴趣的朋友可关注联系我谢谢!

    次阅读
    2评论
    赞同
    收藏
    分享
    2评论
    赞同
    收藏
    分享

    评论·0

    头像头像
    提交评论
      加载中…

      热门资讯