新闻爬虫数据展示网站实现

本文详述了一次实现新闻爬虫数据展示网站的实验过程,包括用户注册登录、日志记录、数据分页排序及可视化功能。通过Echarts或D3实现了数据图表展示,使用ElasticSearch进行高级查询,同时提供了管理界面用于查看和管理用户。实验涵盖了分词查询、主题词排序等附加要求,使网站具备了强大的数据管理和分析能力。
摘要由CSDN通过智能技术生成

1. 实验内容

基于第一个项目爬虫爬取的数据,完成数据展示网站。

基本要求:

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

附加要求:

  1. 分词查询
  2. 主题词排序
  3. ElasticSearch

2. 实验任务

  1. 注册与登录的实现

    1. 建立用户数据库并实现注册接口;
    2. 实现登录接口(验证是否登录成功);
    3. 登陆成功后将登录信息保存到session;
    4. 在主页添加session验证;
    5. 登录界面前端。
  2. 日志

    1. 建立数据库。
    2. 添加写入日志的操作。
  3. 管理实现

    1. 实现对数据库的查询与操作;
    2. 路由实现;
    3. 管理界面前端实现。
  4. 搜索分页和排序

    1. 添加分页查询返回;
    2. 添加翻页的实现;
    3. 修改前端。
  5. 可视化

    1. 用户访问数据可视化;
    2. 爬取新闻数量可视化;
    3. 新闻热词可视化。
  6. 分词查询

    1. 对原查询进行修改。

3. 实验过程

1. 注册与登陆的实现

  1. 建立用户信息数据库
    在数据库crawl中建立一个新的表usr存放用户注册信息,包括id(自动生成)、用户名、密码、注册时间、用户权限和是否活跃五个字段。

    USE `crawl`;
    CREATE TABLE `usr` (
    `id` int(11)  NOT NULL AUTO_INCREMENT,
    `username` varchar(20) NOT NULL,
    `password` varchar(50) NOT NULL,
    `regtime` datetime DEFAULT CURRENT_TIMESTAMP,
    `is_admin` tinyint(1) DEFAULT 0,
    `active` tinyint(1) DEFAULT 1,
    PRIMARY KEY (`id`),
    UNIQUE KEY `user_id` (`id`),
    UNIQUE KEY `name` (`username`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    
  2. 实现注册接口

    注册需要不重复的用户名,因此首先要检查输入的用户名是否有重复。在确认没有重复之后,再将要使用的账号和密码插入数据库中。

    var register = function(username, password, callback) {
       var checksql = 'select username from usr where username=?';
       var checkparam = [username];
       db.query(checksql, checkparam, function(qerr, vals, fields) {
          if (qerr) {
                console.log(qerr);
                callback(qerr, null);
          } else if (vals.length !== 0){
                callback(qerr, "Duplicate username");
                
          } else {
                var sql = 'INSERT INTO usr(username, password) VALUES(?,?)';
                sqlparam = [username, password];
                db.query(sql, sqlparam, function(qerr, vals, fields) {
                   if (qerr) {
                      console.log(qerr);
                      callback(qerr, null);
                   }else{
                      callback(qerr, "Success");
                   }
                });
          }
       });
    };
    
  3. 实现登录接口

    登录逻辑:检查数据库中是否有相应账号密码的用户。有的话登陆成功,没有的话失败。要返回是否成功以及用户权限。

    var login = function(username, password, callback) {
       var checksql = 'select is_admin from usr where username=? and password=?';
       var checkparam = [username, password];
       db.query(checksql, checkparam, function(qerr, vals, fields) {
          if (qerr) {
                console.log(qerr);
                callback(qerr,null, -1, -1);
          } else if(vals.length != 1) {
                callback(qerr, "Denied", -1);
          } else {
                var is_admin = JSON.parse(JSON.stringify(vals))[0].is_admin;
                var active = JSON.parse(JSON.stringify(vals))[0].active;
                callback(qerr, "Success", is_admin, active);
          }
       });
    };
    
  4. 添加session保存登录信息

    首先在app.js里,引入session,并设置session信息。

    var session = require('express-session');
    
    app.use(session({
         
    secret: 'sessiontest',//与cookieParser中的一致
    resave: true,
    saveUninitialized: false, // 是否保存未初始化的会话
    cookie : {
         
       maxAge : 1000 * 60 * 60, // 设置 session 的有效时间,单位毫秒
    },
    }));
    

    在路由端创建登录、注册的接口,解析前端传来的数据,根据它们调用数据库接口,然后判断是否成功登录/注册,成功则写入session,并且跳转到跳转去管理页面或者新闻查看界面的url(因为后续部分功能实现的原因,重新跳转进入新闻查看界面时要要先清除部分session,所以专门编写了一个跳转用的路由接口,后面讲到跳转实现的时候会具体介绍)。

    router.post('/register', function(req, res, next) {
         
       var username = req.body.username;
       var password = req.body.password;
       var al = {
         msg:null};
       //res.render('users');
       
       usr.register(username, password, function(qerr, msg){
         
          
          if(qerr) {
         
             al["msg"] = "sql error";
             res.render('users', al);
          } else {
         
             if (msg==="Success") {
         
             req.session['username'] = username;
             res.cookie('username', username);
             res.redirect('../gotosearch');
             
             // 输出消息:注册成功,自动登录
             // 添加session和cookie
             // 跳转到index
             } else if (msg==="Duplicate username"){
         
             al["msg"] = msg;
             res.render('users', al);
             }
          }
       });
    };
    
    router.post('/login', function(req, res, next) {
         
       var username = req.body.username;
       var password = req.body.password;
       al={
         msg:null};
       //res.render('users');
       usr.login(username, password, function(qerr, msg, is_admin, active){
         
          
          if(qerr) {
         
             al["msg"] = "sql error";
             res.render('users', al);
          } else {
         
             if (msg==="Success") {
         
             if(active===0){
         
                al["msg"]="你被封号了";
                console.log(al);
                res.render('users', al);
             }
             else{
         
             req.session['username'] = username;
             res.cookie('username', username);
             // 输出消息:登录成功
             // 添加session和cookie
             if(is_admin) {
         
                req.session['is_admin'] = 1;
                res.cookie('is_admin', 1);
                res.redirect("../admin");
             } else {
         
                req.session['is_admin'] = 0;
                res.cookie('is_admin',0);
                res.redirect("../gotosearch");
             }
             }
             } else if (msg==="Denied"){
         
             al["msg"] = msg;
             res.render('users', al);
             // 输出消息:账号或密码错误
             }
          }
       });
       //res.send('respond with a resource');
    });
    

    对于退出登录,销毁session即可。在页面上,也只需要加一个表单,只要一个提交按钮,用post方式提交到/users/logout。

    router.post('/logout', function(req, res, next) {
         
       //console.log(1);
       req.session.destroy(function(err) {
         
          if(err){
         
             res.json('退出登录失败');
             return;
          }
          // req.session.loginUser = null;
          res.clearCookie('username');
          res.clearCookie('is_admin');
          var al = {
         msg:null};
          res.render('users',al);
       });
    });
    

    而对于需要登录/是管理员才能访问的页面,就在路由端添加一段判断,如果session内的信息不符合的话就返回登录界面。

    以搜索新闻页面为例:

    if(req.session['username']===undefined) {
         
       res.redirect('/users');
    }else{
         
       ...
    }
    

    同时,利用session还可以添加一些别的东西,比如读取用户名后,在页面最上方显示“欢迎某某某”,如果用户是管理员就多显示一个按钮(是一个表单)可以跳转到管理页面等等。

  5. 登录界面前端实现

    用户界面前端:有一个表单,可以输入用户名/密码,然后有两个按钮:一个提交到注册,一个提交到登录。其中,注册时要判断是否合法。

    提交按钮用onclick进行处理,设置不同的action,然后submit。其中,注册函数会调用判断合法的函数,如果不合法的话,就会用alert进行提示。onclick()调用函数如下:

    <script>
    function login(){
          
         // 跳转形式:
         // document.("表单的name值").action = “”
         // document.("表单的name值").submit = “”
          document.user_form.action="/users/login";
          document.user_form.submit();
       }
       function register() {
          
          var check = check_username(document.user_form.username.value);
          if (check!=="ok"){
          
                alert(check);
          }else{
          
                var check = check_passwd(document.user_form.password.value);
                if (check!=="ok"){
          
                alert(check);
                } else {
          
                   document.user_form.action = "/users/register";
                   document.user_form.submit();
                }
          }
       }
    
       function check_username(str) {
          
          var str2 = "ok";
       if ("" == str)
       {
          
          str2 = "用户名为空";
          return str2;
       }
       else if ((str.length < 5) || (str.length > 20))
       {
          
          str2 = "用户名必须为5 ~ 20位";
          return str2;
       }
       else if (check_other_char(str))
       {
          
          str2 = "不能含有特殊字符";
          return str2;
       }
       return str2;
       }
    
       function check_passwd(str) {
          
          var str2 = "ok";
       if ("" == str)
       {
          
          str2 = "密码为空";
          return str2;
       }
       else if ((str.length < 5) || (str.length > 50))
       {
          
          str2 = "密码必须为5 ~ 50位";
          return str2;
       }
       else if (check_other_char(str))
       {
          
          str2 = "不能含有特殊字符";
          return str2;
       }
       return str2;
       }
    
       function check_other_char(str)
       {
          
          var arr = ["&", "\\", "/", "*", ">", "<", "@", "!"];
          for (var i = 0; i < arr.length; i++)
          {
          
                for (var j = 0; j < str.length; j++)
                {
          
                   if (arr[i] == str.charAt(j))
                   {
          
                      return true;
                   }
                }
          }   
          return false;
       }
    
    </script>
    

    而数据库判断的登录/注册失败的提示消息会传到前端来,要用ejs的函数进行处理。首先判断是否有提示消息,如果有,就输出出来。

         <%if(msg !== null && msg != undefined){
         %>
             Error: <%-msg%>
         <%}%>
    

    登录界面的url是/users,所以需要路由先渲染这个页面。虽然浏览器发送的是post,但是在有的浏览器(比如safari)里,好像确认alert之后会post,所以用了all方法。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值