• UID14721
  • 登录2016-12-05
  • 粉丝0
  • 关注0
  • 发帖2
  • 主页
  • 金币18枚
git_CfiiP214799 发布于2016-12-05 23:40
0/785

简单高效的nodejs爬虫模型

楼层直达
这篇文章讲解一下yunshare项目的爬虫模型。
使用 nodejs 开发爬虫很简单,不需要类似 python 的 scrapy 这样的爬虫框架,只需要用 request 或者 superagent 这样的 http 库就能完成大部分的爬虫工作了。
使用 nodejs 开发爬虫半年左右了,爬虫可以很简单,也可以很复杂。简单的爬虫定向爬取一个网站,可能有个几万或者几十万的页面请求,复杂的爬虫类似 google bot 这样搜索引擎的蜘蛛爬虫,要每时每刻爬取互联网上最新的内容。
一般的个人开发者都是用爬虫定向爬取一些网站,然后提取一些结构化的数据,使用 api 接口获取数据也可以归到这一类。如果想简单的练习爬虫技术,可以尝试爬取豆瓣电影数据和书籍数据的,使用 api 接口和爬取 html 页面都能完成这个任务。
爬虫的说白了就是一个 http 客户端,通过 http 协议和远程 http 服务器通信,获取 html 页面内容或者其他的种子文件, pdf 文件等等。和浏览器不同的一点就是爬虫不会把抓取的内容渲染出来,而是解析页面内容然后保存到数据库里面。
在开始学习爬虫的时候我考虑的是怎么爬取 html 页面内容,怎么解析 html 页面之间的链接规则,后来遇到了页面编码的问题。

统一 utf8 编码


国内网站主要是使用 html 和 gbk 这两种编码方式,解决编码有两种思路,第一个是在获取页面内容的时候根据页面的<meta charset='gbk'>编码把内容统一转码成 utf8 的,因为 nodejs 字符串默认编码就是 utf8 。
这个方案充满了不确定性。
问题 1 :不同网站的指定编码的方式不一样,除了前面提到的那种方式,还有<meta http-equiv="Content-Type" content="text/html; charset=gbk">这种方式指定编码,这个问题还不是很大,很多的 http 工具库都能正确的解析这两种编码,问题是还有很多网站没有指定编码,又或者指定的编码和文件的实际编码不一致(遇到过真实的案例)。
问题 2 :如果你把 gbk 编码的 html 文件转成 utf8 编码保存到本地,用浏览器直接打开这个文件的时候会显示乱码,非常不利于开发过程中的查找问题。

不转码 html 内容


既然前面的方案有这么多的问题,剩下的方法就是把 html 内容直接按照原来的编码保存到本地,然后解析的时候指定编码。
这个方法有 2 个好处: 1 、简化了爬虫模型, 2 、可以用浏览器打开 html 文件,不会乱码。唯一的缺点是不同网站文件内容解析的时候似乎需要指定编码,对于小规模爬虫这个问题其实影响不大。

统一爬虫模型


前面的编码方案解决了爬取不同网站 html 文件的编码问题,我们可以用一个统一的爬虫方法爬取不同网站的内容,那如果你想爬取非 html 内容呢?
是不是又要重新写一个爬虫方法,解决这个问题的方法就是 http 协议,假设我们写的这个爬虫方法就是一个完整的 http 客户端,那理论上这个客户端是不是能根据Content-Typ获取各种格式的文件。
那到底能不能用一个简单的方法就能实现上述的功能呢?下面的方法就是我采用 request 写的 nodejs 简单高效的爬虫模型。
function fetch(url) { console.log(`down ${url} started`); const deferred = Q.defer(); const file = getfile(url);
  fs.ensureDirSync(path.dirname(file)); const stream = request
    .get(url)
    .on('error', (err) => {
      deferred.reject(`down ${url}:${err}`);
    })
    .on('response', (res) => { if (res.statusCode !== 200) {
        deferred.reject(`down ${url}:${res.statusCode}`);
      } else { console.log(`down ${url}:${res.statusCode}`);
      }
    })
    .pipe(fs.createWriteStream(`${file}`));

  stream.on('finish', () => {
    deferred.resolve();
  }); return deferred.promise;
}

这段代码在yunshare/src/util/fetch.js里面,当然这个方法不能单独运行,但是关键的逻辑就是这么简单。
不管是什么格式的 http 请求, json , html , torrent 等都统一把返回的二进制格式文件保存到以md5(url)为文件名的位置。上面的getfile就是用来获取文件路径的。

模型扩展


使用 MD5 散列还是有发生冲突的风险的,如果你想要爬取上亿的网页,可能还需要对上面的模型进行扩展。一个简单的思路就是把网页路径中的域名提取出来,不同网站的内容保存在对应的域文件夹下面。
其他的类似的思路也行,需要注意的就是如果爬虫保存文件和解析文件是分开的,你需要保证在解析文件的时候能用同样的方法定位这个文件。共同的参数就是 url ,所以你生成文件名的时候不能用一些随时间变化的参数。
最后,献上第一个使用 node 全栈开发的网站:网盘搜索,目前索引百度网盘资源 1000w 条了。

0人打赏
您需要登录后才可以回帖
发表回复
极贡献
技术问答
专题荟萃
程序人生
视觉设计
Android开发
iOS开发
编程语言
前端开发
后端开发
服务器架构
软件测试
运维方案
创业路上



最热文章墙

  • 72653/370   【精品推荐】200多种Android动画效果的强悍框架,太全了,不看这个,再有动画的问题,不理你了^@^

  • 41448/0   Python爬虫:常用浏览器的useragent

  • 41434/191   情人节福利,程序员表白的正确姿势:改几行代码就变成自己的表白了

  • 37939/259   【精品推荐】Android版产品级的音乐播放器源码,功能太强大了,最好的产品原型有木有?

  • 36492/145   省时省力的Android组件群来了,非常棒的原型参考

  • 28429/2   超全!整理常用的iOS第三方资源

  • 27900/71   原创表白APP,以程序员的姿势备战新年后的7夕,持续完善中!

  • 27791/142   2016抢红包软件及源码

  • 22080/30   麻省理工的一帮疯子,真的实现了随意操控万物!(绝对黑科技)

  • 21897/157   Android版类似UC浏览器:非常赞,产品级的源码

  • 21695/25   Android工程师面试题大全

  • 21539/27   2016程序员跳槽全攻略

  • 21362/9   GitHub上排名前50的iOS项目:总有一款你用得着

  • 20243/20   码魂:程序员的牛B漫画

  • 18445/10   2016年最全的Android面试考题+答案 精编版

  • 18192/3   吐槽那些程序员的搞笑牛逼注释

  • 17825/42   一个绚丽的loading动效分析与实现!

  • 17723/73   【持续更新中】Android福利贴(二):资料源码大放送

  • 17706/85   Android小而全的博客源码:非常适合全面掌握开发技巧

  • 17119/1   iOS 动画总结

  • 16605/45   惊艳的App引导页:背景图片切换加各个页面动画效果

  • 16307/23   个人收集的Android 各类功能源代码

  • 16130/81   仿京东商城客户端Android最新版,不错的原型和学习资料

  • 15948/10   女程序员的梦,众网友的神回复

  • 15843/5   新一代Android渠道打包工具:1000个渠道包只需要5秒

  • 15735/104   Android带弹幕的视频播放器源码,来自大名鼎鼎的Bilibili弹幕网站

  • 15644/11   年会上现场review代码是怎么样的体验!

  • 15527/21   Android福利第三波【Android电子书】

  • 15445/17   用JavaScript 来开发iOS和Android 原生应用:React Native开源框架中文版来啦

  • 15438/53   基于瀑布流的美女图片浏览App,有注释的源代码

  • 15257/23   珍藏多年的素材,灵感搜寻网站

  • 15063/79   【精品推荐】类似360安全卫士安Android源码:非常赞的产品原型

  • 14886/0   iOS中文版资源库,非常全

  • 14513/18   65条最常用正则表达式,你要的都在这里了

  • 14210/15   基于Android支付宝支付设计和开发方案

  • 13674/17   什么是真正的黑客:收获12200+Stars,人气远超微软开源VS

  • 13475/11   有木有这样一张酷图帮你集齐所有git命令超实用

  • 13036/46   在线音乐播放器完整版(商用级的源码):非常赞,可听免费高品质专辑

  • 13020/7   一张图搞定iOS学习路线,非常全面

  • 12937/7   用程序员的姿势抢过年的火车票

  • 12915/0   GitHub iOS 库和框架Top100 

  • 12643/10   成为Java顶尖程序员 ,看这11本书就够了

  • 12517/10   微信支付终于成功了(安卓,iOS),在此分享

  • 12465/18   一张图搞定Android学习路线,非常全面

  • 12323/61   【技巧一】搭配Android Studio,如何实现App远程真机debug?

  • 12131/3   基于Node.js的强大爬虫,能直接发布抓取的文章哦

  • 12078/29   【持续更新中】Android福利贴(一):资料源码

  • 11518/4   46 个非常有用的 PHP 代码片段

  • 11278/3   即时通信第三方库

  • 10890/8   流媒体视频直播方案

  • 10785/18   八个最优秀的Android Studio插件

  • 10743/9   B站建开源工作组:APP想支持炫酷弹幕的看过来

  • 10613/9   烧了5亿美金,这家神秘的公司即将颠覆人类未来!

  • 10467/2   【精品推荐】高质量PHP代码的50个实用技巧:非常值得收藏

  • 10407/10   中国黑客的隐秘江湖:攻守对立,顶尖高手月入千万美元

  • 9793/6   开箱即用!Android四款系统架构工具

  • 9596/10   十大技巧快速提升Android应用开发性能

  • 9532/3   10款GitHub上最火爆的国产开源项目——可以媲美西半球

  • 9457/3   一张图看清Linux 内核运行原理

  • 9359/1   Android性能优化视频,文档以及工具

  • 返回顶部