1. 程式人生 > >Nodejs學習筆記(十一)--- 資料採集器示例(request和cheerio)

Nodejs學習筆記(十一)--- 資料採集器示例(request和cheerio)

目錄

寫在之前

  很多人都有做資料採集的需求,用不同的語言,不同的方式都能實現,我以前也用C#寫過,主要還是傳送各類請求和正則解析資料比較繁瑣些,總體來說沒啥不好的,就是效率要差一些,

  用nodejs寫採集程式還是比較有效率(可能也只是相對C#來說),今天主要用一個示例來說一下使用nodejs實現資料採集器,主要使用到request和cheerio。

  request :用於http請求

  cheerio:用於提取request返回的html中需要的資訊(和jquery用法一致)

示例

  單獨去說API用法沒什麼意思也沒必要記住全部API,下面開始示例

  還是說點閒話:

  nodejs開發工具還是很多,以前我也很推薦sublime,自從微軟推出了Visual Studio Code後就轉用它去做nodejs開發。

  用它開發還是比較舒服的,免配置、啟動快、自動補全、檢視定義和引用、搜尋快等,有VS的一貫風格,應該會越做越好,所以推薦一下^_^!

  示例要求

  從 http://36kr.com/ 中抓取其中文章的“標題”、“地址”、“釋出時間”、“封面圖片”

  採集器

  1.建立專案資料夾sampleDAU

  2.建立package.json檔案 

{
  "name": "Wilson_SampleDAU",
  
"version": "0.0.1", "private": false, "dependencies": { "request":"*", "cheerio":"*" } }

  3.在終端中用npm安裝引用      

cd 專案根目錄
npm install

  4.建立app.js編寫採集器程式碼

  首先要用瀏覽器開啟要採集的URL,使用開發者工具檢視HTML結構,然後根據結構寫解析程式碼

/*
* 功能:   資料採集
* 建立人: Wilson
* 時間:   2015-07-29
*/
var request = require('request'),
    cheerio 
= require('cheerio'), URL_36KR = 'http://36kr.com/'; //36氪 /* 開啟資料採集器 */ function dataCollectorStartup() { dataRequest(URL_36KR); } /* 資料請求 */ function dataRequest(dataUrl) { request({ url: dataUrl, method: 'GET' }, function(err, res, body) { if (err) { console.log(dataUrl) console.error('[ERROR]Collection' + err); return; } switch(dataUrl) { case URL_36KR: dataParse36Kr(body); break; } }); } /* 36kr 資料解析 */ function dataParse36Kr(body) { console.log('============================================================================================'); console.log('======================================36kr=================================================='); console.log('============================================================================================'); var $ = cheerio.load(body); var articles = $('article') for (var i = 0; i < articles.length; i++) { var article = articles[i]; var descDoms = $(article).find('.desc'); if(descDoms.length == 0) { continue; } var coverDom = $(article).children().first(); var titleDom = $(descDoms).find('.info_flow_news_title'); var timeDom = $(descDoms).find('.timeago'); var titleVal = titleDom.text(); var urlVal = titleDom.attr('href'); var timeVal = timeDom.attr('title'); var coverUrl = coverDom.attr('data-lazyload'); //處理時間 var timeDateSecs = new Date(timeVal).getTime() / 1000; if(urlVal != undefined) { console.info('--------------------------------'); console.info('標題:' + titleVal); console.info('地址:' + urlVal); console.info('時間:' + timeDateSecs); console.info('封面:' + coverUrl); console.info('--------------------------------'); } }; } dataCollectorStartup();

  測試結果

 

  這個採集器就完成了,其實就是request一個get請求,請求回撥中會返回body即HTML程式碼,通過cheerio庫以jquery庫語法一樣操作解析,取出想要的資料! 

加入代理

  做一個採集器DEMO上面就基本完成了。如果需要長期使用為了防止網站遮蔽,還是需要加入一個代理列表

  為示例我從網上的免費代理中提出一些做示例,製作成proxylist.js,其中提供一個隨機取一條代理的函式

var PROXY_LIST = [{"ip":"111.1.55.136","port":"55336"},{"ip":"111.1.54.91","port":"55336"},{"ip":"111.1.56.19","port":"55336"}
                    ,{"ip":"112.114.63.16","port":"55336"},{"ip":"106.58.63.83","port":"55336"},{"ip":"119.188.133.54","port":"55336"}
                    ,{"ip":"106.58.63.84","port":"55336"},{"ip":"183.95.132.171","port":"55336"},{"ip":"11.12.14.9","port":"55336"}
                    ,{"ip":"60.164.223.16","port":"55336"},{"ip":"117.185.13.87","port":"8080"},{"ip":"112.114.63.20","port":"55336"}
                    ,{"ip":"188.134.19.102","port":"3129"},{"ip":"106.58.63.80","port":"55336"},{"ip":"60.164.223.20","port":"55336"}
                    ,{"ip":"106.58.63.78","port":"55336"},{"ip":"112.114.63.23","port":"55336"},{"ip":"112.114.63.30","port":"55336"}
                    ,{"ip":"60.164.223.14","port":"55336"},{"ip":"190.202.82.234","port":"3128"},{"ip":"60.164.223.15","port":"55336"}
                    ,{"ip":"60.164.223.5","port":"55336"},{"ip":"221.204.9.28","port":"55336"},{"ip":"60.164.223.2","port":"55336"}
                    ,{"ip":"139.214.113.84","port":"55336"} ,{"ip":"112.25.49.14","port":"55336"},{"ip":"221.204.9.19","port":"55336"}
                    ,{"ip":"221.204.9.39","port":"55336"},{"ip":"113.207.57.18","port":"55336"} ,{"ip":"112.25.62.15","port":"55336"}
                    ,{"ip":"60.5.255.143","port":"55336"},{"ip":"221.204.9.18","port":"55336"},{"ip":"60.5.255.145","port":"55336"}
                    ,{"ip":"221.204.9.16","port":"55336"},{"ip":"183.232.82.132","port":"55336"},{"ip":"113.207.62.78","port":"55336"}
                    ,{"ip":"60.5.255.144","port":"55336"} ,{"ip":"60.5.255.141","port":"55336"},{"ip":"221.204.9.23","port":"55336"}
                    ,{"ip":"157.122.96.50","port":"55336"},{"ip":"218.61.39.41","port":"55336"} ,{"ip":"221.204.9.26","port":"55336"}
                    ,{"ip":"112.112.43.213","port":"55336"},{"ip":"60.5.255.138","port":"55336"},{"ip":"60.5.255.133","port":"55336"} 
                    ,{"ip":"221.204.9.25","port":"55336"},{"ip":"111.161.35.56","port":"55336"},{"ip":"111.161.35.49","port":"55336"}
                    ,{"ip":"183.129.134.226","port":"8080"} ,{"ip":"58.220.10.86","port":"80"},{"ip":"183.87.117.44","port":"80"}
                    ,{"ip":"211.23.19.130","port":"80"},{"ip":"61.234.249.107","port":"8118"},{"ip":"200.20.168.140","port":"80"}
                    ,{"ip":"111.1.46.176","port":"55336"},{"ip":"120.203.158.149","port":"8118"},{"ip":"70.39.189.6","port":"9090"} 
                    ,{"ip":"210.6.237.191","port":"3128"},{"ip":"122.155.195.26","port":"8080"}];
        

module.exports.GetProxy = function () {
        
    var randomNum = parseInt(Math.floor(Math.random() * PROXY_LIST.length));    
    var proxy = PROXY_LIST[randomNum];

    return 'http://' + proxy.ip + ':' + proxy.port;
}
proxylist.js

  對app.js程式碼做如下修改

/*
* 功能:   資料採集
* 建立人: Wilson
* 時間:   2015-07-29
*/
var request = require('request'),
    cheerio = require('cheerio'), 
    URL_36KR = 'http://36kr.com/',            //36氪
    Proxy = require('./proxylist.js'); 

...

/* 資料請求 */
function dataRequest(dataUrl)
{
    request({
        url: dataUrl,    
        proxy: Proxy.GetProxy(),
        method: 'GET'
    }, function(err, res, body) { 
...
        }

}

...

dataCollectorStartup()
setInterval(dataCollectorStartup, 10000);        

  這樣就改造完成,加入程式碼,並且加了setInterval進行定間隔執行!

請求https

  上面示例中採集http請求,如果換成https呢?

  新建app2.js,程式碼如下

/*
* 功能:   請求HTTPS
* 建立人: Wilson
* 時間:   2015-07-29
*/
var request = require('request'),   
    URL_INTERFACELIFE = 'https://interfacelift.com/wallpaper/downloads/date/wide_16:10/';

/* 開啟資料採集器 */
 function dataCollectorStartup() {         
     dataRequest(URL_INTERFACELIFE);
 }

/* 資料請求 */
function dataRequest(dataUrl)
{
    request({
        url: dataUrl,    
        method: 'GET'
    }, function(err, res, body) { 
        if (err) {            
            console.log(dataUrl)
            console.error('[ERROR]Collection' + err);        
            return;            
        }    

        console.info(body);
        
    });    
}

dataCollectorStartup();

  執行會發現返回body中什麼也沒有^_^!

  加入一些程式碼再看看

/*
* 功能:   請求HTTPS
* 建立人: Wilson
* 時間:   2015-07-29
*/
var request = require('request'),   
    URL_INTERFACELIFE = 'https://interfacelift.com/wallpaper/downloads/date/wide_16:10/';

/* 開啟資料採集器 */

...

/* 資料請求 */
function dataRequest(dataUrl)
{
    request({
        url: dataUrl,    
        method: 'GET',
        headers: {
            'User-Agent': 'wilson'
            }
    }, function(err, res, body) { 
        if (err) {            
            console.log(dataUrl)
            console.error('[ERROR]Collection' + err);        
            return;            
        }    

        console.info(body);
        
    });    
}

...

  再執行,你會發現body中返回請求的HTML!(結果就不放上來了,自已執行一下!)

寫在之後

  離上一篇快半年了^_^! 最近有計劃寫幾篇操作型別的,不講原理也不通講API,只講例項!

  request庫我還是推薦API可以多看看,比如Forms部分我就在實際專案測試中用的比較多!

  比如做介面測試:

  1.提交兩個引數(引數1:字串  引數2:數字)

request.post({url:'介面URL',form: {引數一名稱:'引數一值',引數二名稱:引數二值},function(err,res,body){ 
            
            if(err)
            {
                return;
            }
            console.log(body);
    });

  body就是介面返回

  2.提交一個字串引數,提交一個檔案引數(比如上傳頭像等)

    var r = request.post('介面URL',function(err,res,body){             
            if(err)
            {
                return;
            }
            console.log(body);
    });    
    var form = r.form();
    form.append('引數一名稱', '引數一值');
    form.append('引數二名稱', fs.createReadStream('1.jpg'), {filename: '1.jpg'});

  cheerio庫真沒什麼好講的,會jquery就行,它庫的api基本都不用看!

相關推薦

Nodejs學習筆記--- 資料採集示例requestcheerio

目錄 寫在之前   很多人都有做資料採集的需求,用不同的語言,不同的方式都能實現,我以前也用C#寫過,主要還是傳送各類請求和正則解析資料比較繁瑣些,總體來說沒啥不好的,就是效率要差一些,   用nodejs寫採集程式還是比較有效率(可能也只是相對C#來說),今天主要用一個示例來說一下使用node

Nodejs學習筆記—數據采集示例requestcheerio

列表 意思 9.1 很多 AD 開發 com http undefined 寫在之前   很多人都有做數據采集的需求,用不同的語言,不同的方式都能實現,我以前也用C#寫過,主要還是發送各類請求和正則解析數據比較繁瑣些,總體來說沒啥不好的,就是效率要差一些,   用nodej

python學習筆記叠代其他

技術分享 img 余數 商品列表 步長 取數 sorted函數 學習 四舍五入 yiled 面相過程編程 造好內容,統一發給下面 上面這個是傻瓜版 內置函數 print(divmod(10,3)) 將10除以3,顯示商和余數 enumerate函數,顯示元素及它

設計模式C++學習筆記c/c++面試筆試題

一、指標與引用有什麼區別? 1、指標會佔用記憶體,引用不佔用記憶體。 2、引用在定義時必須初始化。 3、沒有空的引用,但是有空的指標。 二、static關鍵的幾個作用 1、函式體內的static變數的作用範圍為該函式體,該變數記憶體只分配一次,因此其值在下次再呼叫該函式時

2018秋招面試問題資料結構基礎問題

注:面試過程中整理的學習資料,如有侵權聯絡我即刻刪除。 目錄 資料結構中連結串列和陣列的異同? 陣列的元素在記憶體中是連續存放的,我們可以通過下標快速訪問到某個元素,而如果要對陣列進行增加或者刪除元素,就要移動大量的元

《SAS編程與數據挖掘商業案例》學習筆記

ror otto -c ace mov 得到 replace 讀書筆記 集中 繼續讀書筆記,本文重點側重sas觀測值的操作方面, 主要包含:輸出觀測值、更新觀測值、刪除觀測值、停止輸出觀測值等

學習筆記節課

作業linux和windows互傳文件 互傳文件 先安裝一個工具 yum install -y lrzsz 使用sz命令 就可以把linux上的文件傳到windows上去。 rz 就可以把windows上的東西傳到linux上 (當前目錄) 前提是用 xshell securecrt putty是

學習筆記第二節課

作業yum更換國內源 有時候自帶的yum源,不好用,因為自帶的裏面的網址資源是國外的。從國內下載很慢。 想辦法更改國內的源。 實驗: 先把dvd給刪除了, 然後把之前刪除的給cp回來。 然後刪除 CentOS-Base.repo 改一個CentOS7-Base-163.repo 新的需要去下載,寫入下載

Java學習筆記:Java面向對象的三大特性之繼承

類構造 接下來 多重 通過 prot 圖片 等級 ++ class Java面向對象的三大特性之繼承 一:繼承的概念;   繼承是java面向對象編程技術的一塊基石,因為它允許創建分等級層次的類。   繼承就是子類繼承父類的特征和行為,使得子類對象(實例)具有父

深度學習花書學習筆記章 實踐方法論

效能度量 根據任務需求,需要有不同的效能度量方式,常規度量方式如下: _ 真 假 認為真 true positive(TP) false positive(FP)

kubernetes學習筆記:kubernetes dashboard認證及分級授權

第一章、部署dashboard 作為Kubernetes的Web使用者介面,使用者可以通過Dashboard在Kubernetes叢集中部署容器化的應用,對應用進行問題處理和管理,並對叢集本身進行管理。通過Dashboard,使用者可以檢視叢集中應用的執行情況,同時也能夠基於Dashboard建立或修

【OS學習筆記 真實模式:中斷-軟中斷硬中斷基本原理

上一篇文章我們模擬作業系統的載入器程式,使用匯編語言實現了一個程式載入器:點選連結檢視上一篇文章:程式載入器的實現原理 本篇文章,是真實模式學習的結尾。在經過了那麼多坎坷,終於學完了8086的真實模式!!!最重要的是本篇文章沒有彙編程式碼,只講原理~~ 今天的內容比較簡單,學習一下中

opencv學習筆記:影象修復

當我們的照片有劃痕或遭到人為的塗鴉(比如馬賽克)時, 如果我們想讓這些遭到破壞的圖片儘可能恢復到原樣,Opencv能幫我們做到嗎?答案是肯定的。 那麼影象修復技術的原理是什麼呢? 簡而言之,就是利用那些已經被破壞的區域的邊緣, 即邊緣的顏色和結構,根據這些影象留下的資訊去

機器學習筆記——整合學習之Boosting及AdaBoosting

   上一篇記述了Bagging的思維與應用 : https://blog.csdn.net/qq_35946969/article/details/85045432    本篇記錄Boosting的思想與應用:AdaBoosting、GDBT(

Maven 學習筆記:Maven倉庫(快照版本)

 Maven倉庫(快照版本) ---------- 在Maven的世界中,任何一個專案或者構件都必須有自己的版本。版本的值可能是1.0.0,1.3-alpha-4,2.0,2.1-SNAPSHOT或者2.1-20091214.221414-13。其中,1.0、1.3-a

Java Web 學習筆記:RestEasy統一處理異常

JBoss RestEasy框架配置異常統一處理 前提 利用JBoss restEasy框架搭建的restful java web後臺應用 希望通過統一的方式對restful介面丟擲的異常進行

Oracle學習筆記

Oracle學習筆記第十一天 備份和恢復和遷移 這活按我猜想應該是DBA的活,沒有往這方面發展的想法,所以筆記做得簡單點了… 概念: 備份 備份就是把資料庫複製到轉儲裝置的過程 恢復 恢復就是把資料庫由存在故障的狀態轉變為無故障狀態的過程 --

【PMP】Head First PMP 學習筆記章 風險管理

第十一章 風險管理 計劃再仔細的專案也會遇到麻煩。 什麼是風險 風險是任何可能影響專案的不確定時間或狀況,但並非所有風險都是負面的 風險(risk) 事件(event) 狀況(condition) 機會(opporunity) 風險偏好。為了預期的回

pytorch學習筆記(二): 使用 pack_padded_sequence

在使用 pytorch 的 RNN 模組的時候, 有時會不可避免的使用到 pack_padded_sequence 和 pad_packed_sequence, 當使用雙向RNN的時候, 必須要使用 pack_padded_sequence !! .否則的話,

EF6學習筆記:格式化日誌輸出

exec https edi 進行 mman sel 能夠 database container 要專業系統地學習EF推薦《你必須掌握的Entity Framework 6.x與Core 2.0》。這本書作者(汪鵬,Jeffcky)的博客:https://www.cnblo