博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
利用nodejs+phantomjs+casperjs采集淘宝商品的价格
阅读量:4131 次
发布时间:2019-05-25

本文共 4644 字,大约阅读时间需要 15 分钟。

因为一些业务需求需要采集淘宝店铺商品的销售价格,但是淘宝详情页面的价格显示是通过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(
''
).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(
''
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来行的代码,就搞定了所有的采集流程.

 

参考链接:

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

你可能感兴趣的文章
C++模板
查看>>
【C#】如何实现一个迭代器
查看>>
【C#】利用Conditional属性完成编译忽略
查看>>
VUe+webpack构建单页router应用(一)
查看>>
(python版)《剑指Offer》JZ01:二维数组中的查找
查看>>
Spring MVC中使用Thymeleaf模板引擎
查看>>
PHP 7 的五大新特性
查看>>
深入了解php底层机制
查看>>
PHP中的stdClass 【转】
查看>>
XHProf-php轻量级的性能分析工具
查看>>
OpenCV gpu模块样例注释:video_reader.cpp
查看>>
就在昨天,全球 42 亿 IPv4 地址宣告耗尽!
查看>>
Mysql复制表以及复制数据库
查看>>
Linux分区方案
查看>>
如何使用 systemd 中的定时器
查看>>
git命令速查表
查看>>
linux进程监控和自动重启的简单实现
查看>>
OpenFeign学习(三):OpenFeign配置生成代理对象
查看>>
OpenFeign学习(四):OpenFeign的方法同步请求执行
查看>>
OpenFeign学习(六):OpenFign进行表单提交参数或传输文件
查看>>