新闻爬虫展示网站搭建
基于第一个项目爬取的数据,搭建新闻爬虫数据展示的网站
网站首页
一、数据库修改
数据库里新增了用户表、日志表
用户表属性包括用户id(主键),用户名(唯一),密码,权限(默认为true,即用户有查看网站数据的权限)
日志表属性包括日志id(主键),用户名,用户操作,操作时间
CREATE TABLE users (
id_users serial PRIMARY key,
username varchar(255) not null UNIQUE,
password varchar(255) not null,
power boolean not null DEFAULT TRUE
);
CREATE TABLE logs(
id_logs serial PRIMARY KEY,
username varchar(255) not null,
action varchar(255) not null,
operation_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
二、用户登录注册功能实现
注册界面后端功能:
1.获取前端用户输入的用户名和密码
2.在用户表查询该用户,若用户已经存在,提醒用户已经注册过;若用户不存在,用户表插入一条数据,包括(用户名,密码,权限(true)),日志表插入一条数据,包括(用户名,用户操作(register),操作时间)
3.返回用户操作的结果
router.post('/register', function (req, res) {
var response = {}
var name = req.body.name;
// console.log(name);
var password = req.body.passwd;
// console.log(password);
var fetchSql = "SELECT username FROM users WHERE username = $1;";
var fetch_name_Sql_Params = [name];
pgsql.query(fetchSql, fetch_name_Sql_Params, function (err, result) {
if (err) {
console.log(err);
return;
}
if (result.rows[0] == null) { //该username没有被注册过
var AddSql = 'INSERT INTO users (username, password,power)'
+ 'VALUES ($1, $2,$3);';
var newsAddSql_Params = [name, password, 'true'];
pgsql.query(AddSql, newsAddSql_Params, function (err, result) {
if (err) {
response.status = "注册失败";
// console.log(response);
res.end(JSON.stringify(response));
return;
} else {
var fetchInsertSql = 'INSERT INTO logs (username, action)' + 'VALUES ($1, $2);';
var fetchInsertSql_Params = [name, 'register'];
pgsql.query(fetchInsertSql, fetchInsertSql_Params, function (err, result) {
if (err) {
console.log(err);
}
})
response.status = "注册成功";
res.end(JSON.stringify(response));
return;
}
});
} else {
response.status = "该用户已经注册过";
console.log(response);
res.end(JSON.stringify(response));
return
}
});
});
注册功能前端界面:
1.编写了一个注册界面的css样式文件,引用该样式
2.表单输入用户名和用户密码
3.将表单获得的数据传到后端,得到响应
4.后端响应若为注册成功,则跳转到用户登录界面;若为注册失败,则弹出警告框注册失败
$("#register_button").click(function() {
var oUname = document.getElementById("uname");
var oUpass = document.getElementById("upass");
var params = '/register';
$.post(params, {name: oUname.value,passwd: oUpass.value},function(text, status) {
// console.log(text);
JSON.parse(text, function(k,status) {
if(status=="注册成功") {
alert("注册成功");
window.location.href = "login";
ç }
if(status=="注册失败"){
window.alert("注册失败");
}
if(status=="该用户已经注册过"){
alert("该用户已经注册过");
window.location.href = "login";
}
})
})
});
登录界面后端功能:
1.获取前端用户输入的用户名和密码
2.在用户表查询该用户,若用户已经存在,检查该用户密码与用户输入的密码是否一致,同时检查用户是否有权限,密码正确且用户有权限则向日志表插入一条数据,包括(用户名,用户操作(login),操作时间);若用户不存在提示用户还未注册
3.返回用户操作的结果
登录界面前端界面:
1.编写了一个登录界面的css样式文件,引用该样式
2.表单输入用户名和用户密码
3.将表单获得的数据传到后端,得到响应
4.后端响应若为登录成功,判断用户名,若为管理员,则跳转到管理界面,否则跳转到查看爬虫数据的界面;若为密码错误、用户没有权限,则弹出警告框;若为用户还未注册,则跳转到注册界面
$("#login_button").click(function () {
var oUname = document.getElementById("uname")
var oUpass = document.getElementById("upass")
var params = '/login';
$.post(params, { name: oUname.value, passwd: oUpass.value }, function (text, status) {
JSON.parse(text, function (k, v) {
if (v == '登录成功') {
if (oUname.value == 'cy') {
alert(v);
console.log("登录成功");
window.location.href = "administrate";
} else {
alert(v);
console.log("登录成功");
window.location.href = "search";
}
}
if (v == '密码错误') {
alert(v);
console.log("密码错误");
}
if (v == '该用户名没有被注册') {
alert(v);
console.log("该用户名没有被注册");
window.location.href = "register";
}
if (v == '该用户没有权限') {
alert(v);
console.log("该用户没有权限");
}
})
})
});
三、爬虫数据查询(第一个项目已经实现)
采用bootstrap框架的表单样式,以及bootstrapTable展示查询结果,查询结果可以分页显示,同时,从数据库的news表中查询数据时按照新闻发表时间降序排列
关键词时间热度图用echarts柱状图显示
四、爬虫数据图表显示
1.下拉列表选择需要展示的图表:包括折线图、饼图、词云(echarts)
2.折线图展示了新闻总数随时间变化的趋势,可以看到2021-04-07之后新闻数量猛增
获取新闻总数随时间变化:数据库news表查询按照发表时间统计新闻数目,并按发表时间降序排列
router.get('/get_date_num', function (req, res) {
var username = req.cookies.username;
res.writeHead(200, { 'Content-Type': 'text/html;charset=utf-8' });
var fetchSql = "SELECT publish_date,count(*) FROM news group by publish_date order by publish_date;";
pgsql.query_noparam(fetchSql, function (err, result, fields) {
var fetchAddSql = 'INSERT INTO logs (username, action)' + 'VALUES ($1, $2);';
var fetchAddSql_Params = [username, 'view chart'];
pgsql.query(fetchAddSql, fetchAddSql_Params, function(err,result) {
if(err) {
console.log(err);
}
})
// console.log(result.rows);
res.end(JSON.stringify(result.rows));
// console.log(res);
});
});
3.饼图展示了三个网站的新闻数对比,可以看出网易新闻网爬取的新闻数据最多,雪球网最少
获取三个网站新闻数目:数据库news表查询按照源网站名统计新闻数目
router.get('/get_source_num', function (req, res) {
var username = req.cookies.username;
res.writeHead(200, { 'Content-Type': 'text/html;charset=utf-8' });
// console.log(req.query.keyword);
var fetchSql = "SELECT source_name,count(*) FROM news group by source_name;";
pgsql.query_noparam(fetchSql, function (err, result, fields) {
var fetchAddSql = 'INSERT INTO logs (username, action)' + 'VALUES ($1, $2);';
var fetchAddSql_Params = [username, 'view chart'];
pgsql.query(fetchAddSql, fetchAddSql_Params, function(err,result) {
if(err) {
console.log(err);
}
})
// console.log(result.rows);
res.end(JSON.stringify(result.rows));
// console.log(res);
});
});
4.词云图展示了新闻关键词中出现频率较高的词汇,从图中可以看出是疫苗、中国、2021。
获取出现频率较高的关键词:数据库关键词表查询按照关键词统计关键词数目
绘制词云时展示了数量前500的关键词
router.get('/get_keyword_num', function (req, res) {
var username = req.cookies.username;
res.writeHead(200, { 'Content-Type': 'text/html;charset=utf-8' });
var fetchSql = "SELECT word,count(*) as num FROM splitwords group by word order by num desc;";
pgsql.query_noparam(fetchSql, function (err, result, fields) {
var fetchAddSql = 'INSERT INTO logs (username, action)' + 'VALUES ($1, $2);';
var fetchAddSql_Params = [username, 'view chart'];
pgsql.query(fetchAddSql, fetchAddSql_Params, function(err,result) {
if(err) {
console.log(err);
}
})
// console.log(JSON.stringify(result.rows));
res.end(JSON.stringify(result.rows));
});
});
五、管理者界面
第一个列表展示了所有的用户,对每个用户添加了改变权限的按钮和查看用户日志的按钮,点击查看用户日志的按钮,显示第二张表格
改变用户权限:
禁用用户,即将用户表中该用户权限设为false
启用用户,即将用户表中该用户权限设为true
$('[name="status"]').bootstrapSwitch({
onText: "启用", // 设置ON文本
offText: "禁用", // 设置OFF文本
onColor: "success",// 设置ON文本颜色(info/success/warning/danger/primary)
offColor: "danger", // 设置OFF文本颜色 (info/success/warning/danger/primary)
onSwitchChange: function (event, state) {
var id = this.value;
var username = $("#user_table").bootstrapTable("getData")[id].username;
if (state == true) {
console.log("true");
$.get("administrate_off?username=" + username, function () {
});
} else {
console.log("false");
$.get("administrate_open?username=" + username, function () {
});
}
}
})
router.get('/administrate_off', function (req, res) {
var response = {};
var fetchDeleteSql = "UPDATE users SET power = 'false' WHERE username = $1;";
var fetch_Sql_Params = [req.query.username];
pgsql.query(fetchDeleteSql, fetch_Sql_Params, function (err, result, fields) {
if (err) {
console.log(err);
response.status = false;
res.end(JSON.stringify(response));
}
response.status = true;
res.end(JSON.stringify(response));
})
});
六、扩展功能
1.实现对爬虫数据中文分词的查询(第一个项目已经实现,采用nodejieba对新闻内容进行分词,去除停用词后,构建关键词表,实现查询)
2.用Elastic Search+Kibana展示爬虫的数据结果
步骤:
安装jdk
安装解压 Elasticsearch、kibana
启动Elasticsearch 运行bin目录下bat文件
启动kibana 运行bin目录下bat文件
访问Elasticsearch http://localhost:9200/
访问kibana http://localhost:5601/
将postgresql数据库中的新闻表和关键词表导出为csv文件,再导入kibana
利用kibana上的图例绘制图表
利用kibana的dashboard展示绘制的图表
绘制了新闻发表数和新闻发布时间的水平条形图、关键词的词云图(展示数目最多的100个词)、来源网站新闻数的环形图、新闻发表数和新闻发布时间的垂直面积图