Nodejs crawler 爬虫
前言
crawler
集合http请求和cheerio
(取页面dom元素时用到的库,用法与jquery
差不多),使用一个库即可。- 本文章将基于官方文档进行梳理。
- demo 移步至NodeJs爬虫-Crawler与Async结合爬取小说网站;
依赖库
单独使用node-crawler
npm install crawler
# or
yarn add crawler
基础调用
var Crawler = require("crawler");
const crawler = new Crawler({
/** 每进行一个队列时,都会被调用 */
callback: (error, res, done) => {
if (error) {
console.error(error);
} else {
/** 默认使用Cheerio */
/** 使用方式于jquery一至 */
let $ = res.$;
const title = $("title").text();
console.log(title);
}
// 每处理一个队列必须要调用done()才会进行下一个队列
done();
}
});
// 指定爬取一个Url
crawler.queue("https://news.sina.com.cn/");
队列(queue)
这里注意一点,队列是并行执行,不分先后顺序
/** 指定爬取一个Url */
crawler.queue("https://news.sina.com.cn/");
/** 爬取多个Url */
crawler.queue(["https://news.sina.com.cn/", "https://news.baidu.com/"]);
/** 自定义当前队列callback */
crawler.queue([
{
url: "http://parishackers.org/",
/** 这里callback会覆盖全局的callback */
callback: (error, res, done) => {
if (error) {
console.log(error);
} else {
/** 具体爬取操作 */
}
done();
}
}
]);
/** 队列传递参数 */
crawler.queue({
uri: "https://news.sina.com.cn/",
parameter1: "value1",
parameter2: "value2"
});
/** 队列传递了参数就可以通过res.options拿到 */
console.log(res.options.parameter1);
/** 在队列中加入一些HTML代码,无需爬取 */
crawler.queue([
{
html: "<p>This is a <strong>test</strong></p>"
}
]);
控制爬取任务间隔
var Crawler = require("crawler");
var c = new Crawler({
/** `maxConnections` 会强制为1个 */
rateLimit: 1000,
callback: function(err, res, done) {
console.log(res.$("title").text());
done();
}
});
/** 在两次任务间最小时间间隔为 1000 (ms) */
c.queue(tasks);
原始body
当需要下载爬到的image、pdf、word时,需要保持原始的response body
,因此需要把encoding
设置为null
。
var fs = require("fs");
var crawler = new Crawler({
encoding: null,
jQuery: false, // 禁用内置cheerio,关闭后将不能选取元素。
callback: (err, res, done) => {
if (err) {
console.error(err.stack);
} else {
fs.createWriteStream(res.options.filename).write(res.body);
}
done();
}
});
crawler.queue({
uri: "https://Nodejs.org/static/images/logos/nodejs-1920x1200.png",
filename: "nodejs-1920x1200.png"
});
预请求(preRequest)
如果需要在每个请求之前做一些操作,可以使用preRequest
var crawler = new Crawler({
preRequest: (options, done) => {
/** 注意:这里的options不是您传递给crawler.queue的options,而是要传递给request模块的选项 */
console.log(options);
done();
},
callback: (err, res, done) => {
if (err) {
console.log(err);
} else {
console.log(res.statusCode);
}
}
});
crawler.queue({
uri: "https://news.sina.com.cn/",
/** 覆盖默认的preRequest */
preRequest: (options, done) => {
setTimeout(function() {
console.log(options);
done();
}, 1000);
}
});
事件
/** 将任务添加到调度程序时调用 */
crawler.on("schedule", options => {
options.proxy = "http://proxy:port";
});
/** 更改限制器时调用 */
crawler.on("limiterChange", (options, limiter) => {});
/** 准备请求时发出,这里是开始请求前最后一次可以修改的地方 */
crawler.on("request", options => {
options.qs.timestamp = new Date().getTime();
});
/** 队列全部运行完调用 */
crawler.on("drain", options => {
/** 这里可以处理资源释放操作,比如关闭数据库等 */
});
静态变量
/** 添加队列 */
crawler.queue(uri | options);
/** 获取队列个数,只读 */
crawler.queueSize;
选项参考
基础请求选项
options.uri
要爬的网站地址options.timeout
- 其他所有的request配置项
回调
callback(error, res, done)
:完成请求后调用的函数error
:错误res
:请求响应体res.statusCode
:HTTP状态码res.body
:HTTP响应内容,可以是HTML页面、纯文本、xml文档res.headers
:HTTP响应头res.request
:HTTP请求体res.request.uri
:解析的URL的HTTP请求实体res.request.method
:HTTP请求方法res.request.headers
:HTTP请求头
res.options
:此任务的选项$
:dom选择器
done
:在回调中,调用done开始进行下一个队列
时间表选项
options.maxConnections
:工作池大小(默认10)options.rateLimit
:每个请求之间延迟的毫秒数(默认0)options.priorityRange
:优先级的范围,从0开始(默认10)options.priority
:优先级,较低的值具有较高的优先级(默认5)
重试选项
options.retries
:如果请求失败,重试次数(默认3)options.retryTimeout
:重试之前延迟的毫秒数(默认10000)
服务器端DOM选项
options.jQuery
:使用cheerio默认配置来注入文档,如果为false,则禁用注入jQuery选择器。如果您的项目中存在内存泄漏问题,请使用替代解析器来避免这种情况(默认true)
字符集编码
options.forceUTF8
:如果为true,则爬虫将从HTTP头或html中的meta标签获取字符集,并在必要时将其转换为UTF8(默认true)options.incomingEncoding
:是否为手动设置编码(默认null)
使用Cheerio或JSDOM
默认情况下使用Cheerio,替换JSDOM的方式如下:
var jsdom = require('jsdom');
var Crawler = require('crawler');
var c = new Crawler({
jQuery: jsdom
});
文章版权声明:除非注明,否则均为猿易帮原创文章,转载或复制请以超链接形式并注明出处。
还没有评论,来说两句吧...