nodejs抓取动态网页(下phantomjs,具体过程是怎么实现的呢?(一))

优采云 发布时间: 2022-03-21 22:19

  nodejs抓取动态网页(下phantomjs,具体过程是怎么实现的呢?(一))

  最近在研究phantomjs,但只是第一次,谈不上深入研究。首先介绍一下phantomjs是什么。

  官网上的介绍是:“PhantomJS 是一个可以用 JavaScript API 编写脚本的无头 WebKit。它对各种 Web 标准有快速和原生的支持:DOM 处理、CSS 选择器、JSON、Canvas 和 SVG。” 服务器端 JavaScript API。它完全支持没有浏览器支持的 Web,它速度快,原生支持各种 Web 标准:DOM 操作、CSS 选择器、JSON、Canvas 和 SVG。” PhantomJS 可用于页面自动化、Web 监控、网页截图和无接口测试。

  本文结合nodejs,使用phantomjs网页截图功能,对多个URL进行批量截图操作,将图片上传到七牛服务器,批量获取图片下载地址,并保存在本地文件中。

  下面开始说一下这个demo的具体流程是如何实现的。

  一、安装

  1、nodejs

  nodejs的安装在之前的文章中已经提到过,这里不再赘述。详情请参考nodejs官网:;

  2、幻影

  关于phantomjs的安装,这里是windows环境下的安装方法:

  首先去官网下载phantomjs压缩包,解压到本地磁盘。比如我电脑上解压后存储的地址是:D:\Program files\phantomjs-2.1.1;

  二、配置环境变量。将解压后的phantomjs目录下bin目录的路径(比如我本地bin目录的位置是:D:\Program files\phantomjs-2.1.1\bin)添加到系统中变量路径变量中间;

  然后,打开cmd,输入“phantomjs --version”命令查看phantomjs是否安装成功。如果出现版本号信息,则安装成功。如果报错,需要重启电脑。

  结果如下所示:

  

  二、设计理念

  首先说一下写这个demo的初衷。因为我在工作中每次发邮件都需要用到一些截图,不想每次都手动拍多张,所以想用一个自动化的批处理工具来自动截图,不过这只是为了完成截图,使用的时候还是要上传图片。我还是觉得麻烦,所以想在截图完成后自动将这些图片上传到七牛服务器,然后从服务器获取图片下载地址,然后就可以直接使用图片下载地址了。好的。以下是具体的设计思路。

  

  对于上图中的截图设备,具体程序流程为:

  

  三、编码

  1、模拟Echarts图表生成的工程代码和启动方法不再详述。请参考我在github上发布的源码:

  2、截图

  2.1、capture.js

  主要使用phantomjs进行截图操作

   1 var page=require('webpage').create();//创建一个网页对象;

2 var system=require('system');

3 var address,fileName;

4 // page.viewportSize={width:1024,height:800};//设置窗口的大小为1024*800;

5 // page.clipRect={top:0,left:0,width:1024,height:800};//截取从{0,0}为起点的1024*800大小的图像;

6 // //禁止Javascript,允许图片载入;

7 // // 并将userAgent改为"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.31 (KHTML, like Gecko) PhantomJS/19.0";

8 // page.settings={

9 // javascriptEnabled: false,

10 // loadImages: true,

11 // userAgent: 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.31 (KHTML, like Gecko) PhantomJS/19.0'

12 // };

13

14 if (system.args.length === 1) {

15 console.log('Try to pass some args when invoking this script!');

16 phantom.exit(1);

17 }else{

18 //获取指令传递的参数,参数是以数组的形式传递的;

19 address=system.args[1];

20 fileName=system.args[2];

21 count=system.args[3];

22 max=system.args[4];

23 //打开一个网页;

24 page.open(address,function(status){

25 console.log(status);

26 if(status==='success'){

27 //成功后将页面存储为图片并放在指定的位置;

28 page.render('./pictures/'+fileName+'.png');

29 }

30 // page.close();//释放;

31 //退出;

32 phantom.exit();

33 });

34 }

  2.2、phantom.js

  Nodejs 启动一个新的子进程并发送 phantomjs 命令进行截图。截图成功后,发送图片上传命令上传图片:

   1 /**

2 * Created by Administrator on 2016/5/5.

3 */

4 var urls=["http://localhost:3000/","http://localhost:3000/table","http://www.baidu.com"];

5 var count=0;

6 var max=urls.length;

7 if(urls.length!=0){

8 capture(urls[0]);

9 }

10 //生成随机字符串作为图片名称;

11 function createRandomName(len){

12 len = len || 32;

13 /****默认去掉了容易混淆的字符oOLl,9gq,Vv,Uu,I1****/

14 var $chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678';

15 var maxPos = $chars.length;

16 var pwd = '';

17 for (i = 0; i < len; i++) {

18 pwd += $chars.charAt(Math.floor(Math.random() * maxPos));

19 }

20 return pwd;

21 }

22 //开始执行截图命令;

23 function capture(url){

24 var randomPicName='test'+createRandomName(Math.random()*8);

25 console.log("获取的随机名称="+randomPicName);

26 var spawn=require('child_process').spawn;

27 var process=spawn('phantomjs',['capture.js',url,randomPicName,count,max],{cwd:'./routes/'});

28 process.stdout.setEncoding('utf8');

29

30 process.stdout.on("data",function(data){

31 console.log(data);

32 console.log("spawnSTDOUT:"+JSON.stringify(data));

33 var code=data.replace(/[\r\n]/g,"");

34 console.log(code);

35 if(code=='success'){

36 var execFile=require('child_process').execFile;

37 var filePath='./pictures/'+randomPicName+'.png';

38 var execProcess=execFile('node',['upload.js',filePath,randomPicName,count,JSON.stringify(urls)],{cwd:'./routes/'},

39 function(err,stdout,stderr){

40 console.log("execFileSTDOUT:", stdout);

41 console.log("execFileSTDERR:", stderr);

42 });

43 }

44 });

45 process.stderr.on('data',function(data){

46 console.log("stderr"+data);

47 });

48 process.on('close',function(code){

49 if (code == 1) {

50 console.log('child process异常结束。目标:' + url);

51 }

52 });

53 process.on('exit',function(code){

54 console.log('child process exited with code ' + code);

55 count++;

56 if(count!=urls.length){

57 capture(urls[count]);

58 }

59 });

60 }

  2.3、上传.js

  主要是将图片上传到七牛并获取图片的下载地址,并将结果存入本地txt文件:

   1 /**

2 * Created by Administrator on 2016/5/6.

3 */

4 var qiniu = require("qiniu");

5 var config=require('./config');

6 var argvs=process.argv.splice(2);

7 var fs=require("fs");

8 console.log(argvs);

9

10 filePath=argvs[0];

11 key=argvs[1]+'.png';

12 //count;

13 var count=parseInt(argvs[2]);

14 //urls;

15 var urls=JSON.parse(argvs[3]);

16 var max=urls.length;

17 console.log("get the arguments:"+filePath+"---"+key+"--"+count+"---"+max);

18 /**

19 * 第一步:初始化

20 * @type {string}

21 */

22 //需要填写你的 Access Key 和 Secret Key

23 qiniu.conf.ACCESS_KEY = config.qiniu.ACCESS_KEY;

24 qiniu.conf.SECRET_KEY = config.qiniu.SECRET_KEY;

25 //要上传的空间

26 bucket = config.qiniu.Bucket_Name;

27

28 /**

29 * 第二步:获取上传的token

30 * @param bucket

31 * @param key

32 */

33 //构建上传策略函数,设置回调的url以及需要回调给业务服务器的数据

34 function uptoken(bucket, key) {

35 var putPolicy = new qiniu.rs.PutPolicy(bucket+":"+key);

36 console.log("token= "+putPolicy.token());

37 return putPolicy.token();

38 }

39 //生成上传 Token

40 token = uptoken(bucket, key);

41 /**

42 * 第三步:上传图片

43 * @type {string}

44 */

45

46 //构造上传函数

47 function uploadFile(uptoken, key, localFile,count,max) {

48 var extra = new qiniu.io.PutExtra();

49 qiniu.io.putFile(uptoken, key, localFile, extra, function(err, ret) {

50 if(!err) {

51 console.log("上传成功-------------------");

52 // 上传成功, 处理返回值

53 // console.log(ret.hash, ret.key, ret.persistentId);

54 //构建私有空间的链接

55 url = config.qiniu.Domain+ret.key;

56 var policy = new qiniu.rs.GetPolicy();

57 //生成下载链接url

58 var downloadUrl = policy.makeRequest(url);

59 //打印下载的url

60 console.log("downloadUrl= "+downloadUrl);

61 var date=new Date();

62 var dateString=date.toLocaleDateString();//日期;

63 var timeString=date.toLocaleTimeString();//时间;

64 var time=date.toLocaleDateString()+" "+date.toLocaleTimeString();

65 console.log(time);

66 var signalArray={

67 "编号":count+1,

68 "被截屏的路径地址":urls[count],

69 "上传七牛后的图片名称":key,

70 "下载地址":downloadUrl,

71 "截图时间":time

72 };

73 if(count==0){

74 // fs.appendFile(__dirname+'/downloadUrl.txt',"\r\n-----------------"+dateString+" "+timeString+"------------操作开始----------------------\r\n",function(err){

75 // if(err){console.log('fail')}

76 // });

77 fs.appendFileSync(__dirname+'/downloadUrl.txt',"\r\n-----------------"+dateString+" "+timeString+"------------操作开始----------------------\r\n",{encoding:'utf8'});

78 }

79 fs.appendFile(__dirname+'/downloadUrl.txt',JSON.stringify(signalArray)+'\r\n',function(err){

80 if(err){console.log("fail")}

81 });

82 // fs.appendFileSync(__dirname+'/downloadUrl.txt',JSON.stringify(signalArray)+'\r\n',{encoding:'utf8'});

83

84 // if((count+1)==max){

85 // fs.appendFile(__dirname+'/downloadUrl.txt',"\r\n-----------------"+dateString+" "+timeString+"------------操作结束----------------------\r\n",function(err){

86 // if(err){console.log('fail')}

87 // });

88 // fs.appendFileSync(__dirname+'/downloadUrl.txt',"\r\n-----------------"+dateString+" "+timeString+"------------操作结束----------------------\r\n\n",{encoding:'utf8'});

89 // }

90 } else {

91 // 上传失败, 处理返回代码

92 console.log(err);

93 }

94 });

95 }

96 //调用uploadFile上传,并返回下载地址;

97 uploadFile(token, key, filePath,count,max);

  2.4、执行:

  首先, npm install 安装所需的包。二、直接输入“node routes/phantom.js”,回车,程序开始执行。我们来看看执行结果:

  2.4.1、/图片:

  这个目录下还有更多的图片文件,这些是phantomjs截图的图片;

  2.4.2、七牛服务器

  网页登录七牛后,在自己的bucket中可以看到已经添加了很多图片文件,说明我们已经上传成功了:

  

  2.4.3、本地下载Url.txt文件

  

  然后我们测试下载地址是否可以正确下载图片:

  

  

  

  以上就是使用nodejs+phantomjs+七牛实现截图操作的完整方法,将截图上传到七牛,并将下载地址保存在本地磁盘。

  PS:但是有一个问题,七牛的token是有有效期的,也就是说过了有效期,之前的url就不能用了。你可以重新上传一遍,或者直接在七牛上下载之前的图片。

  如果需要源码,可以到我的github下载。下载地址为:

  Phantomjs_pic 项目(生成echarts图表等):;

  phantomjsScreenCapture 项目(实现截图和上传图片):;

  ps:这次只是对phantomjs的一个简单应用。如果您有什么意见和建议,欢迎指出,谢谢!

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线