这篇文章讲解一下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条了。

简单高效的nodejs爬虫模型的更多相关文章

  1. 简单实现nodejs爬虫工具

    约30行代码实现一个简单nodejs爬虫工具,定时抓取网页数据. 使用npm模块 request---简单http请求客户端.(轻量级) fs---nodejs文件模块.   index.js var ...

  2. NodeJS 爬虫爬取LOL英雄联盟的英雄信息,批量下载英雄壁纸

    工欲善其事,必先利其器,会用各种模块非常重要. 1.模块使用 (1)superagent:Nodejs中的http请求库(每个语言都有无数个,java的okhttp,OC的afnetworking) ...

  3. Nodejs爬虫进阶教程之异步并发控制

    Nodejs爬虫进阶教程之异步并发控制 之前写了个现在看来很不完美的小爬虫,很多地方没有处理好,比如说在知乎点开一个问题的时候,它的所有回答并不是全部加载好了的,当你拉到回答的尾部时,点击加载更多,回 ...

  4. NodeJS爬虫系统初探

    NodeJS爬虫系统 NodeJS爬虫系统 0. 概论 爬虫是一种自动获取网页内容的程序.是搜索引擎的重要组成部分,因此搜索引擎优化很大程度上是针对爬虫而做出的优化. robots.txt是一个文本文 ...

  5. 【nodeJS爬虫】前端爬虫系列

    写这篇 blog 其实一开始我是拒绝的,因为爬虫爬的就是cnblog博客园.搞不好编辑看到了就把我的账号给封了:). 言归正传,前端同学可能向来对爬虫不是很感冒,觉得爬虫需要用偏后端的语言,诸如 ph ...

  6. nodejs爬虫如何设置动态ip以及userAgent

    nodejs爬虫如何设置动态ip以及userAgent 转https://blog.csdn.net/u014374031/article/details/78833765 前言 在写nodejs爬虫 ...

  7. nodejs爬虫--抓取CSDN某用户全部文章

    最近正在学习node.js,就像搞一些东西来玩玩,于是这个简单的爬虫就诞生了. 准备工作 node.js爬虫肯定要先安装node.js环境 创建一个文件夹 在该文件夹打开命令行,执行npm init初 ...

  8. NLP论文解读:无需模板且高效的语言微调模型(上)

    原创作者 | 苏菲 论文题目: Prompt-free and Efficient Language Model Fine-Tuning 论文作者: Rabeeh Karimi Mahabadi 论文 ...

  9. 【中文分词】简单高效的MMSeg

    最近碰到一个分词匹配需求--给定一个关键词表,作为自定义分词词典,用户query文本分词后,是否有词落入这个自定义词典中?现有的大多数Java系的分词方案基本都支持添加自定义词典,但是却不支持HDFS ...

随机推荐

  1. (ios)MPMoviePlayerController首次播放视频的时候,没有控制条

    问题: 在视频播放时,现在控制条采用磨砂的效果,会遮罩部分视频 解决思路 1 播放器直接设置不带控制条,在app在 Foreground状态,默认播放器暂停,这样需要在获得Foreground事件,进 ...

  2. 驳 GarbageMan 的《一个超复杂的简介递归》——对延迟计算的实验和思考

    这是一篇因骂战而起的博文,GarbageMan 在该文章回复中不仅对我进行了侮辱,还涉及了我的母校,特写此文用理性的分析和实验予以回击. 在此也劝告 GarbageMan,没什么本事就别在那叫嚣了,还 ...

  3. storm实战:基于storm,kafka,mysql的实时统计系统

    公司对客户开放多个系统,运营人员想要了解客户使用各个系统的情况,在此之前,数据平台团队已经建设好了统一的Kafka消息通道. 为了保证架构能够满足业务可能的扩张后的性能要求,选用storm来处理各个应 ...

  4. SqlServer链接MySql操作步骤

    Sql Server版本 2008R2 1.从MySQL网站下载最新的MySQL ODBC驱动:http://www.mysql.com/downloads/connector/odbc/,我下载的版 ...

  5. 一个update的小故事

    偶尔测试了一段小代码,写个循环 if object_id('tempdb..#TB') is not null drop table #TB go create table #TB ( ID int ...

  6. 使用Hive或Impala执行SQL语句,对存储在Elasticsearch中的数据操作

    http://www.cnblogs.com/wgp13x/p/4934521.html 内容一样,样式好的版本. 使用Hive或Impala执行SQL语句,对存储在Elasticsearch中的数据 ...

  7. 数据分页处理系列之二:HBase表数据分页处理

      HBase是Hadoop大数据生态技术圈中的一项关键技术,是一种用于分布式存储大数据的列式数据库,关于HBase更加详细的介绍和技术细节,朋友们可以在网络上进行搜寻,笔者本人在接下来的日子里也会写 ...

  8. db2服务端安装图解

    一. 准备工作 1. db2服务端安装包,版本:10.1.2 二. 安装图解过程 1. 响应文件是一个包含安装和配置信息的纯英文文本文件.可无需任何用户交互进行db2的批量安装.非必须的. 2. 点击 ...

  9. Linux开机启动(bootstrap)

    计算机开机是一个神秘的过程.我们只是按了开机键,就看到屏幕上的进度条或者一行行的输出,直到我们到达登录界面.然而,计算机开机又是个异常脆弱的过程,我们满心期望的登录界面可能并不会出现,而是一个命令行或 ...

  10. CentOS 6.5下利用Rsyslog+LogAnalyzer+MySQL部署日志服务器

    一.简介 LogAnalyzer 是一款syslog日志和其他网络事件数据的Web前端.它提供了对日志的简单浏览.搜索.基本分析和一些图表报告的功能.数据可以从数据库或一般的syslog文本文件中获取 ...