天天看點

nodejs爬蟲項目(二)

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

nodejs爬蟲項目(二)

首先第一步要在final-project檔案夾下npm install安裝依賴包

這裡我在安裝過程中遇見了問題,安裝一直失敗而且安裝進度非常慢,百度了一下大體了解到這是從國外的鏡像伺服器下擷取包的資源,是以猜測可能和我家的網絡有關。果然,在連接配接了學校的VPN之後再運作npm install很快就安裝完成了(有一說一,移動的網真滴不行)。

nodejs爬蟲項目(二)

接下來需要通路之前已經安裝好的mysql資料庫,建立立兩個mysql表用來儲存使用者的記錄檔,具體過程和代碼如下

nodejs爬蟲項目(二)

具體代碼

--建立使用者資訊資料表 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配置檔案

nodejs爬蟲項目(二)

接下來需要完全使用者可注冊登入網站,非注冊使用者不可登入檢視資料,對于登入和注冊時的錯誤也要有适當的提示,例如登陸時

提示使用者名或密碼輸錯,使用者不存在,注冊時,兩次密碼不一緻,使用者已存在或者注冊成功跳轉登陸頁.。

首先是登入頁面的代碼

nodejs爬蟲項目(二)

先引入先引入angular.js,這樣登陸成功會跳轉到news.html頁面,然後是注冊頁的代碼

nodejs爬蟲項目(二)

使用者可注冊登入網站,非注冊使用者不可登入檢視資料這一部分用JavaScript來實作,由于代碼比較少,就直接寫在登入頁的html裡了

nodejs爬蟲項目(二)

在登入頁路由中,首先調用userDAO,然後儲存session資訊,不然記錄使用者記錄檔時,不知道是哪位使用者進行的操作。

nodejs爬蟲項目(二)

UserDAO的代碼實作以及之前提到的session的設定如下

nodejs爬蟲項目(二)
nodejs爬蟲項目(二)

注冊操作和登出的實作,注意退出時清除session

nodejs爬蟲項目(二)
nodejs爬蟲項目(二)

然後實作查詢功能,先寫好查詢頁面的代碼,然後在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>
           
nodejs爬蟲項目(二)
nodejs爬蟲項目(二)

第52行,拼路由,get方法傳給後端處理。其中排序是按照發表時間排的,也是傳的參數,也在路由中,查詢頁路由的代碼如下

nodejs爬蟲項目(二)

用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); //事件驅動回調
            });
        }
    });
},;
           

查詢結果的展示

nodejs爬蟲項目(二)

第47行,ng-show 是在點選顯示圖表的時候,先隐藏掉這些查詢結果再顯示圖檔;也控制先點選圖表,再點選查詢的時候,将圖表顯示隐藏掉,再展示查詢結果。

當頁面清單的爬蟲資料過多時,需要對清單内容進行分頁,這邊使用了angularjs分頁的實作,不需要背景配合,前台一次性拿完所有的資料然後進行分頁展示。缺點資料量過大的時候頁面加載效率比較低,但界面上對使用者更加友好。下面是實作分頁的代碼。

nodejs爬蟲項目(二)
nodejs爬蟲項目(二)

初始化的時候,首先要顯示第一頁的内容,同時算好一共分多少頁(75行),pageList是一個最多長為5的數組,表示右下角截圖的框裡最多展示5個頁碼。

nodejs爬蟲項目(二)

當選中其它頁面的時候,由于最多顯示五個頁面,右下角的頁面數字也要随之改變,具體代碼實作如下。

nodejs爬蟲項目(二)
nodejs爬蟲項目(二)

下一步是添加資料分析圖表,以柱狀圖的代碼為例

前端代碼

$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’);

借助中間件儲存的資訊

nodejs爬蟲項目(二)

儲存的記錄檔可以在mysql資料庫中查詢,輸入select * from user_faction

nodejs爬蟲項目(二)

附上完整的示範

在final_project檔案夾下cmd運作node bin/www

nodejs爬蟲項目(二)

進入http://localhost:3000/,并進行注冊

nodejs爬蟲項目(二)

搜尋疫情,結果如下

nodejs爬蟲項目(二)
nodejs爬蟲項目(二)

資料分析圖表

nodejs爬蟲項目(二)
nodejs爬蟲項目(二)
nodejs爬蟲項目(二)