NodeJs爬虫-Crawler

02-07
评论
字数统计:5490(字)
使用crawler实现在nodejs上进行爬虫,本文将对官方文档进行梳理。

前言

  • crawler 集合http请求和cheerio(取页面dom元素时用到的库,用法与jquery差不多),使用一个库即可。

  • 本文章将基于官方文档进行梳理。

依赖库

单独使用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
});
本文链接:https://blog.crazylei.com/art/2e556b30
版权声明: 本博客所有文章除特别声明外,均采用CC BY 4.0 CN协议 许可协议。转载请注明出处!

评论

正在加载评论...

©2022 Crazylei Bolg沪ICP备20001821号