nodejs+phantomjs+casperjs

因为一些业务需求需要采集淘宝店铺商品的销售价格,但是淘宝详情页面的价格显示是通过js动态调用显示的.所以就没法通过普通的获取页面html然后通过正则或者xpath的方式获取到想到的信息了.

所幸我们现在有了casperjs.这个是一个基于Phantomjs的库,而Phantomjs则是一个服务器端的js api的webkit浏览器.是不是很神奇?真的是.net的以外的世界很神奇,我们要多走去看看.

好了,现在废话不多说,开始切入正题.

首先就是就是几个相关库的安装.安装过程很简单,相关内容大家百度即可.在文章的底部我也会列出参考链接.

我们先进行下简要的分析:

具体的操作流程就是利用casperjs模拟鼠标点击商品的图片,然后网页显示对应的价格.

默认情况是这样的,如果不点击颜色分类下的图片,则对应的促销价格也只是会显示一个区间.

而只要我们点击了颜色分类对应的图片之后,则会是下面的效果

 

那么我们具体的操作步骤应该是:

1)打开具体的商品详情页

2)获取到颜色分类下图片个数,然后依次模拟鼠标点击

3)每点击一次图片,然后获取对应的促销价格

4)保存每次操作后的结果到数据库或者本地文件中待下一步处理

 

下面我们就来具体的一步步实现上面分析后所需要的步骤:

1.初始化casperjs

1
2
3
4
5
6
7
8
9
var  casper = require( 'casper' ).create({
   clientScripts: [ "jquery.js" ],
   verbose:  false ,
   logLevel:  'debug' ,
   pageSettings: {
     loadImages:  false // The WebPage instance used by Casper will
     loadPlugins:  false  // use these settings
   }
});<br><br>phantom.outputEncoding =  "gbk" ; //解决乱码问题

2.打开具体的url

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/*
获取需要采集的url列表
*/
casper.start(url,  function () {
   casper.GetDetailUrl(url);
});
 
/*
打开具体url
*/
casper.GetDetailUrl =  function (detailUrl) {
  casper.thenOpen(detailUrl,  function () {
  console.log( this .getCurrentUrl());
});
 
};

  

3.处理当前页面的所有sku价格与信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/*
处理当前页面的所有sku价格与信息
*/
casper.then( function  getPic() {
 
   // console.log(this.getHTML());
 
   // fs.write('123', this.getHTML(), 'w');
 
   product = casper.evaluate( function  getProductFromPage() {
     return  $( 'ul[class*="tb-img"]' ).children().size();
   });
 
   console.log(product);
 
   var  str =  ''
   for  ( var  i = 1; i <= product; i++) {
     str += casper.getPrice(i) +  "|" ;
   }
 
   var  item =  new  Object();
   item.price = str;
   item.numiid =  this .getCurrentUrl();
 
   casper.PostData(item);
 
   // fs.write('myfile.html', str, 'w');
 
   //this.capture("4.png");  
});<br><br>

  

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
/*
获取商品的价格
*/
casper.getPrice =  function (index) {
var  dd = casper.clickByImg(index);
if  (dd == -1) {
return  '' ;
}
 
productPrice = casper.evaluate( function  getPriceFromPage() {
return  $( '.tm-price' ).first().text().trim();
});
 
return  (dd +  "_"  + productPrice);
 
};
 
/*
点击小图及获取此商品的data-value
*/
casper.clickByImg =  function (index) {
 
var  x = require( 'casper' ).selectXPath;
// 如果此商品缺货则跳出
var  path =  '//*[@id="J_DetailMeta"]/div[1]/div[1]/div/div[4]/div/div/dl[1]/dd/ul/li['  + index +  ']' ;
var  outOfStock =  this .getElementAttribute(x(path),  'class' );
if  (outOfStock ==  'tb-out-of-stock' )
return  '-1' ;
 
this .click(x( '//*[@id="J_DetailMeta"]/div[1]/div[1]/div/div[4]/div/div/dl[1]/dd/ul/li['  + index +  ']/a' ));
 
return  this .getElementAttribute(x(path),  'data-value' );  // "data-value"
};

  

4.将最后处理后得到的结果提交到服务器上

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/*
提交商品价格信息到服务器
*/
casper.PostData =  function (item) {
 
   casper.open( 'http://XXX/UpdateItemsPrice' ).then( function () {
 
     this .fill( "form" , {
       'numiid' : item.numiid,
       'value' : item.price
     },  false );
 
     this .capture( 'post.png' );
     this .click( "#btnSave" );
 
     this .echo( 'GOT it1.'  + item.numiid);
   });
 
   this .echo( 'GOT it2.'  + item.numiid);
 
   this .wait(2000,  function () {
     this .echo( "I've waited for a second." );
   });
 
 
}

最后run即可.

1
casper.run();

通过以上4个步骤我们就能获取到单个链接下,所有sku的促销价格了.

现在还有个问题,就是我们的nodejs还没出场呢,不会把它忘记的,呵呵.

为什么这里casperjs都搞定了,还需要nodejs呢?那就是因为casperjs只能处理单个链接,如果有多条链接处理的话,就需要启动多个casperjs的实例来完成.

上面的所有代码都是casperjs的一个操作步骤,最后的一个run就是让这个实例按我们定义好的步骤来进行的一个完整的流程.

那么既然如果,我们就请nodejs出场吧~

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
var  count = 0;
console.log( '主进程开启' );
var  startTime =  new  Date().getTime();
 
var  https = require( 'http' );
 
/*
获取需要采集的url列表
*/
https.get( 'http://XXX/GetItemsList' function (res) {
   // console.log("statusCode: ", res.statusCode);
   // console.log("headers: ", res.headers);
 
   res.on( 'data' function (d) {
     // process.stdout.write(d);
 
     var  obj = JSON.parse(d)
 
     for  ( var  i = 0; i < obj.items.length; i++) {
       capture(obj.items[i].detail_url);
     }
     ;
 
   });
 
}).on( 'error' function (e) {
   console.error(e);
});
 
/*
启动casperjs读取单个url
*/
function  capture(url) {
   count++;
   var  spawn = require( 'child_process' ).spawn,
     ls = spawn( 'casperjs' , [ 'casperjs.js' , url]);
 
   ls.on( 'close' function (code) {
     if  (code == 1) {
       console.log( 'child process异常结束。目标:'  + url);
     }
 
   });
 
}

  当然,这里我们的casperjs需要进行模块化处理的,其实就是让casperjs可以获取调用的参数啦

1
2
var  system = require( 'system' );
var  url = system.args[4];

  以上,就是所有采集需要使用到的代码了!怎么样,是不是非常的彪悍啊,整个处理流程只用了区区100来行的代码,就搞定了所有的采集流程

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值