前三篇文章基本完整的讲述了怎么去采集一个页面,但是一个页面的妹子不够看咋办啊,我都想要采集下来慢慢看啊!
这很简单啊,采集一个页面只要输入当前页面的url就可以,采集多个页面只要输入多个url不就得了。当然肯定不能逐个手动输入,但是我们可以把这些url存入数组中,然后遍历数组不就可以了~
那么我们怎么去获取这些url呢?我一般都会采取以下几个方法:
1、url拼凑法,仔细观察要采集的网站,有的网站内容页的url基本都是连贯的,比如咱的校花网,他的url前半部分都一样,都是“http://www.xiaohuar.com/news-1-”,后半部分就是1.html、2.html等逐步递增的,于是我们可以找出最小值跟最大值,然后写一个for循环自动生成url数组:
var minPageId=1; var maxPageId=1722; var urlsArr=[]; for(var i=minPageId;i<=maxPageId;i++){ var url='http://www.xiaohuar.com/news-1-'+i+'.html'; urlsArr.push(url); } console.log(urlsArr);
这样就可以拼凑出想要的url了。但是这个方法有个缺点就是,万一网站的url不连贯甚至不是以id命名咋办?
2、列表获取法,大多数网站都会有一个文章列表页的,只要我们找到文章列表页,然后把里面的url都提取出来不就可以了,这个方法基本可以保证万无一失了。
比如校花网的列表页是这个:http://www.xiaohuar.com/2014.html。打开这个页面可以发现一开始是各学妹的缩略图,但只有120个,肯定不能满足需求啊,再往下看,你会看到一长串的学妹链接,数了数(你真愿意一个个的数我也不拦着,反正我是直接搜索“资料照片”这四个关键字获得的结果),有997个啊!这么多啊!只要把这些链接采集下来基本就可以获取所有学妹了啊!细心的同学可以发现,列表中只有997个学妹,而通过上段for循环得到的结果有1722个,这显然有一部分url是无效的,所以列表获取法得到的数据更精准,不过也不排除列表不完全的情况,根据需求来吧。
思路有了,接下来就是采集http://www.xiaohuar.com/2014.html页面中的列表了。
用到的方法依然是http.request。写代码要有一种意识,重复使用的代码要封装起来。在nodejs中,最常见的封装就是模块(本文要是不说模块这两个字都对不起我起的标题)。也就是我们npm install的那些个的东西。当然我们自己写的模块就不需要npm install了,直接弄个文件放在目录下,然后引用就好。当然啦,你要是也需要npm install你自己写的模块,你也就不屑于看我这篇教程了,哈哈哈哈哈。
好了,言归正传,nodejs模块的基础知识都在这里:http://www.runoob.com/nodejs/nodejs-module-system.html,我就不重复了。只说一点,exports跟module.exports是有区别的,具体的区别网上一搜也一堆,如果实在闹不清楚,你就用module.exports。
接下来我们就把http.request封装起来吧。
var http = require("http"); var BufferHelper = require('bufferhelper'); var querystring = require('querystring'); function spider(options, formData, callback) { if (options) {//判断是否传入参数 var req = http.request(options, function (res) { var bufferHelper = new BufferHelper(); res.on('data', function (chunk) { bufferHelper.concat(chunk); }).on('end', function () { var val = bufferHelper; callback(val); }); }); if (formData) {//判断是不是post,如果是post,记得在options参数里做相应设置 req.write(querystring.stringify(formData)).on('error', function (e) { console.log("Got error: " + e.message); callback(null); }).end(); } else { req.on('error', function (e) { console.log("Got error: " + e.message); callback(null); }).end(); } }else{ console.log('参数错误'); } } module.exports = spider;
将以上代码保存到文件spider.js中,调用的时候就是var spider = require('./spider');//引用路径取决于spider.js存放路径。
那么我们获取所有url的代码如下:
var http = require("http"); var cheerio = require("cheerio"); var iconv = require('iconv-lite'); var fs = require("fs"); var spider = require('./spider');//调用模块 var url='http://www.xiaohuar.com/2014.html'; spider(url, null, function (data) {//此处的data就是spider.js文件中通过callback(bufferHelper)传过来的bufferHelper,所以其类型是buffer。 var val = iconv.decode(data.toBuffer(), 'gb2312');//将获取到的数据由gb2312编码转成utf8编码 var $ = cheerio.load(val, {decodeEntities: false}); var urls=''; $('.newsboxlist ul li a').each(function(){ var thisUrl=$(this).attr('href'); urls+=thisUrl+','; }); fs.writeFile('urlList.txt', urls, function () { console.log('保存成功'); }); });
上述代码就是把所有url采集下来并保存在了文件urlList.txt中。也许你会问,为啥要保存在txt中而不是直接保存成数组紧接着遍历采集呢?很简单,万一在遍历采集的时候程序故障中断了的话,我们岂不是在重新运行代码的时候又要重新采集列表,重新生成数组,重新采集一遍那些已经采集过的页面么?这样会降低效率增加损耗的。将这些url保存成文件的话,我们在重新采集的时候就只需要从urlList.txt中读取url就可以,而不需要再去采集一遍列表页。而且还可以每采集完一个或几个页面,就从urlList.txt中删除对应的链接,那么再重新采集就可以从中断处进行采集,极大的提高了程序运行的效率。
本节对模块的讲述其实并不多,因为这是nodejs的基础知识,我再怎么写也是从别处抄来的,所以还不如引导大家去菜鸟教程看呢,本节只是通过一个简单的代码来演示一下我们怎么自己写简单的模块就好。我也想教教大家怎么写牛的复杂的模块,但是我也没写过,臣妾做不到啊。。。
未经允许不得转载:前端撸码笔记 » [nodejs实战:校花网学妹图片采集+站点发布]四、批量采集:模块封装及调用