Node Crawler:强大的Node开源爬虫
Nodejs    2019-02-21 17:05:26    35    0    0
junjie   Nodejs
自从Node横空出世后,很快有人就用它来开发爬虫,网上也常见Node爬虫教程。然而,很难看到一个通用的、功能丰富的爬虫开源项目,到Github上找了一下找到这个,算是目前能找到的最好的了。 这里将它的文档翻译一下,期待更多的实用案例。 **node-crawler** 目标打造成Node社区最强大和流行的爬虫/内容抽取工具库,且支持生产环境。 特性: - 服务端DOM和自动jQuery注入,使用Cheerio(默认)或JSDOM - 可配置的连接池大小和重试次数 - Control rate limit - 支持设置请求队列优先级 - forceUTF8模式可让爬虫处理字符集编码探测和转换 - 兼容Node 4.x及以上版本 更新日志:https://github.com/bda-research/node-crawler/blob/master/CHANGELOG.md #上手指南 ##安装 ``` $ npm install crawler ``` ##使用 ``` var Crawler = require("crawler"); var c = new Crawler({ maxConnections : 10, // 这个回调每个爬取到的页面都会触发 callback : function (error, res, done) { if(error){ console.log(error); }else{ var $ = res.$; // $默认使用Cheerio // 这是为服务端设计的轻量级jQuery核心实现 console.log($("title").text()); } done(); } }); // 爬取一个URL,使用默认的callback c.queue('http://www.amazon.com'); // 爬取URL列表 c.queue(['http://www.google.com/','http://www.yahoo.com']); // 爬取页面,自定义callback和参数 c.queue([{ uri: 'http://parishackers.org/', jQuery: false, // 覆盖全局的callback callback: function (error, res, done) { if(error){ console.log(error); }else{ console.log('Grabbed', res.body.length, 'bytes'); } done(); } }]); // 在队列中加入一些HTML代码,无需爬取(mostly for tests) c.queue([{ html: '

This is a test

' }]); ``` ##控制爬取间隔时间 当你在流量网站时,使用 rateLimit 控制间隔时间。 ``` var crawler = require("crawler"); var c = new Crawler({ rateLimit: 1000, // `maxConnections` 会强制为1个 callback: function(err, res, done){ console.log(res.$("title").text()); done(); } }); c.queue(tasks);//在两次任务间最小时间间隔为 1000 (ms) ``` #配置项指南 你可以将这些配置发给 Crawler() 构造器,让它们成为全局配置,或者自定义 queue() 的请求已覆盖全局配置。 这个配置列表在mikeal的[request项目配置](https://link.jianshu.com/?t=https://github.com/mikeal/request#requestoptions-callback)的基础上做了扩展,并且会直接发送给 request() 方法。 基本请求配置项: - uri: String 你想爬取的网页链接. - timeout : Number 单位是毫秒 (默认 15000). - 支持mikeal的request的所有配置. 回调: - callback(error, res, done): 请求完成后会被调用 - error: Error - res: http.IncomingMessage 请求的回应,包括 `$` 和 `options` - res.statusCode: Number HTTP status code. E.G.200 - res.body: Buffer | String HTTP返回内容,可能是HTML页面、纯文本或XML文档。 - res.headers: Object HTTP请求的返回头 - res.request: Request Mikeal的 Request 的实例,以取代 http.ClientRequest - res.request.uri: urlObject 解析后的URL实体 - res.request.method: String HTTP request method. E.G. GET - res.request.headers: Object HTTP request headers - res.options: Options 配置项 - $: jQuery Selector HTML和XML的选择器 - done: Function 回调中要做的事情做完后需要调用这个 计划任务选项: - maxConnections: Number 连接池大小 (默认 10). - rateLimit: Number 每条请求之间的间隔时间,单位毫秒 (默认 0). - priorityRange: Number 可接受的优先级数值,最小为0 (默认 10). - priority: Number 当前请求的优先级 (默认 5). 重试选项: - retries: Number 请求失败后的重试次数 (默认 3), - retryTimeout: Number 重试前等待的时间,单位毫秒 (默认 10000), 服务端DOM配置: - jQuery: Boolean|String|Object 如果设置为true,使用cheerio和默认配置来注入爬取内容。或使用解析选项自定义cheerio. 当返回false时停止注入jQuery选择器。如果在你的项目中存在内存泄漏,使用一个替代的解析器"whacko"来避免。(默认 true) 字符集编码: - forceUTF8: Boolean 如果设置为true,爬虫将从HTTP请求头中获取字符集或从HTML中获取meta tag,并且将它转换到UTF8,不用再担心编码问题了(默认 true) - incomingEncoding: String 当设置 forceUTF8: true 时可自行设置接收内容的编码 (默认 null),爬虫就不用自己检测编码了。 如, incomingEncoding : 'windows-1255'. 查看 所有支持的编码 缓存: - skipDuplicates: Boolean 设置为true时,跳过已爬取过的URI,甚至不触发 callback()(默认 false)。 不推荐改动,更好的做法是在爬虫之外使用seenreq进行处理。 其它: - rotateUA: Boolean 当为true时, userAgent 应该是数组,并进行轮换 (默认 false) - userAgent: String|Array, 如果 rotateUA 为 false, 但 userAgent 是一个数组, 爬虫将使用第一个值。 - referer: String 当为真时设置HTTP的 referer header ##Class:Crawler **Event: 'schedule'** - options Options 当一个任务被加到计划时触发. ``` crawler.on('schedule',function(options){ options.proxy = "http://proxy:port"; }); ``` **Event: 'limiterChange'** - options Options - limiter String 当limiter改变时触发. **Event: 'request'** - options Options 当爬虫准备好发送请求时触发. 如果你想在发出请求之前的最后阶段改变配置,可以监听这个事件。 ``` crawler.on('request',function(options){ options.qs.timestamp = new Date().getTime(); }); ``` **Event: 'drain'** 当队列为空时触发。 ``` crawler.on('drain',function(){ // 执行一些操作,如,释放数据库连接。 db.end(); // 关闭MySQL连接。 }); **crawler.queue(uri|options)** ``` - uri String - options Options 将任务加入队列并等待执行。 **crawler.queueSize** - Number 队列数量,该属性为只读。 #处理瓶颈 使用limiter控制爬取频率。所有提交到limiter的任务都需要遵守`rateLimit` 和`maxConnections` 的限制。`rateLimit`是两个任务之间的最小间隔,`maxConnections`是最大的并发数。limiters之间是互相独立的。一个通常的用例是为不同的代理设置不同的limiter。另外值得一提的是,当rateLimit设置为非0的值时,maxConnections 的值将被强制为1. ``` var crawler = require('crawler'); var c = new Crawler({ rateLimit: 2000, maxConnections: 1, callback: function(error, res, done) { if(error) { console.log(error) } else { var $ = res.$; console.log($('title').text()) } done(); } }) // 如果你想以2000毫秒的间隔执行任务 c.queue('http://www.somewebsite.com/page/1') c.queue('http://www.somewebsite.com/page/2') c.queue('http://www.somewebsite.com/page/3') // 如果你想为设置代理,并为每个代理设置2000毫秒的间隔 c.queue({ uri:'http://www.somewebsite.com/page/1', limiter:'proxy_1', proxy:'proxy_1' }) c.queue({ uri:'http://www.somewebsite.com/page/2', limiter:'proxy_2', proxy:'proxy_2' }) c.queue({ uri:'http://www.somewebsite.com/page/3', limiter:'proxy_3', proxy:'proxy_3' }) c.queue({ uri:'http://www.somewebsite.com/page/4', limiter:'proxy_1', proxy:'proxy_1' }) ``` ##Work with Cheerio or JSDOM 爬虫默认使用Cheerio,并将JSDOM作为可选的替代。JSDOM更稳定,如果你想使用JSDOM,你需要引入该依赖`require('jsdom')`,并配置爬虫。 **Working with Cheerio** ``` jQuery: true //(default) //OR jQuery: 'cheerio' //OR jQuery: { name: 'cheerio', options: { normalizeWhitespace: true, xmlMode: true } } ``` 这些解析配置从htmlparser2里继承而来。你可以使用所有可用的配置。默认的配置为: ``` { normalizeWhitespace: false, xmlMode: false, decodeEntities: true } ``` 需要所有的配置项和它们的效果,查看 [这里](https://link.jianshu.com/?t=https://github.com/fb55/DomHandler) 以及 [htmlparser2的配置项](https://link.jianshu.com/?t=https://github.com/fb55/htmlparser2/wiki/Parser-options)。[来源](https://link.jianshu.com/?t=https://github.com/cheeriojs/cheerio#loading) Work with JSDOM 要使用JSDOM,你需要先在项目目录下npm install jsdom,然后配置爬虫。 ``` var jsdom = require('jsdom'); var Crawler = require('crawler'); var c = new Crawler({ jQuery: jsdom }); ``` #如何测试 ##安装并运行Httpbin 爬虫使用本地的httpbin来测试。你可以从PyPI安装httpbin并将其作为WSGI应用来允许。比如,使用Gunicorn: ``` $ pip install httpbin # launch httpbin as a daemon with 6 worker on localhost $ gunicorn httpbin:app -b 127.0.0.1:8000 -w 6 --daemon # Finally $ npm install && npm test ``` ##使用Docker 在安装 Docker 之后, 你可以执行: ``` # Builds the local test environment $ docker build -t node-crawler . # Runs tests $ docker run node-crawler sh -c "gunicorn httpbin:app -b 127.0.0.1:8000 -w 6 --daemon && cd /usr/local/lib/node_modules/crawler && npm install && npm test" # You can also ssh into the container for easier debugging $ docker run -i -t node-crawler bash ``` #一些比较困难的待办事项 - 使用zombie来处理有复杂ajax的页面 - Refactoring the code to be more maintainable重构代码以方便维护 - 通过Sizzle测试 (JSDOM bug? https://github.com/tmpvar/jsdom/issues#issue/81) - 支持Promise - 支持Commander - 支持中间件 --- https://github.com/bda-research/node-crawler 作者:pockry 链接:https://www.jianshu.com/p/50450791ce51 來源:简书 简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

上一篇: PHP 数据库驱动、连接数据不同方式学习笔记

下一篇: 测试基本理论知识

Table of content