利用nodejs+phantomjs+casperjs採集淘寶商品的價格

由於一些業務需求須要採集淘寶店鋪商品的銷售價格,可是淘寶詳情頁面的價格顯示是經過js動態調用顯示的.因此就無法經過普通的獲取頁面html而後經過正則或者xpath的方式獲取到想到的信息了.javascript

所幸咱們如今有了casperjs.這個是一個基於Phantomjs的庫,而Phantomjs則是一個服務器端的js api的webkit瀏覽器.是否是很神奇?真的是.net的之外的世界很神奇,咱們要多走去看看.html

好了,如今廢話很少說,開始切入正題.java

首先就是就是幾個相關庫的安裝.安裝過程很簡單,相關內容你們百度便可.在文章的底部我也會列出參考連接.node

咱們先進行下簡要的分析:jquery

具體的操做流程就是利用casperjs模擬鼠標點擊商品的圖片,而後網頁顯示對應的價格.web

默認狀況是這樣的,若是不點擊顏色分類下的圖片,則對應的促銷價格也只是會顯示一個區間.數據庫

而只要咱們點擊了顏色分類對應的圖片以後,則會是下面的效果api

 

那麼咱們具體的操做步驟應該是:瀏覽器

1)打開具體的商品詳情頁服務器

2)獲取到顏色分類下圖片個數,而後依次模擬鼠標點擊

3)每點擊一次圖片,而後獲取對應的促銷價格

4)保存每次操做後的結果到數據庫或者本地文件中待下一步處理

 

下面咱們就來具體的一步步實現上面分析後所須要的步驟:

1.初始化casperjs

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
  }
});

phantom.outputEncoding = "gbk";//解決亂碼問題

2.打開具體的url

/*
獲取須要採集的url列表
*/
casper.start(url, function() {
  casper.GetDetailUrl(url);
});

/*
打開具體url
*/
casper.GetDetailUrl = function(detailUrl) {
  casper.thenOpen(detailUrl, function() {
  console.log(this.getCurrentUrl());
});

};

  

3.處理當前頁面的全部sku價格與信息

/*
處理當前頁面的全部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");   
});

  

/*
獲取商品的價格
*/
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.將最後處理後獲得的結果提交到服務器上

/*
提交商品價格信息到服務器
*/
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便可.

casper.run();

經過以上4個步驟咱們就能獲取到單個連接下,全部sku的促銷價格了.

如今還有個問題,就是咱們的nodejs還沒出場呢,不會把它忘記的,呵呵.

爲何這裏casperjs都搞定了,還須要nodejs呢?那就是由於casperjs只能處理單個連接,若是有多條連接處理的話,就須要啓動多個casperjs的實例來完成.

上面的全部代碼都是casperjs的一個操做步驟,最後的一個run就是讓這個實例按咱們定義好的步驟來進行的一個完整的流程.

那麼既然若是,咱們就請nodejs出場吧~

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能夠獲取調用的參數啦

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

  以上,就是全部採集須要使用到的代碼了!怎麼樣,是否是很是的彪悍啊,整個處理流程只用了區區100來行的代碼,就搞定了全部的採集流程.

 

參考連接:

http://www.open-open.com/lib/view/open1338375857589.html

http://www.cnmiss.cn/?p=413

http://blog.csdn.net/sagomilk/article/details/20800543

http://www.cnblogs.com/zeusro/p/4188229.html

http://casperjs.readthedocs.org/en/latest/modules/casper.html

相關文章
相關標籤/搜索