解析web网页并保存页面中的图片
这个功能,是很多类似爬虫的应用需要实现的。
如果使用node.js,你会惊讶的发现,这个任务实现起来很容易,就象写嵌入在页面中的javascript一样。
建议没接触过node.js的,可以先看看 node.js能干什么?,里面已经包含了最简单的解析web网页的功能。
这次做的是更具体的事情,我想把维基百科的坦克词条文章抽取出标题和一个图片:
要想开发这个应用,需要为node.js安装jquery库,因为我要用它处理html dom树。具体做法,可参见 在node.js中使用jquery。
这是我第一次使用WebStorm做web前端项目开发,之前主要用Eclipse。放弃Eclipse是因为它的问题越来越多,比如编辑javascript有时候莫名其妙的弹出错误。我估计这和IBM减少对它的投资有关。使用WebStorm的感受很好,我计划在试用结束后购买正式版本。
代码很短,我在github上开了个项目,源代码 见这里。
如果已经本地安装了node和jquery for node,那么就可以执行:
$ node app.js
book.title: 坦克 book.coverImageUrl: //upload.wikimedia.org/wikipedia/commons/thumb/7/73/Iraq-m1_abrams.jpg/300px-Iraq-m1_abrams.jpg
file saved
执行后,会在当前目录找到文件tank.png,这是下载的图片文件。
我把源代码贴在这里:
//声明所需依赖库的对象
var $ = require(‘jquery’),
fs = require(‘fs’),
http = require(‘http’);//http参数对象
var options = {
host:’zh.wikipedia.org’,
port:80,
path:’/wiki/%E5%9D%A6%E5%85%8B’
};var html = ”;//http获取html字符串
var tankBook = {};//分析html获得数据对象http.get(options, function (res) {
res.on(‘data’,
function (data) {//加载数据,一般会执行多次
html += data;
}).on(‘end’, function () {//加载完成
var dom = $(html);//生成文档树
tankBook.title = dom.find(‘#firstHeading’).text();//获取文档标题
tankBook.coverImageUrl = dom.find(‘.thumbimage’).first()[0].src;//获取文档封面图url
console.log(‘book.title: ‘ + tankBook.title + ‘ book.coverImageUrl: ‘ + tankBook.coverImageUrl);
savekImageFile();
});
});function savekImageFile() {
var hostName = tankBook.coverImageUrl.split(‘/’)[2];
var path = tankBook.coverImageUrl.substring(tankBook.coverImageUrl.indexOf(hostName) + hostName.length);var options = {
host:hostName,
port:80,
path:path
};http.get(options, function (res) {
res.setEncoding(‘binary’);
var imageData = ”;res.on(‘data’, function (data) {//图片加载到内存变量
imageData += data;
}).on(‘end’, function () {//加载完毕保存图片
fs.writeFile(‘tank.png’, imageData, ‘binary’, function (err) {
if (err) throw err;
console.log(‘file saved’);
});
});
});
}
代码不多,我重点说一下两个处理内容。
javascript不支持前向后向查找结合使用,这样,我在取图片链接的时候遇到点儿麻烦:
//upload.wikimedia.org/wikipedia/commons/thumb/7/73/Iraq-m1_abrams.jpg/300px-Iraq-m1_abrams.jpg
我需要得到host name:
upload.wikimedia.org
可能办法很多,我最终使用字符串的处理方法解决的。
还有一个事情,javascript是处理不了二进制内容的,这是和flash很大的区别,当然,这种认识是针对目前的浏览器的。node.js脱离浏览器,因此不受这个限制。它的fs模块可直接操作文件。
另外,我使用Mac Lion,WebStorm的一些组合快捷键,使用到f功能键,比如shift+f10,是运行项目,可是f10被用于缩小(平铺)当前应用各窗口了。我在settings的keymap中,为run增加了command+shift+R,本来想用command+R,这样就和我用xcode的快捷键一致了,但是冲突。
还有个问题,WebStorm开发,怎么集成对node的支持。主界面有个图标:
用它设置你的node.js源代码的目录。也许有人下载了直接可以运行的node.js,那需要再下载一下node.js的源代码包,在github上。
执行node应用,也需要设置一下,创建单独的node.js运行配置: