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


因為一些業務需求需要采集淘寶店鋪商品的銷售價格,但是淘寶詳情頁面的價格顯示是通過js動態調用顯示的.所以就沒法通過普通的獲取頁面html然后通過正則或者xpath的方式獲取到想到的信息了.

所幸我們現在有了casperjs.這個是一個基於Phantomjs的庫,而Phantomjs則是一個服務器端的js api的webkit瀏覽器.是不是很神奇?真的是.net的以外的世界很神奇,我們要多走去看看.

好了,現在廢話不多說,開始切入正題.

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

我們先進行下簡要的分析:

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

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

而只要我們點擊了顏色分類對應的圖片之后,則會是下面的效果

 

那么我們具體的操作步驟應該是:

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM