一、前言
基于上一个作业完成了数据爬取之后,接下来就要进行如何将爬取的数据进行展示。
要求:
二、实现网站
1.网站注册/登录
// 登录时,检查用户输入的账户密码是否与数据库中的一致
$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;
});
}
};
});
就如同平时的网站注册/登录一样,用户需要注册并登录后才能进入网站查询相关数据;
网站样式:
这样就能够注册并登录了。
2.操作记录
既然用户要登录,那么需要记录用户的数据以及在网站内的操作,于是要建立两个表user和user_action来分别记录用户和用户的操作
先建立表格:
建立成功!
尝试注册了好几个账号之后,进行用户查询:
注册的用户成功记录在表格user中。
(关于操作日志的记录,在下文操作说明之后再在后面展示)
3.一系列的操作
(1)新闻查询
// 查询数据
$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;
// 检查用户传的参数是否有问题
//用户有可能这样输入:___ and/or 新冠(直接把查询词输在了第二个位置)
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}`;
$http.get(myurl).then(
function (res) {
if(res.data.message=='data'){
$scope.isisshowresult = true; //显示表格查询结果
// $scope.searchdata = res.data;
$scope.initPageSort(res.data.result)
}else {
window.location.href=res.data.result;
}
},function (err) {
$scope.msg = err.data;
});
};
用户能根据关键词查询相关新闻:
可以看到成功查询了
但是在查询过程中下方分页只有前一页与后一页,对于页码多的可能需要首页和末页,于是对js和html代码进行修改:
//首页
$scope.first = function () {
$scope.selectPage(1);
};
//末页
$scope.last = function () {
$scope.selectPage($scope.pages);
};
<li>
<a ng-click="first()" role="button"><span role="button">首页</span></a>
</li>
<li>
<a ng-click="last()" role="button"><span role="button">末页</span></a>
</li>
增加首页与末页的按钮,效果如下:
按钮也有效果 (csdn放不了视频,没办法。视频上传b站结果被退回了,怕不是侵权了 )
(2)表格/图
既然是数据统计,那么就要有统计图表格,有柱状图,饼图,折线图等;
1.柱状图:
$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;
});
};
展示结果:
将鼠标移到柱上可以查看相应个数
2.饼状图
$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);
}
;
}
});
};
在这之中:
var pattern = /./;//匹配名字
这一行匹配的是名字,由于老师给的实例中国新闻网中均为责任编辑:xxx而我爬的一些网站并非如此,所以要改动这行,否则饼状图无法显示。但是怎么改总有一部分无法显示,研究了好久也没研究出来,所以只能搞个半成品了。(能力还需提高)
3.折线图:
$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);
}
}
});
};
但是这里只能显示的是疫情该词的出现频率,如果要改换要到route中的js文件中:
var keyword = '疫情'; //也可以改进,接受前端提交传入的搜索词
需要直接在这个文件中改,可以接受前端搜索词,但是我无论怎么改进就是不行,进行过了各种尝试,改了之后,折线图可能就无法显示,所以就强行改js文件了。
(看来还得继续深造)
4.词云
词云:由词汇组成类似云的彩色图形。(百度)
$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: '所有新闻内容 jieba分词 的词云展示'
},
series: [{
type: 'wordCloud',
sizeRange: [12, 60],
rotationRange: [-90, 90],
rotationStep: 45,
gridSize: 2,
shape: 'circle',
maskImage: maskImage,
drawOutOfBound: false,
textStyle: {
normal: {
fontFamily: 'sans-serif',
fontWeight: 'bold',
// Color can be a callback function or a color string
color: function () {
// Random color
return 'rgb(' + [
Math.round(Math.random() * 160),
Math.round(Math.random() * 160),
Math.round(Math.random() * 160)
].join(',') + ')';
}
},
emphasis: {
shadowBlur: 10,
shadowColor: '#333'
}
},
data: data
}]
};
maskImage.onload = function () {
// option.series[0].data = data;
chart.clear();
chart.setOption(option);
};
window.onresize = function () {
chart.resize();
};
}
});
}
});
这里使用了nodejieba,一个分词系统
出现形状是根据图片文件而确定的,替换文件会有不同样子。
maskImage.src = './images/logo.png';
只要将logo.png样式换了就有不同效果,换成中国地图的样式后(由于词数不够或加载原因,可能不全):
4.操作记录
既然用户已经在网站上进行了一系列的操作,那就回到之前,可用mysql里的user_arction表格记录操作:
操作记录很多,就放一部分了。
三、总结
大部分代码是依靠老师的,自己也进行了探索。其中,首末页的成功建立以及词云的不同样式的探索成功让我感觉很开心。当然,有些东西尝试过探索但是还是失败了,可能还是需要仔细学习,毕竟只了解了一部分内容还是不够的,希望之后能够继续学下去,了解更多!