基于爬虫数据实现前端网页制作(学到很多!)

目录

前言

上效果!

用户注册、登录网页

检索球队信息

图表制作:

柱状图展示的是各队伍的胜率信息:

饼状图展示的是各队伍的比赛场数

折线图展示的是各队伍的平均得分

管理员操作的实现

结语


前言

        几个月前,笔者发表了一篇爬虫的文章,爬取虎扑的NBA赛事信息(传送门)。但这么多数据只能自己看,当然略显无趣,所以现在笔者在这里基于node.js制作了一个前端网站。该网站实现了用户的注册、登录操作,用户可以登录网站检索想看到的球队的比赛信息,还可以查看各队伍的胜率图、比赛场次图、场均得分图;同时网站还实现了管理员身份,管理员的注册信息从本地数据库插入(想当管理员?得先过了我这关!),管理员可以查看所有用户的注册信息,还可以查看用户的操作日志,还可以停用用户账号。下面就来看一下制作网页的过程吧!

上效果!

<iframe allowfullscreen="true" data-mediaembed="bilibili" id="33PT5F8r-1624693808231" src="https://player.bilibili.com/player.html?aid=376283173"></iframe>

NBA爬虫数据前端网页展示

用户注册、登录网页

        首先,我们要准备好页面的背景图,还要写好要用的css样式。

基于爬虫数据实现前端网页制作(学到很多!)

基于爬虫数据实现前端网页制作(学到很多!)

*{
    margin: 0;
    padding: 0;
}
body
{
    background-image: url(./pictures/background.jpg);
    background-size: cover;
    background-position:top;
    font-family: sans-serif;
    
}
.form .login-page
{
    width: 360px;
    padding: 10% 0 0;
    margin: auto;
}
.form
{
    position: relative;
    top: 150px;
    z-index: 1;
    background: rgb(205, 186, 226);
    max-width: 360px;
    margin: 0 auto 100px;
    padding: 45px;
    text-align: center;
}
.form input
{
    outline: none;
    background: #f2f2f2;
    width: 100%;
    border: 0;
    margin: 0 0 15px;
    padding: 15px;
    box-sizing: border-box;
    font-size: 14px;
}
.form button
{
    text-transform: uppercase;
    outline: 0;
    background: orange;
    width: 100%;
    border: none;
    padding: 15px;
    color: #fff;
    font-size: 14px;
    cursor: pointer;
    transition: .5s;
}
.form button:hover,.form button:active
{
    background: green;
    border: none;
}
.form .message a
{
    color: rgb(240, 17, 17);
    text-decoration: none;
}
.register-form
{
    display: none;
}

 这些是准备工作,然后就可以开始写我们的html网页前端代码了。

前端代码要实现两个模块,登录和注册。

<!--Register-->
<form class="register-form" method="POST" id="register-form" role="form">
    <div class="form-group">
        <input type="text" ng-model="add_username" tabindex="1" class="form-control" placeholder="User Name">
    </div>
    <div class="form-group">
        <input type="password" ng-model="add_password" tabindex="2" class="form-control" placeholder="Password">
    </div>
    <div class="form-group">
        <input type="password" ng-model="confirm_password" tabindex="2" class="form-control" placeholder="Confirm Your Password">
    </div>
    <div class="form-group">
        <div class="row">
            <div class="col-sm-6 col-sm-offset-3">
                <button type="button" id="register-submit" tabindex="4" class="form-control" ng-click="doAdd()">Register</button>
            </div>
        </div>
    </div>
    <p class="massage">Already Registered ? <a href="#">Login</a></p>
</form>

<!--Login-->
<form class="login-form" method="POST" id="login-form" role="form">
    <div class="form-group">
        <input type="text" ng-model="username" tabindex="1" class="form-control" placeholder="User Name" name="username">
    </div>
    <div class="form-group">
        <input type="password" ng-model="password" tabindex="2" placeholder="Password" name="password">
    </div>
    <div class="form-group">
        <div class="row">
            <div class="col-sm-6 col-sm-offset-3">
                <button type="button" id="login-submit" tabindex="4" class="form-control" ng-click="check_pwd()">Login</button>
            </div>
        </div>
    </div>
    <p class="massage">Not Registered ? <a href="#">Register</a></p>
        <p class="massage alert alert-warning" ng-if="msg && msg!='ok'">
        <a href="#" class="close" data-dismiss="alert">&times;</a>
        <strong>警告!</strong>{{msg}}
    </p>
</form>

然后我们需要在同一个页面进行登录和注册的切换,因此用到了这一段代码(前提要引入jQuery模块):

$('.massage a').click(function() {
    $('form').animate({height:"toggle", opacity:"toggle"}, "slow");
});

不说了,咱们直接上效果图:

基于爬虫数据实现前端网页制作(学到很多!)

基于爬虫数据实现前端网页制作(学到很多!)

由于万能的css,两个界面切换地很流畅,鼠标悬停在按钮上会有高亮。然后通过angular和express实现前后端的连接,将用户的注册信息写入mysql数据库中,也可以从数据库验证用户的密码。

检索球队信息

        成功登录后,我们会进入competition.html页面。

基于爬虫数据实现前端网页制作(学到很多!)

点击检索,会出现如下画面。

基于爬虫数据实现前端网页制作(学到很多!)

这里做了一个html元素的隐藏和显示。代码如下:

<div ng-show="isShow" style="width: 1300px;position:relative; top:70px;left: 80px">
<!--    查询页面-->
    <div ng-include="'search.html'"></div>
</div>

基于爬虫数据实现前端网页制作(学到很多!)

用show属性的false和true来控制标签的显示与否。

后端可以捕获用户输入的球队名称,然后传到mysql检索。

// 查询数据(根据主客场队伍检索)
    $scope.search = function () {
        var team = $scope.team;
        var oppo = $scope.oppo;

        // 用户可能一个队伍名都不输入,默认查找全部数据
        var myurl = `/competitions/search?t1=${team}&op=${oppo}`;

        $http.get(myurl).then(
            function (res) {
                if(res.data.message=='data'){
                    $scope.isisshowresult = true; //显示表格查询结果
                    $scope.initPageSort(res.data.result)
                }else {
                    window.location.href=res.data.result;
                }


            },function (err) {
                $scope.msg = err.data;
            });
    };

//另一个文件↓

router.get('/search', function(request, response) {
    console.log(request.session['username']);
    //sql字符串和参数
    if (request.session['username']===undefined) {
        response.json({message:'url',result:'/index.html'});
    }else {
        var param = request.query;
        compDAO.search(param,function (err, result, fields) {
            response.json({message:'data',result:result});
        })
    }
});

//另一个文件↓

search :function(searchparam, callback) {
        // 组合查询条件
        var sql = 'select team,ground,scores,record,oppo,ground_op,'+
        'opScores,opRecord,time,timeCost,location,'+
        'numsOfAd,shoot,three_point,penalty,frontcourt,'+
        'backcourt,backboard,assist,foul,steal,mistake,cover from myfetches ';

        if(searchparam["t1"]!="undefined"){
            sql +=(`where team like '%${searchparam["t1"]}%'`);
            if(searchparam["op"]!="undefined"){
                sql +=(`AND oppo like '%${searchparam["op"]}%' `);
            };
        }
        else if(searchparam["op"]!="undefined"){
            sql +=(`where oppo like '%${searchparam["t1"]}%' `);
        };

        sql+=';';
        pool.getConnection(function(err, conn) {
            if (err) {
                callback(err, null, null);
            } else {
                conn.query(sql, function(qerr, vals, fields) {
                    conn.release(); //释放连接
                    callback(qerr, vals, fields); //事件驱动回调
                });
            }
        });
    }

检索支持双队伍检索,即固定主场队伍和客场队伍(有相对顺序关系)。因此在mysql检索语句中要加一系列条件判断语句,组合成mysql命令行的检索指令。

最后的效果图如下,结果实现了分页处理,而且还可以根据比赛时间排序(阿杜,你没有输!):

基于爬虫数据实现前端网页制作(学到很多!)

基于爬虫数据实现前端网页制作(学到很多!)

图表制作:

        点击图片,会下拉三个图表选项,分别是柱状图、饼状图、折线图。图表全部依赖ECharts制作。

柱状图展示的是各队伍的胜率信息:

基于爬虫数据实现前端网页制作(学到很多!)

胜率信息由爬取的record是字符串类型,所以要用parInt函数对record战绩信息的字符字串操作,得到胜场和败场,从而计算出胜率。

    $scope.histogram = function () {
        $scope.isShow = false;
        $http.get("/competitions/histogram")
            .then(
                function (res) {
                    if(res.data.message=='url'){
                        window.location.href=res.data.result;
                    }else {
                        let xdata = [], ydata = [], newdata;
                        res.data.result.forEach(function (element) {
                            // "record":"XX胜利XX失败"
                            if(element["record"].length > 4 && xdata.indexOf(element["team"]) == -1)
                            {
                                var win = parseInt(element["record"].substr(0, 2));//将字符串数据转化为数字,计算胜率
                                var lose = parseInt(element["record"].substr(3, 2));
                                var rate = win / (win + lose);
                                ydata.push(rate);
                                xdata.push(element["team"]);
                            }
                        });
                        newdata = {"xdata": xdata, "ydata": ydata};

                        var myChart = echarts.init(document.getElementById('main1'));

                        // 指定图表的配置项和数据
                        var option = {
                            title: {
                                text: 'NBA各队伍胜率'
                            },
                            tooltip: {},
                            legend: {
                                data: ['队伍']
                            },
                            xAxis: {
                                data: newdata["xdata"],
                                axisLabel: {
                                    show: true,
                                    interval:0
                                }
                            },

                            yAxis: {},
                            series: [{
                                name: '胜率',
                                type: 'bar',
                                data: newdata["ydata"],
                                barGap: '80%',
                                barWidth: '50%'
                            }]
                        };
                        // 使用刚指定的配置项和数据显示图表。
                        myChart.setOption(option);
                    }
                },
                function (err) {
                    $scope.msg = err.data;
                });

    };

饼状图展示的是各队伍的比赛场数

基于爬虫数据实现前端网页制作(学到很多!)

比赛的场次可以直接用mysql中的内置aggregate function COUNT() 得到。

"select team as x,count(team) as y from myfetches group by team;"

然后再将得到的数据作为pie图的数据就好了。

    $scope.pie = function () {
        $scope.isShow = false;
        $http.get("/competitions/pie").then(
            function (res) {
                if(res.data.message=='url'){
                    window.location.href=res.data.result;
                }else {
                    let newdata = [];
                    res.data.result.forEach(function (element) {
                        newdata.push({name: element["x"], value: element["y"]});
                    });

                    var myChart = echarts.init(document.getElementById('main1'));
                    var app = {};
                    option = null;
                    // 指定图表的配置项和数据
                    var option = {
                        title: {
                            text: '各队伍比赛场数',
                            x: 'center'
                        },
                        tooltip: {
                            trigger: 'item',
                            formatter: "{a} <br/>{b} : {c} ({d}%)"
                        },
                        legend: {
                            orient: 'vertical',
                            left: 'left',
                            // data: ['直接访问', '邮件营销', '联盟广告', '视频广告', '搜索引擎']
                        },
                        series: [
                            {
                                name: '访问来源',
                                type: 'pie',
                                radius: '55%',
                                center: ['50%', '60%'],
                                data: newdata,
                                itemStyle: {
                                    emphasis: {
                                        shadowBlur: 10,
                                        shadowOffsetX: 0,
                                        shadowColor: 'rgba(0, 0, 0, 0.5)'
                                    }
                                }
                            }
                        ]
                    };
                    // myChart.setOption(option);
                    app.currentIndex = -1;

                    setInterval(function () {
                        var dataLen = option.series[0].data.length;
                        // 取消之前高亮的图形
                        myChart.dispatchAction({
                            type: 'downplay',
                            seriesIndex: 0,
                            dataIndex: app.currentIndex
                        });
                        app.currentIndex = (app.currentIndex + 1) % dataLen;
                        // 高亮当前图形
                        myChart.dispatchAction({
                            type: 'highlight',
                            seriesIndex: 0,
                            dataIndex: app.currentIndex
                        });
                        // 显示 tooltip
                        myChart.dispatchAction({
                            type: 'showTip',
                            seriesIndex: 0,
                            dataIndex: app.currentIndex
                        });
                    }, 1000);
                    if (option && typeof option === "object") {
                        myChart.setOption(option, true);
                    }
                    ;
                }
            });
    };

折线图展示的是各队伍的平均得分

        效果如下:

基于爬虫数据实现前端网页制作(学到很多!)

与饼状图同理,平均得分也可以由AVG()函数得到。

"select team as x,avg(scores) as y from myfetches group by team;"

得到数据后,便将数据加入ECharts组件即可展示折线图。

    $scope.line = function () {
        $scope.isShow = false;
        $http.get("/competitions/line").then(
            function (res) {
                if(res.data.message=='url'){
                    window.location.href=res.data.result;
                }else {
                    var myChart = echarts.init(document.getElementById("main1"));
                    let teams = [];
                    let avgScores = [];
                    res.data.result.forEach(function(element) {
                        teams.push(element["x"]);
                        avgScores.push(element["y"]);
                    });
                    option = {
                        title: {
                            text: '各队伍平均得分'
                        },
                        xAxis: {
                            type: 'category',
                            data: teams,
                        },
                        yAxis: {
                            type: 'value'
                        },
                        series: [{
                            data: avgScores,
                            type: 'line',
                            itemStyle: {normal: {label: {show: true}}}
                        }],

                    };

                    if (option && typeof option === "object") {
                        myChart.setOption(option, true);
                    }
                }

            });
    };

每次展示图表之前,都先初始化前端的main1标签,避免多张图重叠,然后再展示当前的图片。

管理员操作的实现

我们希望管理员有以下权限:查看所有用户的注册信息以及用户的操作日志,还有停用用户账号。

管理员的注册当然不能写在网页前端,不然人人都可以有管理他人账号的权力了。因此管理员的账号必须由后台直接在mysql中插入。

基于爬虫数据实现前端网页制作(学到很多!)

管理页面的前端和用户登录的前端类似。

基于爬虫数据实现前端网页制作(学到很多!)

当然需要在app文件中加入一个新的路由地址,一系列数据库操作也要和user的操作分离开来(这得创建好多新文件,头秃了......)。

管理员成功登录后,会出现如下界面。

基于爬虫数据实现前端网页制作(学到很多!)

页面的查看选项卡有两个选项,用户注册信息与操作日志浏览、停用用户。因为前者只是实现mysql数据的展示,而后者需要管理员输入,并对数据库信息进行修改,因此我将二者分开。

进入用户注册信息与操作日志浏览选项卡,会出现如下画面。

基于爬虫数据实现前端网页制作(学到很多!)

管理员可以点击两个按钮选择要浏览的信息。

(用户注册信息)

基于爬虫数据实现前端网页制作(学到很多!)

(用户操作日志)

基于爬虫数据实现前端网页制作(学到很多!)

这里的前端实现也与前面的competition类似,显示一个页面时隐藏其他页面。数据展示也实现了分页处理和按时间顺序排序的操作。

点击停用用户按钮,会出现如下画面。

基于爬虫数据实现前端网页制作(学到很多!)

管理员输入要停用的用户名,点击确定按钮,即可删除要删除的用户。

基于爬虫数据实现前端网页制作(学到很多!)

停用成功后,会alert一个弹窗,告诉管理员停用成功。

我们再查看用户注册信息,发现已经没有'mr_king'的注册信息了。

基于爬虫数据实现前端网页制作(学到很多!)

再到登陆界面用mr_king的账号密码登录,也无法登录。

基于爬虫数据实现前端网页制作(学到很多!)

前端页面显示用户不存在。

结语

        这次前端网页制作的过程我无疑是收获满满的:学会了很多mysql的命令、更加熟练地使用路由实现前后端交互、html的设计也愈发熟练。希望这个网页能为我的Web编程课提交一份满意的答卷。

上一篇:[译] 协程中的取消和异常(第 1 部分)- 协程:第一件事


下一篇:uni-app小程序下载图片