设为首页 收藏本站
查看: 1496|回复: 0

[经验分享] Nodejs学习笔记(十一)--- 数据采集器示例(request和cheerio)

[复制链接]

尚未签到

发表于 2017-2-22 11:22:46 | 显示全部楼层 |阅读模式
目录




  • 写在之前
  • 示例

    • 示例要求
    • 采集器


  • 加入代理
  • 请求https
  • 写在之后...

写在之前
  很多人都有做数据采集的需求,用不同的语言,不同的方式都能实现,我以前也用C#写过,主要还是发送各类请求和正则解析数据比较繁琐些,总体来说没啥不好的,就是效率要差一些,
  用nodejs写采集程序还是比较有效率(可能也只是相对C#来说),今天主要用一个示例来说一下使用nodejs实现数据采集器,主要使用到request和cheerio。
  request :用于http请求
  https://github.com/request/request
  cheerio:用于提取request返回的html中需要的信息(和jquery用法一致)
  https://github.com/cheeriojs/cheerio

示例
  单独去说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;
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();
  测试结果

DSC0000.png


  这个采集器就完成了,其实就是request一个get请求,请求回调中会返回body即HTML代码,通过cheerio库以jquery库语法一样操作解析,取出想要的数据!

加入代理
  做一个采集器DEMO上面就基本完成了。如果需要长期使用为了防止网站屏蔽,还是需要加入一个代理列表
  为示例我从网上的免费代理中提出一些做示例,制作成proxylist.js,其中提供一个随机取一条代理的函数


DSC0001.gif DSC0002.gif


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!(结果就不放上来了,自已执行一下!)
  详细的请看:https://github.com/request/request#custom-http-headers  

写在之后
  离上一篇快半年了^_^! 最近有计划写几篇操作类型的,不讲原理也不通讲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基本都不用看!

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-345682-1-1.html 上篇帖子: 原生nodejs 学习笔记1 下篇帖子: 使用 Nodejs 搭建简单的Web服务器
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表