之前已經爬取了多個網站的新聞資料,現在要對這些資料進行整理展示,具體要求如下

首先第一步要在final-project檔案夾下npm install安裝依賴包
這裡我在安裝過程中遇見了問題,安裝一直失敗而且安裝進度非常慢,百度了一下大體了解到這是從國外的鏡像伺服器下擷取包的資源,是以猜測可能和我家的網絡有關。果然,在連接配接了學校的VPN之後再運作npm install很快就安裝完成了(有一說一,移動的網真滴不行)。
接下來需要通路之前已經安裝好的mysql資料庫,建立立兩個mysql表用來儲存使用者的記錄檔,具體過程和代碼如下
具體代碼
--建立使用者資訊資料表 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;
–記錄使用者的登陸,查詢(具體查詢語句)操作
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裡将其引入
<div class="row" style="margin-bottom: 10px;">
<label class="col-lg-2 control-label">标題關鍵字</label>
<div class="col-lg-3">
<input type="text" class="form-control" placeholder="标題關鍵字" ng-model="$parent.title1">
</div>
<div class="col-lg-1">
<select class="form-control" autocomplete="off" ng-model="$parent.selectTitle">
<option selected="selected">AND</option>
<option>OR</option>
</select>
</div>
<div class="col-lg-3">
<input type="text" class="form-control" placeholder="标題關鍵字" ng-model="$parent.title2">
</div>
</div>
<div class="row" style="margin-bottom: 10px;">
<label class="col-lg-2 control-label">内容關鍵字</label>
<div class="col-lg-3">
<input type="text" class="form-control" placeholder="内容關鍵字" ng-model="$parent.content1">
</div>
<div class="col-lg-1">
<select class="form-control" autocomplete="off" ng-model="$parent.selectContent">
<option selected="selected">AND</option>
<option>OR</option>
</select>
</div>
<div class="col-lg-3">
<input type="text" class="form-control" placeholder="内容關鍵字" ng-model="$parent.content2">
</div>
</div>
<div class="form-group">
<div class="col-md-offset-9">
<button type="submit" class="btn btn-default" ng-click="search()">查詢</button>
</div>
</div>
<table class="table table-striped">
<thead>
<tr>
<td>序号</td>
<td>标題</td>
<td>作者</td>
<td>關鍵詞</td>
<td>連結</td>
<td>釋出時間</td>
</tr>
</thead>
<tbody>
<tr ng-repeat="(key, item) in items">
<td>{{index+key}}</td>
<td>{{item.title}}</td>
<td>{{item.author}}</td>
<td>{{item.keywords}}</td>
<td>{{item.url}}</td>
<td>{{item.publish_date}}</td>
</tr>
</tbody>
</table>
<div class="row">
<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>
<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>
</div>
第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/,并進行注冊
搜尋疫情,結果如下
資料分析圖表