期末大作业要求:

在这里插入图片描述

本次作业基于期中作业里面所爬出来的数据,主要是网页的展示界面,但是前端的要求变高了,就把上次的前端重新修改了下~

注册登录

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>注册界面</title>
    <style>
* {
    margin: 0;
    padding: 0;
}

body {
    height: 100vh;
    display: flex;
    justify-content: center;
    align-items: center;
    background: linear-gradient(45deg, rgb(181, 154, 254), rgb(245, 189, 253)) fixed;
}

.container {
    position: relative;
    width: 70rem;
}

.switch span {
    color: #ccc;
    font-size: 4rem;
    cursor: pointer;
}

.switch span.active {
    color: rgb(181, 154, 254);
}

.panel {
    width: 100%;
    position: absolute;
    right: 0;
    top: 0;

    display: flex;
    justify-content: center;
}

.form {
    width: 12rem;
    margin: 3rem 0 0;
}

.form .input {
    position: relative;
    opacity: 1;
    height: 2rem;
    width: 100%;
    margin: 2rem 0;
    transition: .4s;
}

.input input {
    outline: none;
    width: 100%;
    border: none;
    border-bottom: .1rem solid rgb(181, 154, 254);
    position: relative;
    line-height: 35px;
    background: transparent;
    z-index: 1;
}

.input label {
    position: absolute;
    left: 0;
    top: 20%;
    font-size: 1.2rem;
    color: rgb(129, 101, 207);
    transition: .3s;
}   

.hasValue ~ label, input:focus ~ label {
    top: -50%;
    font-size: .9rem;
}

.form span {
    display: block;
    color: rgb(110, 89, 167);
    font-size: .8rem;
    cursor: pointer;
}

.form button {
    border: none;
    outline: none;
    margin: 2.5rem 0 0;
    width: 100%;
    height: 3rem;
    border-radius: 3rem;
    background: linear-gradient(90deg, rgb(181, 154, 254), rgb(245, 189, 253));
    box-shadow: 0 0 8px rgb(181, 154, 254);
    cursor: pointer;
    color: white;
}

#live2dcanvas {
    border: 0 !important;
}
    </style>
    <script src="https://cdn.staticfile.org/vue/2.6.9/vue.js"></script>
</head>

<body>
    <div id='app' class="container">
        <div class="panel">
            <div class="content login">
                <div class="switch">
                    <span :class='{"active": active === "login"}' @click='go("login")'>登陆</span>
                    <span>/</span>
                    <span :class='{"active": active === "register"}' @click='go("register")'>注册</span>
                </div>
                <div class='form' id="fromLogin">
                    <template v-if='active === "register"'>
                        <div class="input"><input :class='{ hasValue: registerForm.email }' v-model='registerForm.email' type="text" name="email" id='email' /><label for="email">邮箱</label></div>
                        <div class="input"><input :class='{ hasValue: registerForm.Username }' v-model='registerForm.Username' type="text" name="Username" id="username" /><label for="username">用户名</label></div>
                        <div class="input"><input :class='{ hasValue: registerForm.Password }' v-model='registerForm.Password' type="password" name="Password" id="Password" /><label for="Password">密码</label></div>
                        <div class="input"><input :class='{ hasValue: registerForm.repeat }' v-model='registerForm.repeat' type="password" name="repeat" id="Passwordrepeat" /><label for="Passwordrepeat">重复密码</label></div>
                    </template>

                    <template v-if='active === "login"'>
                        <div class="input"><input :class='{ hasValue: loginForm.Username }' v-model='loginForm.Username' type="text" name="Username" id="username" /><label for="username">用户名</label></div>
                        <div class="input"><input :class='{ hasValue: loginForm.Password }' v-model='loginForm.Password' type="password" name="Password" id="Password" /><label for="Password">密码</label></div>
                    </template>

                    <span>忘记?</span>

                    <button type="submit" @click='submit'>登陆</button>
                </div>
            </div>
        </div>
    </div>
</body>

<script>
var vue = new Vue({
    el: '#app',
    data: {
        active: 'login',
        registerForm: { email: '', Username: '', Password: '', repeat: '', },
        loginForm: { Username: '', Password: '', },
    },
    methods: {
        go (type) {
            this.active = type
        },
        submit() {
            if (type === 'login') {
                console.log('login', this.loginForm)
            } 

            if (type === 'register') {
                console.log('register', this.registerForm)
            }
        }
    },
    beforeMount () {}
})
</script>

</html>

上面的代码是原来自己做的,后来老师发出来了示例,就把大部分改成了示例模板的样子。 

<!DOCTYPE html>
<html ng-app="login">
<head>
    <meta charset="utf-8" />
    <title>Login</title>
    <link rel="stylesheet" href="http://cdn.bootcss.com/bootstrap/3.3.0/css/bootstrap.min.css">
    <script src="https://cdn.staticfile.org/jquery/3.2.1/jquery.min.js"></script>
    <script src="https://cdn.staticfile.org/popper.js/1.12.5/umd/popper.min.js"></script>
    <script src="https://cdn.staticfile.org/twitter-bootstrap/4.1.0/js/bootstrap.min.js"></script>
<!--    <script src="../node_modules/angular/angular.min.js"></script>-->
    <script src="/angular/angular.min.js"></script>

<!--    引入自己的样式与js-->
    <link rel="stylesheet" type="text/css" href="stylesheets/index.css">
    <script type="text/javascript" src="javascripts/index.js"></script>
    <script>
        var app = angular.module('login', []);
        app.controller('loginCtrl', function ($scope, $http, $timeout) {

            // 登录时,检查用户输入的账户密码是否与数据库中的一致
            $scope.check_pwd = function () {
                var data = JSON.stringify({
                    username: $scope.username,
                    password: $scope.password
                });
                $http.post("/users/login", data)
                    .then(
                    function (res) {
                        if(res.data.msg=='ok') {
                            window.location.href='/news.html';
                        }else{
                            $scope.msg=res.data.msg;
                        }
                    },
                        function (err) {
                        $scope.msg = err.data;
                    });

            };
            //增加注册用户
            $scope.doAdd = function () {
                // 检查用户注册时,输入的两次密码是否一致
                if($scope.add_password!==$scope.confirm_password){
                    // $timeout(function () {
                    //     $scope.msg = '两次密码不一致!';
                    // },100);
                    $scope.msg = '两次密码不一致!';
                }
                else {
                    var data = JSON.stringify({
                        username: $scope.add_username,
                        password: $scope.add_password
                    });
                    $http.post("/users/register", data)
                        .then(function (res) {
                            if(res.data.msg=='成功注册!请登录') {
                                $scope.msg=res.data.msg;
                                $timeout(function () {
                                    window.location.href='index.html';
                                },2000);

                            } else {
                                $scope.msg = res.data.msg;
                            }
                        }, function (err) {
                            $scope.msg = err.data;
                        });
                }
            };
        });
    </script>
</head>
<body>
<div class="container" ng-controller="loginCtrl">
    <div class="row">
        <div class="col-md-6 col-md-offset-3">
            <div class="panel panel-login">
                <div class="panel-heading">
                    <div class="row">
                        <div class="col-xs-6">
                            <a href="#" class="active" id="login-form-link">Login</a>
                        </div>
                        <div class="col-xs-6">
                            <a href="#" id="register-form-link">Register</a>
                        </div>
                    </div>
                    <hr>
                </div>
                <div class="panel-body">
                    <div class="row">
                        <div class="col-lg-12">
                            <form id="login-form" method="post" role="form" style="display: block;">
<!--                                登陆部分-->
                                <div class="form-group">
                                    <input ng-model="username" tabindex="1" class="form-control" placeholder="Username" value=""/>
                                </div>
                                <div class="form-group">
                                    <input type="password" ng-model="password" tabindex="2" class="form-control" placeholder="Password">
                                </div>
<!--                                <div class="form-group text-center">-->
<!--                                    <input type="checkbox" tabindex="3" class="" name="remember" id="remember">-->
<!--                                    <label for="remember"> Remember Me</label>-->
<!--                                </div>-->

                                <div class="form-group">
                                    <div class="row">
                                        <div class="col-sm-6 col-sm-offset-3">
                                            <button id="login-submit" tabindex="4" class="form-control btn btn-login" ng-click="check_pwd()">LOG IN</button>
                                        </div>
                                    </div>
                                </div>
                            </form>
                            <form id="register-form" method="post" role="form" style="display: none;">
                                <div class="form-group">
                                    <input ng-model="add_username" tabindex="1" class="form-control" placeholder="Username" value=""/>
                                </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 Password">
                                </div>
                                <div class="form-group">
                                    <div class="row">
                                        <div class="col-sm-6 col-sm-offset-3">
                                            <button tabindex="4" class="form-control btn btn-register" ng-click="doAdd()">Register Now</button>
                                        </div>
                                    </div>
                                </div>

                            </form>

                        </div>
                    </div>
                </div>
<!--                <div class="alert alert-warning alert-dismissible fade show">-->
<!--                    <button type="button" class="close" data-dismiss="alert">&times;</button>-->
<!--                    <strong>警告!</strong>{{msg}}-->
<!--                </div>-->
            </div>
            <div class="alert alert-warning" ng-if="msg && msg!='ok'">
                <a href="#" class="close" data-dismiss="alert">&times;</a>
                <strong>警告!</strong>{{msg}}
            </div>
        </div>
    </div>
</div>
</body>

整个是一个注册和登录界面的前端代码,本来想贴图但是发现怎么也贴不上去,就罢了。

下面是成果展示:(原来自己的)

修改老师的之后:

(上面显示格式有点小错误,但是功能都可以实现) 

为了使登录用户有效,非注册用户不能查询,我们就要再建立一个用来储存用户信息的表格来调用,在vscode里面创建的代码如下:

CREATE TABLE `user` (
  `mail` varchar(200) DEFAULT NULL,
  `name` varchar(200) DEFAULT NULL,
  `password` varchar(200) DEFAULT NULL,
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

还有一个记录用户操作的表格:

CREATE TABLE `crawl`.`user_s_action` (
  `id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
  `username` VARCHAR(45) NOT NULL,
  `request_time` VARCHAR(45) NOT NULL,
  `request_method` VARCHAR(20) NOT NULL,
  `request_url` VARCHAR(300) NOT NULL,
  `status` int(4),
  `remote_addr` VARCHAR(100) NOT NULL,
    PRIMARY KEY (`id`))
ENGINE=InnoDB DEFAULT CHARSET=utf8;

后端的注册和登录路由(几乎不用改):

var mysql = require('mysql');
var mysqlConf = require('../conf/mysqlConf');
var userSqlMap = require('./userSqlMap');
var pool = mysql.createPool(mysqlConf.mysql);
// 使用了连接池,重复使用数据库连接,而不必每执行一次CRUD操作就获取、释放一次数据库连接,从而提高了对数据库操作的性能。
 
module.exports = {
    add: function (user, callback) {
        pool.query(userSqlMap.add, [user.username, user.password], function (error, result) {
            if (error) throw error;
            callback(result.affectedRows > 0);
        });
    },
    getByUsername: function (username, callback) {
        pool.query(userSqlMap.getByUsername, [username], function (error, result) {
            if (error) throw error;
            callback(result);
        });
    },
 
};
var express = require('express');
var router = express.Router();
var userDAO = require('../dao/userDAO');
 
router.post('/login', function(req, res) {
  var username = req.body.username;
  var password = req.body.password;
  // var sess = req.session;
 
  userDAO.getByUsername(username, function (user) {
    if(user.length==0){
      res.json({msg:'用户不存在!请检查后输入'});
 
    }else {
      if(password===user[0].password){
        req.session['username'] = username;
        res.cookie('username', username);
        res.json({msg: 'ok'});
        // res.json({msg:'ok'});
      }else{
        res.json({msg:'用户名或密码错误!请检查后输入'});
      }
    }
  });
});
 
/* add users */
router.post('/register', function (req, res) {
  var add_user = req.body;
  // 先检查用户是否存在
  userDAO.getByUsername(add_user.username, function (user) {
    if (user.length != 0) {
      // res.render('index', {msg:'用户不存在!'});
      res.json({msg: '用户已存在!'});
    }else {
      userDAO.add(add_user, function (success) {
        res.json({msg: '成功注册!请登录'});
      })
    }
  });
 
});
 
// 退出登录
router.get('/logout', function(req, res, next){
  // 备注:这里用的 session-file-store 在destroy 方法里,并没有销毁cookie
  // 所以客户端的 cookie 还是存在,导致的问题 --> 退出登陆后,服务端检测到cookie
  // 然后去查找对应的 session 文件,报错
  // session-file-store 本身的bug
 
  req.session.destroy(function(err) {
    if(err){
      res.json('退出登录失败');
      return;
    }
 
    // req.session.loginUser = null;
    res.clearCookie('username');
    res.json({result:'/index.html'});
  });
});
 
module.exports = router;

 后端新闻页的接口路由:

var mysql = require('mysql');
var mysqlConf = require('../conf/mysqlConf');
var pool = mysql.createPool(mysqlConf.mysql);
// 使用了连接池,重复使用数据库连接,而不必每执行一次CRUD操作就获取、释放一次数据库连接,从而提高了对数据库操作的性能。
 
module.exports = {
    query_noparam :function(sql, callback) {
        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); //事件驱动回调
                });
            }
        });
    },
    search :function(searchparam, callback) {
        // 组合查询条件
        var sql = 'select * from fetches ';
 
        if(searchparam["t2"]!="undefined"){
            sql +=(`where title like '%${searchparam["t1"]}%' ${searchparam['ts']} title like '%${searchparam["t2"]}%' `);
        }else if(searchparam["t1"]!="undefined"){
            sql +=(`where title like '%${searchparam["t1"]}%' `);
        };
 
        if(searchparam["t1"]=="undefined"&&searchparam["t2"]=="undefined"&&searchparam["c1"]!="undefined"){
            sql+='where ';
        }else if(searchparam["t1"]!="undefined"&&searchparam["c1"]!="undefined"){
            sql+='and ';
        }
 
        if(searchparam["c2"]!="undefined"){
            sql +=(`content like '%${searchparam["c1"]}%' ${searchparam['cs']} content like '%${searchparam["c2"]}%' `);
        }else if(searchparam["c1"]!="undefined"){
            sql +=(`content like '%${searchparam["c1"]}%' `);
        }
 
        if(searchparam['stime']!="undefined"){
            if(searchparam['stime']=="1"){
                sql+='ORDER BY publish_date ASC ';
            }else {
                sql+='ORDER BY publish_date DESC ';
            }
        }
 
        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); //事件驱动回调
                });
            }
        });
    },
 
 
};
var newsDAO = require('../dao/newsDAO');
var express = require('express');
var router = express.Router();
 
var mywordcutModule = require('./wordcut.js');
var myfreqchangeModule = require('./freqchange.js');
 
 
router.get('/search', function(request, response) {
    console.log(request.session['username']);
    //sql字符串和参数
    if (request.session['username']===undefined) {
        // response.redirect('/index.html')
        response.json({message:'url',result:'/index.html'});
    }else {
        var param = request.query;
        newsDAO.search(param,function (err, result, fields) {
            response.json({message:'data',result:result});
        })
    }
});
 
router.get('/column', function(request, response) {
    //sql字符串和参数
    console.log(request.session['username']);
 
    //sql字符串和参数
    if (request.session['username']===undefined) {
        // response.redirect('/index.html')
        response.json({message:'url',result:'/index.html'});
    }else {
        var fetchSql = "select publish_date as x,count(publish_date) as y from fetches group by publish_date order by publish_date;";
        newsDAO.query_noparam(fetchSql, function (err, result, fields) {
            response.writeHead(200, {
                "Content-Type": "application/json",
                "Cache-Control": "no-cache, no-store, must-revalidate",
                "Pragma": "no-cache",
                "Expires": 0
            });
            response.write(JSON.stringify({message:'data',result:result}));
            response.end();
        });
    }
});
 
 
router.get('/pie', function(request, response) {
    //sql字符串和参数
    console.log(request.session['username']);
 
    //sql字符串和参数
    if (request.session['username']===undefined) {
        // response.redirect('/index.html')
        response.json({message:'url',result:'/index.html'});
    }else {
        var fetchSql = "select author as x,count(author) as y from fetches group by author;";
        newsDAO.query_noparam(fetchSql, function (err, result, fields) {
            response.writeHead(200, {
                "Content-Type": "application/json",
                "Cache-Control": "no-cache, no-store, must-revalidate",
                "Pragma": "no-cache",
                "Expires": 0
            });
            response.write(JSON.stringify({message:'data',result:result}));
            response.end();
        });
    }
});
 
router.get('/line', function(request, response) {
    //sql字符串和参数
    console.log(request.session['username']);
 
    //sql字符串和参数
    if (request.session['username']===undefined) {
        // response.redirect('/index.html')
        response.json({message:'url',result:'/index.html'});
    }else {
        var keyword = '价格'; //也可以改进,接受前端提交传入的搜索词
        var fetchSql = "select content,publish_date from fetches where content like'%" + keyword + "%' order by publish_date;";
        newsDAO.query_noparam(fetchSql, function (err, result, fields) {
            response.writeHead(200, {
                "Content-Type": "application/json",
                "Cache-Control": "no-cache, no-store, must-revalidate",
                "Pragma": "no-cache",
                "Expires": 0
            });
            response.write(JSON.stringify({message:'data',result:myfreqchangeModule.freqchange(result, keyword)}));
            response.end();
        });
    }
});
 
            response.write(JSON.stringify({message:'data',result:mywordcutModule.wordcut(result)}));//返回处理过的数据
            response.end();
        });
    }
});
 
 
module.exports = router;

这些需要在mysql里面再次进行操作,这个我在期中作业里面已经展示过了,这里就不再赘述。具体可以参考:(5条消息) 2021-04-27_A singirle。的博客-CSDN博客 

其中还有很多是直接应用了老师的代码然后稍加修改的。

查询词(满足bool表达式)

 增加的代码如下:

满足布尔类型

if(typeof title1=="undefined" && typeof title2!="undefined" && title2.length>0){
            title1 = title2;
        }
        if(typeof content1=="undefined" && typeof content2!="undefined" && content2.length>0){
            content1 = content2;
        }

用户直接搜索:

var myurl = `/news/search?t1=${title1}&ts=${selectTitle}&t2=${title2}&c1=${content1}&cs=${selectContent}&c2=${content2}&stime=${sorttime}`;

搜索界面的网页展示如下(在期中前端代码上做了一些小的修改,具体参考上面的期中作业链接):

 最后通过搜索的界面展示(包括分页):

老师的示例给出来后就重新弄了个:

前端代码:

<form class="form-horizontal" role="form">
    <div class="row" style="margin-bottom: 10px;">
        <label class="col-lg-2 control-label">标题关键字</label>
        <div class="col-lg-3">
            <input type="text" class="form-control" placeholder="标题关键字" ng-model="$parent.title1">
        </div>
        <div class="col-lg-1">
            <select class="form-control" autocomplete="off" ng-model="$parent.selectTitle">
                <option selected="selected">AND</option>
                <option>OR</option>

            </select>
        </div>
        <div class="col-lg-3">
            <input type="text" class="form-control" placeholder="标题关键字" ng-model="$parent.title2">
        </div>
    </div>



    <div class="row" style="margin-bottom: 10px;">
        <label class="col-lg-2 control-label">内容关键字</label>
        <div class="col-lg-3">
            <input type="text" class="form-control" placeholder="内容关键字" ng-model="$parent.content1">
        </div>
        <div class="col-lg-1">
            <select class="form-control" autocomplete="off" ng-model="$parent.selectContent">
                <option selected="selected">AND</option>
                <option>OR</option>
            </select>
        </div>
        <div class="col-lg-3">
            <input type="text" class="form-control" placeholder="内容关键字" ng-model="$parent.content2">
        </div>
    </div>


    <div class="form-group">
        <div class="col-md-offset-9">
            <button type="submit" class="btn btn-default" ng-click="search()">查询</button>
        </div>
    </div>

</form>

<!--显示查询结果-->
<div ng-show="isisshowresult">

    <table class="table table-striped">
        <thead>
            <tr>
                <td>序号</td>
                <td>标题</td>
                <td>作者</td>
<!--                <td>内容</td>-->
                <td>关键词</td>
                <td>链接</td>
                <td>发布时间</td>
            </tr>

        </thead>
        <tbody>
        <tr ng-repeat="(key, item) in items">
            <td>{{index+key}}</td>
            <td>{{item.title}}</td>
            <td>{{item.author}}</td>
<!--            <td>{{item.content}}</td>-->
            <td>{{item.keywords}}</td>
            <td>{{item.url}}</td>
            <td>{{item.publish_date}}</td>
        </tr>

        </tbody>
    </table>

    <div class="row">
<!--        <div class="form-group">-->
        <div class="pull-left" style="margin-top: 12px;">
            <button type="submit" class="btn btn-primary" ng-click="searchsortASC()" >发布时间升序</button>
            <button type="submit" class="btn btn-primary" ng-click="searchsortDESC()">发布时间降序</button>
        </div>
<!--        </div>-->
        <div class="pull-right">
            <nav>
                <ul class="pagination">
                    <li>
                        <a ng-click="Previous()" role="button"><span role="button">上一页</span></a>
                    </li>
                    <li ng-repeat="page in pageList" ng-class="{active:isActivePage(page)}" role="button">
                        <a ng-click="selectPage(page)" >{{ page }}</a>
                    </li>
                    <li>
                        <a ng-click="Next()" role="button"><span role="button">下一页</span></a>
                    </li>
                </ul>
            </nav>
        </div>
    </div>
</div>

分页js代码:

    $scope.initPageSort=function(item){
        $scope.pageSize=5;  //每页显示的数据量,可以随意更改
        $scope.selPage = 1;
        $scope.data = item;
        $scope.pages = Math.ceil($scope.data.length / $scope.pageSize); //分页数
        $scope.pageList = [];//最多显示5页,后面6页之后不会全部列出页码来
        $scope.index = 1;
        // var page = 1;
        // for (var i = page; i < $scope.pages+1 && i < page+5; i++) {
        //     $scope.pageList.push(i);
        // }
        var len = $scope.pages> 5 ? 5:$scope.pages;
        $scope.pageList = Array.from({length: len}, (x,i) => i+1);
 
        //设置表格数据源(分页)
        $scope.items = $scope.data.slice(0, $scope.pageSize);
 
    };
 
    //打印当前选中页
    $scope.selectPage = function (page) {
        //不能小于1大于最大(第一页不会有前一页,最后一页不会有后一页)
        if (page < 1 || page > $scope.pages) return;
        //最多显示分页数5,开始分页转换
        var pageList = [];
        if(page>2){
            for (var i = page-2; i <= $scope.pages && i < page+3; i++) {
                pageList.push(i);
            }
        }else {
            for (var i = page; i <= $scope.pages && i < page+5; i++) {
                pageList.push(i);
            }
        }
 
        $scope.index =(page-1)*$scope.pageSize+1;
        $scope.pageList = pageList;
        $scope.selPage = page;
        $scope.items = $scope.data.slice(($scope.pageSize * (page - 1)), (page * $scope.pageSize));//通过当前页数筛选出表格当前显示数据
        console.log("选择的页:" + page);
    };
 
    //设置当前选中页样式
    $scope.isActivePage = function (page) {
        return $scope.selPage == page;
    };
    //上一页
    $scope.Previous = function () {
        $scope.selectPage($scope.selPage - 1);
    };
    //下一页
    $scope.Next = function () {
        $scope.selectPage($scope.selPage + 1);
    };
 
    $scope.searchsortASC = function () {
        $scope.sorttime = '1';
        $scope.search();
    };
    $scope.searchsortDESC = function () {
        $scope.sorttime = '2';
        $scope.search();
    };

用Echarts实现数据分析表:

词云:

词云的实现我参考了很多代码,最后还是没做出来,但是基本过程总结如下:

首先要安装一些库,例如 jieba、matplotlib、wordcloud等等,在命令提示行里面输入pip install 下载就可以了!

参考网页:https://www.cnblogs.com/djdjdj123/p/12153603.html

我挑出了一则新闻内容做了关键字(自己挑选出来)的词云,内容如下:

英国泰特美术馆所藏意大利艺术家阿梅迪奥·莫迪利亚尼( Amedeo Modigliani)一幅1917年作品《女孩肖像》背后,最近通过研究后被认为藏着另一位女子的肖像。虽然画布表面所绘模特身份未知,但被覆盖的肖像基本被认为是莫迪利亚尼的前情人、英国女诗人比阿特丽斯·黑斯廷斯(Beatrice Hastings)。
伦敦大学的两位博士候选人利用X射线和人工智能对莫迪利亚尼画作的分析,试图借助“算法”和3D技术,以油画的纹理和笔触还原被覆盖的肖像。这再次勾起了人们对莫迪利亚尼和黑斯廷斯的兴趣,他反复画她,尽管这对情侣因为酒后争吵和凶狠的厮打在巴黎艺术圈臭名昭著,但不得不说她既是他的魔鬼,也是他的缪斯。
1906年,22岁的莫迪利亚尼初抵巴黎,这时候的巴黎正是艺术蓬勃发展的时候,以毕加索为首的立体派、马蒂斯的野兽派、超现实主义、表现主义、未来派……各种艺术流派热闹非凡,巴黎的激情激发了他的创作欲望,却也让他埋没在这诸多天才中。
由于体弱多病,加之巴黎生活的困难,莫迪利亚尼渐渐形成了酗酒的习惯,在穷苦和麻醉中过着颓废的生活。

 利用凡科的最终制作展示成果如下:(聊表观赏)

折线图:

$scope.line = function () {
        $scope.isShow = false;
        $http.get("/news/line").then(
            function (res) {
                if(res.data.message=='url'){
                    window.location.href=res.data.result;
                }else {
                    var myChart = echarts.init(document.getElementById("main1"));
                    option = {
                        title: {
                            text: '"疫情"该词在新闻中的出现次数随时间变化图'
                        },
                        xAxis: {
                            type: 'category',
                            data: Object.keys(res.data.result)
                        },
                        yAxis: {
                            type: 'value'
                        },
                        series: [{
                            data: Object.values(res.data.result),
                            type: 'line',
                            itemStyle: {normal: {label: {show: true}}}
                        }],

                    };

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

            });
    };

柱状图:

$scope.histogram = function () {
        $scope.isShow = false;
        $http.get("/news/column")
            .then(
                function (res) {

                    if(res.data.message=='url'){
                        window.location.href=res.data.result;
                    }else {

                        // var newdata = washdata(data);
                        let xdata = [], ydata = [], newdata;

                        var pattern = /\d{4}-(\d{2}-\d{2})/;
                        res.data.result.forEach(function (element) {
                            // "x":"2020-04-28T16:00:00.000Z" ,对x进行处理,只取 月日
                            xdata.push(pattern.exec(element["x"])[1]);
                            ydata.push(element["y"]);
                        });
                        newdata = {"xdata": xdata, "ydata": ydata};

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

                        // 指定图表的配置项和数据
                        var option = {
                            title: {
                                text: '新闻发布数(以时间为基准)'
                            },
                            tooltip: {},
                            xAxis: {
                                data: newdata["xdata"]
                            },

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

    };

 饼图:


    $scope.pie = function () {
        $scope.isShow = false;
        $http.get("/news/pie").then(
            function (res) {
                if(res.data.message=='url'){
                    window.location.href=res.data.result;
                }else {
                    let newdata = [];

                    var pattern = /责任编辑:(.+)/;//匹配名字
                    res.data.result.forEach(function (element) {
                        // "x":  责任编辑:李夏君 ,对x进行处理,只取 名字
                        newdata.push({name: pattern.exec(element["x"])[1], 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);
                    }
                    ;
                }
            });
    };

只能根据代码来修改一下做出来了,但是最后实现不了,所以自己输入了数据做了其它两个图

option = {
    tooltip: {
        trigger: 'item',
        formatter: '{a} <br/>{b}: {c} ({d}%)'
    },
    legend: {
        orient: 'vertical',
        left: 10,
        data: [ '北京','广东','河北','河南','黑龙江','湖北','湖南','江苏','山东','山西','上海','四川','云南','浙江','重庆']
    },
    series: [
        {
            name: '报名人数',
            type: 'pie',
            radius: ['50%', '70%'],
            avoidLabelOverlap: false,
            label: {
                show: false,
                position: 'center'
            },
            emphasis: {
                label: {
                    show: true,
                    fontSize: '30',
                    fontWeight: 'bold'
                }
            },
            labelLine: {
                show: false
            },
            data: [
                {value: 4.9, name: '北京'},
                {value: 78.3, name: '广东'},
                {value: 63.4, name: '河北'},
                {value: 125, name: '河南'},
                {value: 21.1, name: '黑龙江'},
                {value: 37.4, name: '湖北'},
                {value: 56.8, name: '湖南'},
                {value: 34.2, name: '江苏'},
                {value: 79.5, name: '山东'},
                {value: 32.56, name: '山西'},
                {value: 7, name: '上海'},
                {value: 69, name: '四川'},
                {value: 32.59, name: '陕西'},
                {value: 31.5, name: '浙江'},
                {value: 24.75, name: '重庆'},
            ]
        }
    ]
};

option = {
    tooltip: {
        trigger: 'axis',
        axisPointer: {
            type: 'cross',
            crossStyle: {
                color: '#999'
            }
        }
    },
    toolbox: {
        feature: {
            dataView: {show: true, readOnly: false},
            magicType: {show: true, type: ['line', 'bar']},
            restore: {show: true},
            saveAsImage: {show: true}
        }
    },
    legend: {
        data: ['当地接种比率', '接种新冠疫苗人数']
    },
    xAxis: [
        {
            type: 'category',
            data: ['广东', '北京', '海南', '安徽', '山东', '河南', '云南'],
            axisPointer: {
                type: 'shadow'
            }
        }
    ],
    yAxis: [
        {
            type: 'value',
            name: '百分比(%)',
            min: 0,
            max: 100,
            interval: 10,
            axisLabel: {
                formatter: '{value} %'
            }
        },
        {
            type: 'value',
            name: '人数(万人)',
            min: 0,
            max: 3000,
            interval: 500,
            axisLabel: {
                formatter: '{value} 万人'
            }
        }
    ],
    series: [
        {
            name: '当地接种比率',
            type: 'bar',
            data: [32.97, 81.31, 82.58, 31.01, 13.19, 18.01, 97.4]
        },
        {
            name: '接种新冠疫苗人数',
            type: 'line',
            yAxisIndex: 1,
            data: [2339.11, 1557.8, 637.48, 1172.7381, 801.48, 1020.4, 396.3]
        }
    ]
};

到这里我的期末展示就全部结束啦~

web的设计还是很有趣的,只是学不会罢了哎!

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐