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

[经验分享] 利用nodejs+phantomjs+casperjs采集淘宝商品的价格

[复制链接]
发表于 2017-2-22 11:17:04 | 显示全部楼层 |阅读模式
  因为一些业务需求需要采集淘宝店铺商品的销售价格,但是淘宝详情页面的价格显示是通过js动态调用显示的.所以就没法通过普通的获取页面html然后通过正则或者xpath的方式获取到想到的信息了.
  所幸我们现在有了casperjs.这个是一个基于Phantomjs的库,而Phantomjs则是一个服务器端的js api的webkit浏览器.是不是很神奇?真的是.net的以外的世界很神奇,我们要多走去看看.
  好了,现在废话不多说,开始切入正题.
  首先就是就是几个相关库的安装.安装过程很简单,相关内容大家百度即可.在文章的底部我也会列出参考链接.
  我们先进行下简要的分析:
  具体的操作流程就是利用casperjs模拟鼠标点击商品的图片,然后网页显示对应的价格.
  默认情况是这样的,如果不点击颜色分类下的图片,则对应的促销价格也只是会显示一个区间.
DSC0000.png

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

  那么我们具体的操作步骤应该是:
  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.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

运维网声明 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-345674-1-1.html 上篇帖子: HTML5+NodeJs实现WebSocket即时通讯 下篇帖子: nodejs开发指南读后感
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

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

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

扫描微信二维码查看详情

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


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


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


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



合作伙伴: 青云cloud

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