成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

手把手教你寫帶登錄的NodeJS爬蟲+數(shù)據(jù)展示

cpupro / 1981人閱讀

摘要:可以通過傳入待刪除數(shù)組元素組成的數(shù)組進(jìn)行一次性刪除。如果后臺(tái)返回的為表示登錄的已失效,需要重新執(zhí)行。等所有的異步執(zhí)行完畢后,再執(zhí)行回調(diào)函數(shù)。回調(diào)函數(shù)的參數(shù)是每個(gè)函數(shù)返回?cái)?shù)據(jù)組成的數(shù)組。

其實(shí)在早之前,就做過立馬理財(cái)?shù)匿N售額統(tǒng)計(jì),只不過是用前端js寫的,需要在首頁的console調(diào)試面板里粘貼一段代碼執(zhí)行,點(diǎn)擊這里。主要是通過定時(shí)爬取https://www.lmlc.com/s/web/home/user_buying異步接口來獲取數(shù)據(jù)。然后通過一定的排重算法來獲取最終的數(shù)據(jù)。但是這樣做有以下缺點(diǎn):

代碼只能在瀏覽器窗口下運(yùn)行,關(guān)閉瀏覽器或者電腦就失效了

只能爬取一個(gè)頁面的數(shù)據(jù),不能整合其他頁面的數(shù)據(jù)

爬取的數(shù)據(jù)無法存儲(chǔ)到本地

上面的異步接口數(shù)據(jù)會(huì)部分過濾,導(dǎo)致我們的排重算法失效

由于最近學(xué)習(xí)了node爬蟲相關(guān)知識(shí),我們可以在后臺(tái)自己模擬請(qǐng)求,爬取頁面數(shù)據(jù)。并且我開通了阿里云服務(wù)器,可以把代碼放到云端跑。這樣,1、2、3都可以解決。4是因?yàn)橹安恢肋@個(gè)ajax接口是每三分鐘更新一次,這樣我們可以根據(jù)這個(gè)來排重,確保數(shù)據(jù)不會(huì)重復(fù)。說到爬蟲,大家想到的比較多的還是python,確實(shí)python有Scrapy等成熟的框架,可以實(shí)現(xiàn)很強(qiáng)大的爬取功能。但是node也有自身的優(yōu)點(diǎn),憑借強(qiáng)大的異步特性,可以很輕松的實(shí)現(xiàn)高效的異步并發(fā)請(qǐng)求,節(jié)省cpu的開銷。其實(shí)node爬蟲還是比較簡(jiǎn)單的,下面我們就來分析整個(gè)爬蟲爬取的流程和最終如何展示數(shù)據(jù)的。

線上地址

一、爬蟲流程

我們最終的目標(biāo)是實(shí)現(xiàn)爬取立馬理財(cái)每日的銷售額,并知道賣了哪些產(chǎn)品,每個(gè)產(chǎn)品又被哪些用戶在什么時(shí)間點(diǎn)買的。首先,介紹下爬蟲爬取的主要步驟:

1. 結(jié)構(gòu)分析

我們要爬取頁面的數(shù)據(jù),第一步當(dāng)然是要先分析清楚頁面結(jié)構(gòu),要爬哪些頁面,頁面的結(jié)構(gòu)是怎樣的,需不需要登錄;有沒有ajax接口,返回什么樣的數(shù)據(jù)等。

2. 數(shù)據(jù)抓取

分析清楚要爬取哪些頁面和ajax,就要去抓取數(shù)據(jù)了。如今的網(wǎng)頁的數(shù)據(jù),大體分為同步頁面和ajax接口。同步頁面數(shù)據(jù)的抓取就需要我們先分析網(wǎng)頁的結(jié)構(gòu),python抓取數(shù)據(jù)一般是通過正則表達(dá)式匹配來獲取需要的數(shù)據(jù);node有一個(gè)cheerio的工具,可以將獲取的頁面內(nèi)容轉(zhuǎn)換成jquery對(duì)象,然后就可以用jquery強(qiáng)大的dom API來獲取節(jié)點(diǎn)相關(guān)數(shù)據(jù), 其實(shí)大家看源碼,這些API本質(zhì)也就是正則匹配。ajax接口數(shù)據(jù)一般都是json格式的,處理起來還是比較簡(jiǎn)單的。

3. 數(shù)據(jù)存儲(chǔ)

抓取的數(shù)據(jù)后,會(huì)做簡(jiǎn)單的篩選,然后將需要的數(shù)據(jù)先保存起來,以便后續(xù)的分析處理。當(dāng)然我們可以用MySQL和Mongodb等數(shù)據(jù)庫存儲(chǔ)數(shù)據(jù)。這里,我們?yōu)榱朔奖?,直接采用文件存?chǔ)。

4. 數(shù)據(jù)分析

因?yàn)槲覀冏罱K是要展示數(shù)據(jù)的,所以我們要將原始的數(shù)據(jù)按照一定維度去處理分析,然后返回給客戶端。這個(gè)過程可以在存儲(chǔ)的時(shí)候去處理,也可以在展示的時(shí)候,前端發(fā)送請(qǐng)求,后臺(tái)取出存儲(chǔ)的數(shù)據(jù)再處理。這個(gè)看我們要怎么展示數(shù)據(jù)了。

5. 結(jié)果展示

做了這么多工作,一點(diǎn)展示輸出都沒有,怎么甘心呢?這又回到了我們的老本行,前端展示頁面大家應(yīng)該都很熟悉了。將數(shù)據(jù)展示出來才更直觀,方便我們分析統(tǒng)計(jì)。

二、爬蟲常用庫介紹 1. Superagent

Superagent是個(gè)輕量的的http方面的庫,是nodejs里一個(gè)非常方便的客戶端請(qǐng)求代理模塊,當(dāng)我們需要進(jìn)行g(shù)et、post、head等網(wǎng)絡(luò)請(qǐng)求時(shí),嘗試下它吧。

2. Cheerio

Cheerio大家可以理解成一個(gè) Node.js 版的 jquery,用來從網(wǎng)頁中以 css selector 取數(shù)據(jù),使用方式跟 jquery 一模一樣。

3. Async

Async是一個(gè)流程控制工具包,提供了直接而強(qiáng)大的異步功能mapLimit(arr, limit, iterator, callback),我們主要用到這個(gè)方法,大家可以去看看官網(wǎng)的API。

4. arr-del

arr-del是我自己寫的一個(gè)刪除數(shù)組元素方法的工具。可以通過傳入待刪除數(shù)組元素index組成的數(shù)組進(jìn)行一次性刪除。

5. arr-sort

arr-sort是我自己寫的一個(gè)數(shù)組排序方法的工具。可以根據(jù)一個(gè)或者多個(gè)屬性進(jìn)行排序,支持嵌套的屬性。而且可以再每個(gè)條件中指定排序的方向,并支持傳入比較函數(shù)。

三、頁面結(jié)構(gòu)分析

先屢一下我們爬取的思路。立馬理財(cái)線上的產(chǎn)品主要是定期和立馬金庫(最新上線的光大銀行理財(cái)產(chǎn)品因?yàn)槭掷m(xù)比較麻煩,而且起投金額高,基本沒人買,這里不統(tǒng)計(jì))。定期我們可以爬取理財(cái)頁的ajax接口:https://www.lmlc.com/web/product/product_list?pageSize=10&pageNo=1&type=0。(update: 定期近期沒貨,可能看不到數(shù)據(jù),可以看1月19號(hào)以前的)數(shù)據(jù)如下圖所示:

這里包含了所有線上正在銷售的定期產(chǎn)品,ajax數(shù)據(jù)只有產(chǎn)品本身相關(guān)的信息,比如產(chǎn)品id、籌集金額、當(dāng)前銷售額、年化收益率、投資天數(shù)等,并沒有產(chǎn)品被哪些用戶購買的信息。所以我們需要帶著id參數(shù)去它的產(chǎn)品詳情頁爬取,比如立馬聚財(cái)-12月期HLB01239511。詳情頁有一欄投資記錄,里邊包含了我們需要的信息,如下圖所示:

但是,詳情頁需要我們?cè)诘卿浀臓顟B(tài)下才可以查看,這就需要我們帶著cookie去訪問,而且cookie是有有效期限制的,如何保持我們cookie一直在登錄態(tài)呢?請(qǐng)看后文。

其實(shí)立馬金庫也有類似的ajax接口:https://www.lmlc.com/web/product/product_list?pageSize=10&pageNo=1&type=1,但是里邊的相關(guān)數(shù)據(jù)都是寫死的,沒有意義。而且金庫的詳情頁也沒有投資記錄信息。這就需要我們爬取一開始說的首頁的ajax接口:https://www.lmlc.com/s/web/home/user_buying。但是后來才發(fā)現(xiàn)這個(gè)接口是三分鐘更新一次,就是說后臺(tái)每隔三分鐘向服務(wù)器請(qǐng)求一次數(shù)據(jù)。而一次是10條數(shù)據(jù),所以如果在三分鐘內(nèi),購買產(chǎn)品的記錄數(shù)超過10條,數(shù)據(jù)就會(huì)有遺漏。這是沒有辦法的,所以立馬金庫的統(tǒng)計(jì)數(shù)據(jù)會(huì)比真實(shí)的偏少。

四、爬蟲代碼分析 1. 獲取登錄cookie

因?yàn)楫a(chǎn)品詳情頁需要登錄,所以我們要先拿到登錄的cookie才行。getCookie方法如下:

function getCookie() {
    superagent.post("https://www.lmlc.com/user/s/web/logon")
        .type("form")
        .send({
            phone: phone,
            password: password,
            productCode: "LMLC",
            origin: "PC"
        })
        .end(function(err, res) {
            if (err) {
                handleErr(err.message);
                return;
            }
            cookie = res.header["set-cookie"]; //從response中得到cookie
            emitter.emit("setCookeie");
        })
}

phone和password參數(shù)是從命令行里傳進(jìn)來的,就是立馬理財(cái)用手機(jī)號(hào)登錄的賬號(hào)和密碼。我們用superagent去模擬請(qǐng)求立馬理財(cái)?shù)卿浗涌冢?b>https://www.lmlc.com/user/s/web/logon。傳入相應(yīng)的參數(shù),在回調(diào)中,我們拿到header的set-cookie信息,并發(fā)出一個(gè)setCookeie事件。因?yàn)槲覀冊(cè)O(shè)置了監(jiān)聽事件:emitter.on("setCookie", requestData),所以一旦獲取cookie,我們就會(huì)去執(zhí)行requestData方法。

2. 理財(cái)頁ajax的爬取

requestData方法的代碼如下:

function requestData() {
    superagent.get("https://www.lmlc.com/web/product/product_list?pageSize=100&pageNo=1&type=0")
    .end(function(err,pres){
        // 常規(guī)的錯(cuò)誤處理
        if (err) {
            handleErr(err.message);
            return;
        }
        // 在這里清空數(shù)據(jù),避免一個(gè)文件被同時(shí)寫入
        if(clearProd){
            fs.writeFileSync("data/prod.json", JSON.stringify([]));
            clearProd = false;
        }
        let addData = JSON.parse(pres.text).data;
        let formatedAddData = formatData(addData.result);
        let pageUrls = [];
        if(addData.totalPage > 1){
            handleErr("產(chǎn)品個(gè)數(shù)超過100個(gè)!");
            return;
        }
        for(let i=0,len=addData.result.length; i

代碼很長,getDetailData函數(shù)代碼后面分析。

請(qǐng)求的ajax接口是個(gè)分頁接口,因?yàn)橐话阍谑鄣目偖a(chǎn)品數(shù)不會(huì)超過10條,我們這里設(shè)置參數(shù)pageSize為100,這樣就可以一次性獲取所有產(chǎn)品。

clearProd是全局reset信號(hào),每天0點(diǎn)整的時(shí)候,會(huì)清空prod(定期產(chǎn)品)和user(首頁用戶)數(shù)據(jù)。

因?yàn)橛袝r(shí)候產(chǎn)品較少會(huì)采用搶購的方式,比如每天10點(diǎn),這樣在每天10點(diǎn)的時(shí)候數(shù)據(jù)會(huì)更新很快,我們必須要增加爬取的頻次,以防丟失數(shù)據(jù)。所以針對(duì)預(yù)售產(chǎn)品即buyStartTime大于當(dāng)前時(shí)間,我們要記錄下,并設(shè)定計(jì)時(shí)器,當(dāng)開售時(shí),調(diào)整爬取頻次為1次/秒,見setPreId方法。

如果沒有正在售賣的產(chǎn)品,即pageUrls為空,我們將爬取的頻次設(shè)置為最大32s。

requestData函數(shù)的這部分代碼主要記錄下是否有新產(chǎn)品,如果有的話,新建一個(gè)對(duì)象,記錄產(chǎn)品信息,push到prod數(shù)組里。prod.json數(shù)據(jù)結(jié)構(gòu)如下:

[{
  "productName": "立馬聚財(cái)-12月期HLB01230901",
  "financeTotalAmount": 1000000,
  "productId": "201801151830PD84123120",
  "yearReturnRate": 6.4,
  "investementDays": 364,
  "interestStartTime": "2018年01月23日",
  "interestEndTime": "2019年01月22日",
  "getDataTime": 1516118401299,
  "alreadyBuyAmount": 875000,
  "records": [
  {
    "username": "劉**",
    "buyTime": 1516117093472,
    "buyAmount": 30000,
    "uniqueId": "劉**151611709347230,000元"
  },
  {
    "username": "劉**",
    "buyTime": 1516116780799,
    "buyAmount": 50000,
    "uniqueId": "劉**151611678079950,000元"
  }]
}]

是一個(gè)對(duì)象數(shù)組,每個(gè)對(duì)象表示一個(gè)新產(chǎn)品,records屬性記錄著售賣信息。

3. 產(chǎn)品詳情頁的爬取

我們?cè)倏聪耮etDetailData的代碼:

function getDetailData(){
    // 請(qǐng)求用戶信息接口,來判斷登錄是否還有效,在產(chǎn)品詳情頁判斷麻煩還要造成五次登錄請(qǐng)求
    superagent
        .post("https://www.lmlc.com/s/web/m/user_info")
        .set("Cookie", cookie)
        .end(function(err,pres){
        // 常規(guī)的錯(cuò)誤處理
        if (err) {
            handleErr(err.message);
            return;
        }
        let retcode = JSON.parse(pres.text).retcode;
        if(retcode === 410){
            handleErr("登陸cookie已失效,嘗試重新登陸...");
            getCookie();
            return;
        }
        var reptileLink = function(url,callback){
            // 如果爬取頁面有限制爬取次數(shù),這里可設(shè)置延遲
            console.log( "正在爬取產(chǎn)品詳情頁面:" + url);
            superagent
                .get(url)
                .set("Cookie", cookie)
                .end(function(err,pres){
                    // 常規(guī)的錯(cuò)誤處理
                    if (err) {
                        handleErr(err.message);
                        return;
                    }
                    var $ = cheerio.load(pres.text);
                    var records = [];
                    var $table = $(".buy-records table");
                    if(!$table.length){
                        $table = $(".tabcontent table");
                    }
                    var $tr = $table.find("tr").slice(1);
                    $tr.each(function(){
                        records.push({
                            username: $("td", $(this)).eq(0).text(),
                            buyTime: parseInt($("td", $(this)).eq(1).attr("data-time").replace(/,/g, "")),
                            buyAmount: parseFloat($("td", $(this)).eq(2).text().replace(/,/g, "")),
                            uniqueId: $("td", $(this)).eq(0).text() + $("td", $(this)).eq(1).attr("data-time").replace(/,/g, "") + $("td", $(this)).eq(2).text()
                        })
                    });
                    callback(null, {
                        productId: url.split("?id=")[1],
                        records: records
                    });
                });
        };
        async.mapLimit(pageUrls, 10 ,function (url, callback) {
          reptileLink(url, callback);
        }, function (err,result) {
            let time = (new Date()).format("yyyy-MM-dd hh:mm:ss");
            console.log(`所有產(chǎn)品詳情頁爬取完畢,時(shí)間:${time}`.info);
            let oldRecord = JSON.parse(fs.readFileSync("data/prod.json", "utf-8"));
            let counts = [];
            for(let i=0,len=result.length; i=0 && maxNum <= 2){
                    delay = delay + 1000;
                }
                if(maxNum >=8 && maxNum <= 10){
                    delay = delay/2;
                }
                // 每天0點(diǎn),prod數(shù)據(jù)清空,排除這個(gè)情況
                if(maxNum == 10 && (time2 - time1 >= 60*1000)){
                    handleErr("部分?jǐn)?shù)據(jù)可能丟失!");
                }
                if(delay <= 1000){
                    delay = 1000;
                }
                if(delay >= 32*1000){
                    delay = 32*1000;
                }
                return delay
            }
            if(oldDelay != delay){
                clearInterval(timer);
                timer = setInterval(function(){
                    requestData();
                }, delay);
            }
            fs.writeFileSync("data/prod.json", JSON.stringify(oldRecord));
        })
    });
}

我們先去請(qǐng)求用戶信息接口,來判斷登錄是否還有效,因?yàn)樵诋a(chǎn)品詳情頁判斷麻煩還要造成五次登錄請(qǐng)求。帶cookie請(qǐng)求很簡(jiǎn)單,在post后面set下我們之前得到的cookie即可:.set("Cookie", cookie)。如果后臺(tái)返回的retcode為410表示登錄的cookie已失效,需要重新執(zhí)行g(shù)etCookie()。這樣就能保證爬蟲一直在登錄狀態(tài)。

async的mapLimit方法,會(huì)將pageUrls進(jìn)行并發(fā)請(qǐng)求,一次并發(fā)量為10。對(duì)于每個(gè)pageUrl會(huì)執(zhí)行reptileLink方法。等所有的異步執(zhí)行完畢后,再執(zhí)行回調(diào)函數(shù)。回調(diào)函數(shù)的result參數(shù)是每個(gè)reptileLink函數(shù)返回?cái)?shù)據(jù)組成的數(shù)組。

reptileLink函數(shù)是獲取產(chǎn)品詳情頁的投資記錄列表信息,uniqueId是由已知的username、buyTime、buyAmount參數(shù)組成的字符串,用來排重的。

async的回調(diào)主要是將最新的投資記錄信息寫入對(duì)應(yīng)的產(chǎn)品對(duì)象里,同時(shí)生成了counts數(shù)組。counts數(shù)組是每個(gè)產(chǎn)品這次爬取新增的售賣記錄個(gè)數(shù)組成的數(shù)組,和delay一起傳入getNewDelay函數(shù)。getNewDelay動(dòng)態(tài)調(diào)節(jié)爬取頻次,counts是調(diào)節(jié)delay的唯一依據(jù)。delay過大可能產(chǎn)生數(shù)據(jù)丟失,過小會(huì)增加服務(wù)器負(fù)擔(dān),可能會(huì)被管理員封ip。這里設(shè)置delay最大值為32,最小值為1。

4. 首頁用戶ajax爬取

先上代碼:

function requestData1() {
    superagent.get(ajaxUrl1)
    .end(function(err,pres){
        // 常規(guī)的錯(cuò)誤處理
        if (err) {
            handleErr(err.message);
            return;
        }
        let newData = JSON.parse(pres.text).data;
        let formatNewData = formatData1(newData);
        // 在這里清空數(shù)據(jù),避免一個(gè)文件被同時(shí)寫入
        if(clearUser){
            fs.writeFileSync("data/user.json", "");
            clearUser = false;
        }
        let data = fs.readFileSync("data/user.json", "utf-8");
        if(!data){
            fs.writeFileSync("data/user.json", JSON.stringify(formatNewData));
            let time = (new Date()).format("yyyy-MM-dd hh:mm:ss");
            console.log((`首頁用戶購買ajax爬取完畢,時(shí)間:${time}`).silly);
        }else{
            let oldData = JSON.parse(data);
            let addData = [];
            // 排重算法,如果uniqueId不一樣那肯定是新生成的,否則看時(shí)間差如果是0(三分鐘內(nèi)請(qǐng)求多次)或者三分鐘則是舊數(shù)據(jù)
            for(let i=0, len=formatNewData.length; i

user.js的爬取和prod.js類似,這里主要想說一下如何排重的。user.json數(shù)據(jù)格式如下:

[
{
  "payAmount": 5067.31,
  "productId": "jsfund",
  "productName": "立馬金庫",
  "productType": 6,
  "time": 1548489,
  "username": "鄭**",
  "buyTime": 1516118397758,
  "uniqueId": "5067.31jsfund鄭**"
}, {
  "payAmount": 30000,
  "productId": "201801151830PD84123120",
  "productName": "立馬聚財(cái)-12月期HLB01230901",
  "productType": 0,
  "time": 1306573,
  "username": "劉**",
  "buyTime": 1516117199684,
  "uniqueId": "30000201801151830PD84123120劉**"
}]

和產(chǎn)品詳情頁類似,我們也生成一個(gè)uniqueId參數(shù)用來排除,它是payAmount、productId、username參數(shù)的拼成的字符串。如果uniqueId不一樣,那肯定是一條新的記錄。如果相同那一定是一條新記錄嗎?答案是否定的。因?yàn)檫@個(gè)接口數(shù)據(jù)是三分鐘更新一次,而且給出的時(shí)間是相對(duì)時(shí)間,即數(shù)據(jù)更新時(shí)的時(shí)間減去購買的時(shí)間。所以每次更新后,即使是同一條記錄,時(shí)間也會(huì)不一樣。那如何排重呢?其實(shí)很簡(jiǎn)單,如果uniqueId一樣,我們就判斷這個(gè)buyTime,如果buyTime的差正好接近180s,那么幾乎可以肯定是舊數(shù)據(jù)。如果同一個(gè)人正好在三分鐘后購買同一個(gè)產(chǎn)品相同的金額那我也沒轍了,哈哈。

5. 零點(diǎn)整合數(shù)據(jù)

每天零點(diǎn)我們需要整理user.json和prod.json數(shù)據(jù),生成最終的數(shù)據(jù)。代碼:

let globalTimer = setInterval(function(){
    let nowTime = +new Date();
    let nowStr = (new Date()).format("hh:mm:ss");
    let max = nowTime;
    let min = nowTime - 24*60*60*1000;
    // 每天00:00分的時(shí)候?qū)懭氘?dāng)天的數(shù)據(jù)
    if(nowStr === "00:00:00"){
        // 先保存數(shù)據(jù)
        let prod = JSON.parse(fs.readFileSync("data/prod.json", "utf-8"));
        let user = JSON.parse(fs.readFileSync("data/user.json", "utf-8"));
        let lmlc = JSON.parse(JSON.stringify(prod));
        // 清空緩存數(shù)據(jù)
        clearProd = true;
        clearUser = true;
        // 不足一天的不統(tǒng)計(jì)
        // if(nowTime - initialTime < 24*60*60*1000) return
        // 篩選prod.records數(shù)據(jù)
        for(let i=0, len=prod.length; i= max){
                    delArr1.push(j);
                }
            }
            sort.delArrByIndex(lmlc[i].records, delArr1);
        }
        // 刪掉prod.records為空的數(shù)據(jù)
        let delArr2 = [];
        for(let i=0, len=lmlc.length; i= min && user[i].buyTime < max){
                lmlc[0].records.push({
                    "username": user[i].username,
                    "buyTime": user[i].buyTime,
                    "buyAmount": user[i].payAmount,
                });
            }
        }
        // 刪除無用屬性,按照時(shí)間排序
        lmlc[0].records.sort(function(a,b){return a.buyTime - b.buyTime});
        for(let i=1, len=lmlc.length; i

globalTimer是個(gè)全局定時(shí)器,每隔1s執(zhí)行一次,當(dāng)時(shí)間為00:00:00時(shí),clearProd和clearUser全局參數(shù)為true,這樣在下次爬取過程時(shí)會(huì)清空user.json和prod.json文件。沒有同步清空是因?yàn)榉乐苟嗵幫瑫r(shí)修改同一文件報(bào)錯(cuò)。取出user.json里的所有金庫記錄,獲取當(dāng)天金庫相關(guān)信息,生成一條立馬金庫的prod信息并unshift進(jìn)prod.json里。刪除一些無用屬性,排序數(shù)組最終生成帶有當(dāng)天時(shí)間戳的json文件,如:20180101.json。

五、前端展示 1、整體思路

前端總共就兩個(gè)頁面,首頁和詳情頁,首頁主要展示實(shí)時(shí)銷售額、某一時(shí)間段內(nèi)的銷售情況、具體某天的銷售情況。詳情頁展示某天的具體某一產(chǎn)品銷售情況。頁面有兩個(gè)入口,而且比較簡(jiǎn)單,這里我們采用gulp來打包壓縮構(gòu)建前端工程。后臺(tái)用express搭建的,匹配到路由,從data文件夾里取到數(shù)據(jù)再分析處理再返回給前端。

2、前端用到的組件介紹

Echarts

Echarts是一個(gè)繪圖利器,百度公司不可多得的良心之作。能方便的繪制各種圖形,官網(wǎng)已經(jīng)更新到4.0了,功能更加強(qiáng)大。我們這里主要用到的是直方圖。

DataTables

Datatables是一款jquery表格插件。它是一個(gè)高度靈活的工具,可以將任何HTML表格添加高級(jí)的交互功能。功能非常強(qiáng)大,有豐富的API,大家可以去官網(wǎng)學(xué)習(xí)。

Datepicker

Datepicker是一款基于jquery的日期選擇器,需要的功能基本都有,主要樣式比較好看,比jqueryUI官網(wǎng)的Datepicker好看太多。

3、gulp配置

gulp配置比較簡(jiǎn)單,代碼如下:

var gulp = require("gulp");
var uglify = require("gulp-uglify");
var less = require("gulp-less");
var minifyCss = require("gulp-minify-css");
var livereload = require("gulp-livereload");
var connect = require("gulp-connect");
var minimist = require("minimist");
var babel = require("gulp-babel");

var knownOptions = {
  string: "env",
  default: { env: process.env.NODE_ENV || "production" }
};

var options = minimist(process.argv.slice(2), knownOptions);

// js文件壓縮
gulp.task("minify-js", function() {
    gulp.src("src/js/*.js")
        .pipe(babel({
          presets: ["es2015"]
        }))
        .pipe(uglify())
        .pipe(gulp.dest("dist/"));
});

// js移動(dòng)文件
gulp.task("move-js", function() {
    gulp.src("src/js/*.js")
        .pipe(babel({
          presets: ["es2015"]
        }))
        .pipe(gulp.dest("dist/"))
        .pipe(connect.reload());
});

// less編譯
gulp.task("compile-less", function() {
    gulp.src("src/css/*.less")
        .pipe(less())
        .pipe(gulp.dest("dist/"))
        .pipe(connect.reload());
});

// less文件編譯壓縮
gulp.task("compile-minify-css", function() {
    gulp.src("src/css/*.less")
        .pipe(less())
        .pipe(minifyCss())
        .pipe(gulp.dest("dist/"));
});

// html頁面自動(dòng)刷新
gulp.task("html", function () {
  gulp.src("views/*.html")
    .pipe(connect.reload());
});

// 頁面自動(dòng)刷新啟動(dòng)
gulp.task("connect", function() {
    connect.server({
        livereload: true
    });
});

// 監(jiān)測(cè)文件的改動(dòng)
gulp.task("watch", function() {
    gulp.watch("src/css/*.less", ["compile-less"]);
    gulp.watch("src/js/*.js", ["move-js"]);
    gulp.watch("views/*.html", ["html"]);
});

// 激活瀏覽器livereload友好提示
gulp.task("tip", function() {
    console.log("
<----- 請(qǐng)用chrome瀏覽器打開 http://localhost:5000 頁面,并激活livereload插件 ----->
");
});

if (options.env === "development") {
    gulp.task("default", ["move-js", "compile-less", "connect", "watch", "tip"]);
}else{
    gulp.task("default", ["minify-js", "compile-minify-css"]);
}

開發(fā)和生產(chǎn)環(huán)境都是將文件打包到dist目錄。不同的是:開發(fā)環(huán)境只是編譯es6和less文件;生產(chǎn)環(huán)境會(huì)再壓縮混淆。支持livereload插件,在開發(fā)環(huán)境下,文件改動(dòng)會(huì)自動(dòng)刷新頁面。

后記

至此,一個(gè)完整的爬蟲就完成了。其實(shí)我覺得最需要花時(shí)間的是在分析頁面結(jié)構(gòu),處理數(shù)據(jù)還有解決各種問題,比如如何保持一直在登錄狀態(tài)等。

本爬蟲代碼只做研究學(xué)習(xí)用處,禁止用作任何商業(yè)分析。再說,統(tǒng)計(jì)的數(shù)據(jù)也不準(zhǔn)確。

因?yàn)榇a開源,希望大家照著代碼去爬取其他網(wǎng)站,如果都拿立馬理財(cái)來爬,估計(jì)服務(wù)器會(huì)承受不了的額。

歡迎大家star學(xué)習(xí)交流:線上地址 | github地址 | 我的博客

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/107523.html

相關(guān)文章

  • 把手你寫電商爬蟲-第二課 實(shí)戰(zhàn)尚妝網(wǎng)分頁商品采集爬蟲

    摘要:剩下的同學(xué),我們繼續(xù)了可以看出,作為一個(gè)完善的電商網(wǎng)站,尚妝網(wǎng)有著普通電商網(wǎng)站所擁有的主要的元素,包括分類,分頁,主題等等。 系列教程 手把手教你寫電商爬蟲-第一課 找個(gè)軟柿子捏捏 如果沒有看過第一課的朋友,請(qǐng)先移步第一課,第一課講了一些基礎(chǔ)性的東西,通過軟柿子切糕王子這個(gè)電商網(wǎng)站好好的練了一次手,相信大家都應(yīng)該對(duì)寫爬蟲的流程有了一個(gè)大概的了解,那么這課咱們就話不多說,正式上戰(zhàn)場(chǎng),對(duì)壘...

    junfeng777 評(píng)論0 收藏0
  • 把手你寫電商爬蟲-第二課 實(shí)戰(zhàn)尚妝網(wǎng)分頁商品采集爬蟲

    摘要:剩下的同學(xué),我們繼續(xù)了可以看出,作為一個(gè)完善的電商網(wǎng)站,尚妝網(wǎng)有著普通電商網(wǎng)站所擁有的主要的元素,包括分類,分頁,主題等等。 系列教程 手把手教你寫電商爬蟲-第一課 找個(gè)軟柿子捏捏 如果沒有看過第一課的朋友,請(qǐng)先移步第一課,第一課講了一些基礎(chǔ)性的東西,通過軟柿子切糕王子這個(gè)電商網(wǎng)站好好的練了一次手,相信大家都應(yīng)該對(duì)寫爬蟲的流程有了一個(gè)大概的了解,那么這課咱們就話不多說,正式上戰(zhàn)場(chǎng),對(duì)壘...

    objc94 評(píng)論0 收藏0
  • 互聯(lián)網(wǎng)金融爬蟲怎么寫-第一課 p2p網(wǎng)貸爬蟲(XPath入門)

    摘要:之前寫了一個(gè)電商爬蟲系列的文章,簡(jiǎn)單的給大家展示了一下爬蟲從入門到進(jìn)階的路徑,但是作為一個(gè)永遠(yuǎn)走在時(shí)代前沿的科技工作者,我們從來都不能停止。金融數(shù)據(jù)實(shí)在是價(jià)值大,維度多,來源廣。由于也是一種,因此通常來說,在中抽取某個(gè)元素是通過來做的。 相關(guān)教程: 手把手教你寫電商爬蟲-第一課 找個(gè)軟柿子捏捏 手把手教你寫電商爬蟲-第二課 實(shí)戰(zhàn)尚妝網(wǎng)分頁商品采集爬蟲 手把手教你寫電商爬蟲-第三課 實(shí)戰(zhàn)...

    kk_miles 評(píng)論0 收藏0
  • 互聯(lián)網(wǎng)金融爬蟲怎么寫-第一課 p2p網(wǎng)貸爬蟲(XPath入門)

    摘要:之前寫了一個(gè)電商爬蟲系列的文章,簡(jiǎn)單的給大家展示了一下爬蟲從入門到進(jìn)階的路徑,但是作為一個(gè)永遠(yuǎn)走在時(shí)代前沿的科技工作者,我們從來都不能停止。金融數(shù)據(jù)實(shí)在是價(jià)值大,維度多,來源廣。由于也是一種,因此通常來說,在中抽取某個(gè)元素是通過來做的。 相關(guān)教程: 手把手教你寫電商爬蟲-第一課 找個(gè)軟柿子捏捏 手把手教你寫電商爬蟲-第二課 實(shí)戰(zhàn)尚妝網(wǎng)分頁商品采集爬蟲 手把手教你寫電商爬蟲-第三課 實(shí)戰(zhàn)...

    jlanglang 評(píng)論0 收藏0
  • 把手你寫電商爬蟲-第五課 京東商品評(píng)論爬蟲 一起來對(duì)付反爬蟲

    摘要:和前面幾節(jié)課類似的分析這節(jié)課就不做了,對(duì)于分頁,請(qǐng)求什么的,大家可以直接參考前面的四節(jié)課,這一刻主要特別的是,我們?cè)诓杉唐返耐瑫r(shí),會(huì)將京東的商品評(píng)價(jià)采集下來。 系列教程: 手把手教你寫電商爬蟲-第一課 找個(gè)軟柿子捏捏 手把手教你寫電商爬蟲-第二課 實(shí)戰(zhàn)尚妝網(wǎng)分頁商品采集爬蟲 手把手教你寫電商爬蟲-第三課 實(shí)戰(zhàn)尚妝網(wǎng)AJAX請(qǐng)求處理和內(nèi)容提取 手把手教你寫電商爬蟲-第四課 淘寶網(wǎng)商品爬...

    jsummer 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<