WEB编程:期末展示

期末大作业展示:

一、项目要求

在这里插入图片描述

1、用户可注册登录网站,非注册用户不可登录查看数据
2、用户注册、登录、查询等操作记入数据库中的日志
3、爬虫数据查询结果列表支持分页和排序
4、用Echarts或者D3实现3个以上的数据分析图表展示在网站中
5、实现一个管理端界面,可以查看(查看用户的操作记录)和管理(停用启用)注册用户。

二、简单回顾

我们希望实现这样一个有着基本注册、查询功能的网站。在之前的工作中,我已经搭建好了一个简单的网站,来实现简单的关键词查找功能,请看:
在这里插入图片描述

三、准备工作

1、express框架安装

express是一个简洁而灵活的node.js web应用框架,提供一系列强大特性帮助创建各种web应用。
使用express可以快速地搭建一个功能完整的网站。

安装过程

npm install -g express-generator
这样准备工作已经完成。

2、项目框架

2.1 数据库准备
CREATE TABLE `crawl`.`user` ( 
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,  
`username` VARCHAR(45) NOT NULL,  
`password` VARCHAR(45) NOT NULL,  
`registertime` datetime DEFAULT CURRENT_TIMESTAMP,  
PRIMARY KEY (`id`),  
UNIQUE KEY `username_UNIQUE` (`username`))ENGINE=InnoDB DEFAULT CHARSET=utf8;

这是在crawl数据库中建立了一个名叫user的表格。为了记录该网站的用户信息。

CREATE TABLE `crawl`.`user_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;

以上是建立了一个名叫user_action的表格。一个用来查看注册的用户;另一个用来记录用户的行为。
注意:以上两个表格都是在数据库中创建的,即将该段代码写入mysql中。

2.2 数据库配置
module.exports = {
    mysql: {
        host: 'localhost',
        user: 'root',
        password: 'root',
        database:'crawl',
        // 最大连接数,默认为10
        connectionLimit: 10
    }
};

这样做的目的是建立一个连接mysql的配置文件。

2.3 用户界面

我们希望看到,登录时:如果用户名或密码错误,将发起提醒;如果用户没有注册,则提醒用户不存在。注册时:如果两次密码不一致,进行提醒;如果用户已经存在,给出提醒;如果新用户注册成功,自动跳转登录页面。

首先cmd运行我的代码,这时出现了登录or注册页面:
在这里插入图片描述
若一个新用户点击“login”键,会自动跳转“register”页面。
之后,会有关于新闻搜索的界面显示。同时,点击“图标”键出现柱状图、折线图等的直观分析。

四、功能实现

3.1 登录功能

在网页端,用check函数检查用户密码是否输入正确,如果输入正确,会跳转到news.html界面,即成功登陆。如果密码错误,就会提出警告。

$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;
                    });

3.2 注册功能

注册功能和登录是类似的,其中,第一遍add_password输入用户密码,然后confirm_password用来确认密码。

 <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 class="alert alert-warning" ng-if="msg && msg!='ok'">
     <a href="#" class="close" data-dismiss="alert">&times;</a>
          <strong>警告!</strong>{{msg}}
               </div>

报错情况:密码两次不一致

3.3 路由代码

当获取到密码时,将自动检测匹配度;
如果输入密码正确,发送一个json响应,同时“ok”,同时将此次操作保存到服务器内部;反之,如果密码错误或其他,msg不会有正确提示。

var userDAO = require('../dao/userDAO');
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:'用户名或密码错误!请检查后输入'});
      }

3.4 查看日志(管理端界面)

最开始我认为日志需要我记录下每一次操作痕迹,手动写入数据库中。经过与同学们的交流,我了解到可以运用node.js中的express框架使用Morgan中间件记录日志。

var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var session = require('express-session');
var logger = require('morgan');//Morgan中间件记录日志

另外,session技术可以帮助我。在WEB开发中,服务器可以为每个用户浏览器创建一个会话对象(session对象),注意:一个浏览器独占一个session对象(默认情况下)。因此,在需要保存用户数据时,服务器程序可以把用户数据写到用户浏览器独占的session中,当用户使用浏览器访问其它程序时,其它程序可以从用户的session中取出该用户的数据,为用户服务。

app.use(session({
  secret: 'sessiontest',
  resave: true,
  saveUninitialized: false, 
  cookie : {
    maxAge : 1000 * 60 * 60, 
  },
}));

在这一番操作之后,我得到了想要的结果。
进入我的数据库,输入:

select * from user_action;

显示:
在这里插入图片描述

3.5 查询功能

在这里插入图片描述
为了实现查询词支持布尔表达式,我去了解了一下有关概念。
即输入“中国”and“世界”,所出现的内容标题必须包含这两个关键词;而输入“中国”or“世界”,所出现的内容标题要么包含“中国”,要么包含“世界”。
查询数据:

$scope.search = function () {
        var title1 = $scope.title1;
        var title2 = $scope.title2;
        var selectTitle = $scope.selectTitle;
        var content1 = $scope.content1;
        var content2 = $scope.content2;
        var selectContent = $scope.selectContent;
        var sorttime = $scope.sorttime;

有时读者不输入特殊词,则默认显示所有信息(利用正则表达式):

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

结果是:
在这里插入图片描述

3.6 分页功能

这里再简单地说明一下,查询到的新闻如何进行分页,我选择直接在HTML文件中实现分页功能(利用angular实现):

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

为了页面的简洁,我选择一页展示4条新闻,最多不展示超过5页的内容:

$scope.initPageSort=function(item){
        $scope.pageSize=4;  //每页显示的数据量是可以随意更改的
        $scope.selPage = 1;
        $scope.data = item;
        $scope.pages = Math.ceil($scope.data.length / $scope.pageSize); 
        //分页数
        $scope.pageList = [];//后面6页之后不会全部列出
        $scope.index = 1;
        
        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);

展示一下:
在这里插入图片描述

3.7 排序功能

杂乱的信息无法给人一个好印象,我将用时间排序,来使信息有序起来:

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

展示:
在这里插入图片描述

3.8 Echart图表

经过老师的介绍,我了解到Echart.js的作用:ECharts,一个纯 Javascript 的图表库,可以流畅的运行在PC 和移动设备上,兼容当前绝大部分浏览器(IE8/9/10/11,Chrome,Firefox,Safari等),底层依赖轻量级的 Canvas 类库 ZRender,提供直观,生动,可交互,可高度个性化定制的数据可视化图表。

ECharts 提供了常规的折线图,柱状图,散点图,饼图,K线图,用于统计的盒形图,用于地理数据可视化的地图,热力图,线图,用于关系数据可视化的关系图,treemap,多维数据可视化的平行坐标,还有用于 BI 的漏斗图,仪表盘,并且支持图与图之间的混搭。

那么如何应用到我的网页中呢?
首先,我想做一个词云:

$scope.wordcloud = function () {
        $scope.isShow = false;
        $http.get("/news/wordcloud").then(
            function (res) {
                if(res.data.message=='url'){
                    window.location.href=res.data.result;
                }else {
           var mainContainer = document.getElementById('main1');
                  var chart = echarts.init(mainContainer);
                  var data = [];
                  for (var name in res.data.result) {
                        data.push({
                            name: name,
                            value: Math.sqrt(res.data.result[name])
                        })
                    }
                    var maskImage = new Image();
                    maskImage.src = './images/logo.png';
                    var option = {
                        title: {
                            text: '所有新闻内容的鲸鱼词云'
                        },

展现如下:
在这里插入图片描述
(关键词为“中国”)
其次,我将要做一个展现不同时期新闻数量的柱状图,

$scope.histogram = function () {
        $scope.isShow = false;
        $http.get("/news/histogram")
            .then(
                function (res) {
                   if(res.data.message=='url'){
                        window.location.href=res.data.result;
                    }else {
                        let xdata = [], ydata = [], newdata;
                        var pattern = /\d{4}-(\d{2}-\d{2})/;
                        res.data.result.forEach(function (element) {
                            xdata.push(pattern.exec(element["x"])[1]);
                            ydata.push(element["y"]);
                        });
                        newdata = {"xdata": xdata, "ydata": ydata};
                        var option = {
                            title: {
                                text: '有关新闻发布数量随时间的变化柱状图'
                            },
                            tooltip: {},
                            legend: {
                                data: ['新闻发布数']
                            },
                            xAxis: {
                                data: newdata["xdata"]
                            },
                            yAxis: {},
                            series: [{
                                name: '新闻数目',
                                type: 'bar',
                                data: newdata["ydata"]
                            }]
                        };
                },
    };

(代码中已经指定了横轴和纵轴)
在这里插入图片描述
最后,我将用一个饼状图来展示数据库中新闻编辑的信息:

$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) { newdata.push({name: pattern.exec(element["x"]), value: element["y"]});
                        
                    });

为了这个饼状图我想了两天整,试了很多种方法,还是报错;最后,一次和别人的交流启发了我:是不是传参数的时候出现问题了?之后我发现,一个变量没有定义,删掉重新修改后,展示如下:
在这里插入图片描述
胜利!
还没完哦,最后还有一个折线图。为了解近段时间以来我国有关疫情的报道数量,我将用折线图展示。一开始,这个折线图怎么也出现不了,不是没有横纵坐标轴就是没有数据,但是网页也没有报错,还是代码出了问题。一开始,我原有的一行代码为ydata.push(element[“count(*)”]);此时仅有坐标轴而没有数据;经过修改为ydata.push(element[“count”]);成功出现了数据。

$scope.line = function () {
        $scope.isShow = false;
        $http.get("/news/line").then(
            function (res) {
                console.log(res);
                if(res.data.message=='url')
                {
                    window.location.href=res.data.result;
                }
                else{
                    let xdata = [], ydata = [], newdata;
                    var pattern = /\d{4}-(\d{2}-\d{2})/;
                    res.data.result.forEach(function(element){
                    console.log(element);
                    xdata.push(pattern.exec(element["publish_date"])[1]);
                    //ydata.push(element["count(*)"]);
                    ydata.push(element["count"]);
                    });
                    newdata = {"xdata":xdata, "ydata":ydata};
                    var myChart = echarts.init(document.getElementById("main1"));

折线图如下:
在这里插入图片描述
至此,四个图全部做好了。

五、项目回顾

通过本次项目的实践,我感受到了研究前后端实现的乐趣。虽然期间也遇到了很多困难,比如各种花样百出的报错信息、界面无法显示等等。但是通过自己的思索,还是明白了解决这些问题的方法。由于自己能力所限,页面仍然称不上美观(页面红配绿是我本人了),但是对web编程的理解更加深刻了。
最后,感谢老师和助教的指导,你们辛苦啦!
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
目标检测(Object Detection)是计算机视觉领域的一个核心问题,其主要任务是找出图像中所有感兴趣的目标(物体),并确定它们的类别和位置。以下是对目标检测的详细阐述: 一、基本概念 目标检测的任务是解决“在哪里?是什么?”的问题,即定位出图像中目标的位置并识别出目标的类别。由于各类物体具有不同的外观、形状和姿态,加上成像时光照、遮挡等因素的干扰,目标检测一直是计算机视觉领域最具挑战性的任务之一。 二、核心问题 目标检测涉及以下几个核心问题: 分类问题:判断图像中的目标属于哪个类别。 定位问题:确定目标在图像中的具体位置。 大小问题:目标可能具有不同的大小。 形状问题:目标可能具有不同的形状。 三、算法分类 基于深度学习的目标检测算法主要分为两大类: Two-stage算法:先进行区域生成(Region Proposal),生成有可能包含待检物体的预选框(Region Proposal),再通过卷积神经网络进行样本分类。常见的Two-stage算法包括R-CNN、Fast R-CNN、Faster R-CNN等。 One-stage算法:不用生成区域提议,直接在网络中提取特征来预测物体分类和位置。常见的One-stage算法包括YOLO系列(YOLOv1、YOLOv2、YOLOv3、YOLOv4、YOLOv5等)、SSD和RetinaNet等。 四、算法原理 以YOLO系列为例,YOLO将目标检测视为回归问题,将输入图像一次性划分为多个区域,直接在输出层预测边界框和类别概率。YOLO采用卷积网络来提取特征,使用全连接层来得到预测值。其网络结构通常包含多个卷积层和全连接层,通过卷积层提取图像特征,通过全连接层输出预测结果。 五、应用领域 目标检测技术已经广泛应用于各个领域,为人们的生活带来了极大的便利。以下是一些主要的应用领域: 安全监控:在商场、银行
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值