nodejs 爬虫相关模块小整合

AnyaUJVI 8年前
   <p>爬虫关键步骤都围绕在于 请求 、 获取数据 、 处理数据 ,当然还有应对一些反爬虫的策略,比如伪造headers,ip代理等等,下文就主要围绕nodejs我常用的模块和经验谈起</p>    <h3><strong>请求和获取数据模块</strong></h3>    <p>superagent</p>    <p>名字就叫做超级代理,是一个非常实用的http请求模块,常用于 get 、 post 等请求,对于nodejs爬虫我主要就用它来实现请求操作,还有一些表单post操作,模拟ajax请求等,z支持链式调用</p>    <pre>  superagent.post(url)      .set(headers) //设置请求头      .set('Cookie', cookie) // 设置cookie      .type('form')      .send({          //表单数据      })      .end(function(err, res) {          //数据与错误处理  })  </pre>    <p>中文文档: <a href="/misc/goto?guid=4959723178880240327" rel="nofollow,noindex">https://cnodejs.org/topic/5378720ed6e2d16149fa16bd</a></p>    <p>superagent-charset</p>    <p>这个是上面那个模块的拓展,因为 superagent 只支持 UTF-8 ,用了这个库可以指定编码,当你用 superagent 爬出乱码时可以使用它</p>    <pre>  superagent.get(url)      .set(headers)       .charset('gbk') //指定编码      .end(function(err, res) {          if (err) {              return console.err(err);          }      })  </pre>    <p>superagent-retry</p>    <p>当你遇到以下错误的时候,可以使用它,之前我用了它确实错误问题就解决了</p>    <ul>     <li>ECONNRESET</li>     <li>ECONNREFUSED</li>     <li>ETIMEDOUT</li>     <li>EADDRINFO</li>     <li>ESOCKETTIMEDOUT</li>     <li>superagent client timeouts</li>     <li>bad gateway errors (502, 503, 504 statuses)</li>     <li>Internal Server Error (500 status)</li>    </ul>    <pre>  var superagent = require('superagent');  require('./superagent-retry')(superagent);  superagent.get(url)      .set(headers_visit)      .retry(2) //在响应前请求两次      .end(function(err, res) {          if (err) {              return console.err(err);          }       })  </pre>    <h3><strong>处理数据模块</strong></h3>    <p>cheerio</p>    <p>这是一个非常好用的处理模块,是jQuery的子集,可以使用大量jQuery的语法来获取你爬虫请求到的数据,用正则真是太不友好~</p>    <pre>  superagent.get(url)      .set(headers)      .end(function(err, res) {          if (err) {              return console.err(err);          }          $ = cheerio.load(res.text);          // $(".XXX")选中class          // $("#XXX")选中id          // ...          })  </pre>    <p>中文文档: <a href="/misc/goto?guid=4959723179200865450" rel="nofollow,noindex">https://cnodejs.org/topic/5203a71844e76d216a727d2e</a></p>    <p>fs</p>    <p>它虽然是一个模块,但并不需要从npm下载(npm里的那个就一句话 console.log("I'm fs modules"); ),是nodejs自带的文件系统模块,直接引入即可,提供了nodejs本地读写的能力,可以写入读取本地文件,我们爬虫如果不需要写入数据库,写入本地的话,就必须得用到它了</p>    <pre>  var fs = require('fs');  // 读取文件  fs.readFile('input.txt', function (err, data) {    if (err) {       return console.error(err);    }  });  // 写入文件  fs.writeFile('input.txt', 'XXX',  function(err) {     if (err) {         return console.error(err);     }  });  </pre>    <p>中文教程: <a href="/misc/goto?guid=4959723179299667154" rel="nofollow,noindex">http://www.runoob.com/nodejs/nodejs-fs.html</a></p>    <p>excel相关</p>    <p>最近爬的数据需要爬入excel,然而fs模块并不能直接写入xlsx,就得用别的途径</p>    <p>node-xlsx</p>    <p>这个模块挺简单上手的,我只试过导出excel,也可以读取,觉得挺方便,具体其他可以直接看docs</p>    <pre>  var xlsx = require('node-xlsx');  var fs = require('fs');    var data = [      [1, 2, 3],      [true, false, null, 'sheetjs'],      ['foo', 'bar', new Date('2014-02-19T14:30Z'), '0.3'],      ['baz', null, 'qux']  ];    var buffer = xlsx.build([{      name: 'mySheet',      data: data  }]);    fs.writeFile('test.xlsx', buffer, {          'flag': 'w+'      }, function(err) {          if (err) {              return console.error(err);          }          console.log("写入成功");      });  </pre>    <p>tips:不过因为我爬取大量数据,如果一味放数组里也会让程序崩溃,但是我开启 a+ 这个fs的追加模式,发现写入有点问题,所以我最近采用了逗号分割csv的方式</p>    <p>csv</p>    <p>.csv后缀文件可以以纯文本存储表格数据,然后我直接用 fs 写入,用 , 来分割列,用 \n 来分割行就解决问题了,这个简单快捷</p>    <h3><strong>异步处理模块</strong></h3>    <p>这个我没去调研各个模块,,就只介绍我用过的</p>    <p>对于异步这在node爬虫中是必须去处理的,因为fs写入文件,superagent请求这些都是异步的,我们可以用 promise 来解决,当然es6出现了 generator 生成器解决回调,还有es7的 async/await 的异步解决方案,这里就暂且不说这些了,我就只介绍下我使用的 async 模块</p>    <p>async</p>    <p>这是一个异步流程控制模块,还可以在爬虫时控制并发数目,通常来说我们爬取一堆url有规律的数据,我通常构造一个数组然后使用它来解决异步</p>    <pre>  // 我这里对一个有规律的url+urlArr[i]进行爬取  for (var i = 1; i <= 900000; i++) {      urlArr.push(i);  }  // 这里是分6批执行,每一批并行,批之间按顺序  async.eachLimit(urlArr, 6, function(item, callback) {      spider(item, callback);//爬虫函数      // 用callback(null)代表完成      // 用callback('err')代表错误  }, function(err) {      if (err) {          return console.log(err);      }      console.log("结束");  });  </pre>    <p>这个模块就可以解决我的异步问题了,更多用法看这位作者写的,挺详细的, <a href="/misc/goto?guid=4959723179610794264" rel="nofollow,noindex">https://github.com/alsotang/async_demo</a></p>    <h3><strong>其他模块</strong></h3>    <p>这些模块就有些针对爬虫特定需求的</p>    <p>node-tesseract</p>    <p>这是验证码识别相关的</p>    <ul>     <li>可以看我的文章 <a href="/misc/goto?guid=4959723179724792979" rel="nofollow,noindex">https://bupt-hjm.github.io/2016/05/29/buptclass/</a></li>     <li>还有这位前辈写的 <a href="/misc/goto?guid=4959661419604399213" rel="nofollow,noindex">http://think2011.net/2016/01/31/node-ocr/</a></li>    </ul>    <p>node-schedule</p>    <p>当我们的爬虫需要定时爬取的时候,它就可以发挥巨大作用啦</p>    <ul>     <li> <p>node.js中使用node-schedule实现定时任务实例</p> </li>    </ul>    <p>node-ssh2sync</p>    <p>之前我爬取教务系统,因为只能校园网访问,所以我就只能本地爬取上传服务器,这个不是npm下载的模块,直接从github下载,作为我简单的上传需求,它还是挺好用的</p>    <pre>  var ssh2sync = require('ssh2sync');    var root_local = ... ; // Grab these from command line arguments?  var root_remote = ...;  var force = true;    ssh2sync.upload(root_local, root_remote, force, {        //    debug: console.log,      host: ... remote host name ...,      port: 22,      username: ... user name ...,      privateKey: require('fs').readFileSync('/path/to/users/.ssh/id_dsa')      // OR password: ... the password ..  });  </pre>    <h3> </h3>    <p> </p>    <p>来自:http://bupt-hjm.github.io/2016/10/31/nodejs-spider-experience/</p>    <p> </p>