之前已经爬取了多个网站的新闻数据,现在要对这些数据进行整理展示,具体要求如下
首先第一步要在final-project文件夹下npm install安装依赖包
这里我在安装过程中遇见了问题,安装一直失败而且安装进度非常慢,百度了一下大体了解到这是从国外的镜像服务器下获取包的资源,所以猜测可能和我家的网络有关。果然,在连接了学校的VPN之后再运行npm install很快就安装完成了(有一说一,移动的网真滴不行)。
接下来需要访问之前已经安装好的mysql数据库,新建立两个mysql表用来保存用户的操作日志,具体过程和代码如下
具体代码
--创建用户信息数据表 CREATE TABLE
crawl.
user(
idINT UNSIGNED NOT NULL AUTO_INCREMENT,
usernameVARCHAR(45) NOT NULL,
passwordVARCHAR(45) NOT NULL,
registertimedatetime DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (
id), UNIQUE KEY
username_UNIQUE(
username`))
ENGINE=InnoDB DEFAULT CHARSET=utf8;
–记录用户的登陆,查询(具体查询语句)操作
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;`
然后需要在项目文件夹下建立mysql配置文件
接下来需要完全用户可注册登录网站,非注册用户不可登录查看数据,对于登录和注册时的错误也要有适当的提示,例如登陆时
提示用户名或密码输错,用户不存在,注册时,两次密码不一致,用户已存在或者注册成功跳转登陆页.。
首先是登录页面的代码
先引入先引入angular.js,这样登陆成功会跳转到news.html页面,然后是注册页的代码
用户可注册登录网站,非注册用户不可登录查看数据这一部分用JavaScript来实现,由于代码比较少,就直接写在登录页的html里了
在登录页路由中,首先调用userDAO,然后保存session信息,不然记录用户操作日志时,不知道是哪位用户进行的操作。
UserDAO的代码实现以及之前提到的session的设置如下
注册操作和退出登录的实现,注意退出时清除session
然后实现查询功能,先写好查询页面的代码,然后在news.html里将其引入
序号
标题
作者
关键词
链接
发布时间
{{index+key}}
{{item.title}}
{{item.author}}
{{item.keywords}}
{{item.url}}
{{item.publish_date}}
第52行,拼路由,get方法传给后端处理。其中排序是按照发表时间排的,也是传的参数,也在路由中,查询页路由的代码如下
用newsDAO.search函数实现查询词支持布尔表达式,主要是拼起sql。
var mysql = require(‘mysql’); var mysqlConf = require(’…/conf/mysqlConf’); var pool =
mysql.createPool(mysqlConf.mysql);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); //事件驱动回调 }); } }); },;
第47行,ng-show 是在点击显示图表的时候,先隐藏掉这些查询结果再显示图片;也控制先点击图表,再点击查询的时候,将图表显示隐藏掉,再展示查询结果。
当页面列表的爬虫数据过多时,需要对列表内容进行分页,这边使用了angularjs分页的实现,不需要后台配合,前台一次性拿完所有的数据然后进行分页展示。缺点数据量过大的时候页面加载效率比较低,但界面上对用户更加友好。下面是实现分页的代码。
初始化的时候,首先要显示第一页的内容,同时算好一共分多少页(75行),pageList是一个最多长为5的数组,表示右下角截图的框里最多展示5个页码。
当选中其它页面的时候,由于最多显示五个页面,右下角的页面数字也要随之改变,具体代码实现如下。
下一步是添加数据分析图表,以柱状图的代码为例
前端代码
$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 {
// 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: {},
legend: {
data: ['新闻发布数']
},
xAxis: {
data: newdata["xdata"]
},
yAxis: {},
series: [{
name: '新闻数目',
type: 'bar',
data: newdata["ydata"]
}]
};
// 使用刚指定的配置项和数据显示图表。
myChart.setOption(option);
}
},
function (err) {
$scope.msg = err.data;
});
};
路由代码
router.get(’/histogram’, 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();
});
}
});
最后将用户注册、登录、查询等操作记入数据库中的日志,直接在app.js中,引入var logger = require('morgan’);
借助中间件保存的信息
保存的操作日志可以在mysql数据库中查询,输入select * from user_faction
附上完整的演示
在final_project文件夹下cmd运行node bin/www
进入http://localhost:3000/,并进行注册
搜索疫情,结果如下
数据分析图表