nodeJs爬虫的技术点总结


Posted in NodeJs onMay 13, 2018

背景

最近打算把之前看过的nodeJs相关的内容在复习下,顺便写几个爬虫来打发无聊,在爬的过程中发现一些问题,记录下以便备忘。

依赖

用到的是在网上烂大街的cheerio库来处理爬取的内容,使用superagent处理请求,log4js来记录日志。

日志配置

话不多说,直接上代码:

const log4js = require('log4js');

log4js.configure({
 appenders: {
  cheese: {
   type: 'dateFile',
   filename: 'cheese.log',
   pattern: '-yyyy-MM-dd.log',
   // 包含模型
   alwaysIncludePattern: true,

   maxLogSize: 1024,
   backups: 3 }
 },
 categories: { default: { appenders: ['cheese'], level: 'info' } }
});

const logger = log4js.getLogger('cheese');
logger.level = 'INFO';

module.exports = logger;

以上直接导出一个logger对象,在业务文件里直接调用logger.info()等函数添加日志信息就可以,会按天生成日志。相关信息网络上一堆。

爬取内容并处理

superagent.get(cityItemUrl).end((err, res) => {
  if (err) {
   return console.error(err);
  }

  const $ = cheerio.load(res.text);
  // 解析当前页面,获取当前页面的城市链接地址
  const cityInfoEle = $('.newslist1 li a');
  cityInfoEle.each((idx, element) => {
   const $element = $(element);
   const sceneURL = $element.attr('href'); // 页面地址
   const sceneName = $element.attr('title'); // 城市名称
   if (!sceneName) {
    return;
   }
   logger.info(`当前解析到的目的地是: ${sceneName}, 对应的地址为: ${sceneURL}`);

   getDesInfos(sceneURL, sceneName); // 获取城市详细信息

   ep.after('getDirInfoComplete', cityInfoEle.length, (dirInfos) => {
    const content = JSON.parse(fs.readFileSync(path.join(__dirname, './imgs.json')));

    dirInfos.forEach((element) => {
     logger.info(`本条数据为:${JSON.stringify(element)}`);
     Object.assign(content, element);
    });

    fs.writeFileSync(path.join(__dirname, './imgs.json'), JSON.stringify(content));
   });
  });
 });

使用superagent请求页面,请求成功后使用cheerio 来加载页面内容,然后使用类似Jquery的匹配规则来查找目的资源。

多个资源加载完成,使用eventproxy来代理事件,处理一次资源处罚一次事件,所有事件触发完成后处理数据。

以上就是最基本的爬虫了,接下来就是一些可能会出问题或者需要特别注意的地方了。。。

读写本地文件

创建文件夹

function mkdirSync(dirname) {
 if (fs.existsSync(dirname)) {
  return true;
 }
 if (mkdirSync(path.dirname(dirname))) {
  fs.mkdirSync(dirname);
  return true;
 }

 return false;
}

读写文件

const content = JSON.parse(fs.readFileSync(path.join(__dirname, './dir.json')));

   dirInfos.forEach((element) => {
    logger.info(`本条数据为:${JSON.stringify(element)}`);
    Object.assign(content, element);
   });

   fs.writeFileSync(path.join(__dirname, './dir.json'), JSON.stringify(content));

批量下载资源

下载资源可能包括图片、音频等等。

使用Bagpipe处理异步并发 参考

const Bagpipe = require('bagpipe');

const bagpipe = new Bagpipe(10);

  bagpipe.push(downloadImage, url, dstpath, (err, data) => {
   if (err) {
    console.log(err);
    return;
   }
   console.log(`[${dstpath}]: ${data}`);
  });

下载资源,使用stream来完成文件写入。

function downloadImage(src, dest, callback) {
 request.head(src, (err, res, body) => {
  if (src && src.indexOf('http') > -1 || src.indexOf('https') > -1) {
   request(src).pipe(fs.createWriteStream(dest)).on('close', () => {
    callback(null, dest);
   });
  }
 });
}

编码

有时候直接使用 cheerio.load处理的网页内容,写入文件后发现是编码后的文字,可以通过

const $ = cheerio.load(buf, { decodeEntities: false });

来禁止编码,

ps: encoding库和iconv-lite未能实现将utf-8编码的字符转换为中文,可能是还对API不熟悉,稍后可以关注下。

最后,附上一个匹配所有dom标签的正则

const reg = /<.*?>/g;
NodeJs 相关文章推荐
ubuntu下安装nodejs以及升级的办法
May 08 NodeJs
nodejs根据ip数组在百度地图中进行定位
Mar 06 NodeJs
NodeJs安装npm包一直失败的解决方法
Apr 28 NodeJs
NodeJS设计模式总结【单例模式,适配器模式,装饰模式,观察者模式】
Sep 06 NodeJs
nodejs实现简单的gulp打包
Dec 21 NodeJs
nodejs使用redis作为缓存介质实现的封装缓存类示例
Feb 07 NodeJs
Nodejs使用Mongodb存储与提供后端CRD服务详解
Sep 04 NodeJs
详解从NodeJS搭建中间层再谈前后端分离
Nov 13 NodeJs
监控Nodejs的性能实例代码
Jul 02 NodeJs
NodeJs实现简易WEB上传下载服务器
Aug 10 NodeJs
nodejs nedb 封装库与使用方法示例
Feb 06 NodeJs
详解nodejs内置模块
May 06 NodeJs
修改Nodejs内置的npm默认配置路径方法
May 13 #NodeJs
nodejs取得当前执行路径的方法
May 13 #NodeJs
详解Nodejs内存治理
May 13 #NodeJs
nodejs更改项目端口号的方法
May 13 #NodeJs
利用nodeJs anywhere搭建本地服务器环境的方法
May 12 #NodeJs
NodeJs搭建本地服务器之使用手机访问的实例讲解
May 12 #NodeJs
nodejs 简单实现动态html的方法
May 12 #NodeJs
You might like
php检测图片木马多进制编程实践
2013/04/11 PHP
PHP大文件及断点续传下载实现代码
2020/08/18 PHP
javascript脚本编程解决考试分数统计问题
2008/10/18 Javascript
基于jquery点击自以外任意处,关闭自身的代码
2012/02/10 Javascript
如何使用JS获取IE上传文件路径(IE7,8)
2013/07/08 Javascript
js 显示base64编码的二进制流网页图片
2014/04/04 Javascript
javascript异步处理工作机制详解
2015/04/13 Javascript
Node.js读写文件之批量替换图片的实现方法
2016/09/07 Javascript
BootStrap下拉菜单和滚动监听插件实现代码
2016/09/26 Javascript
移动端点击态处理的三种实现方式
2017/01/12 Javascript
Angular实现一个简单的多选复选框的弹出框指令实例
2017/04/25 Javascript
基于AngularJS实现表单验证功能
2017/07/28 Javascript
jquery实现回车键触发事件(实例讲解)
2017/11/21 jQuery
JS执行控制之节流模式实例分析
2018/12/21 Javascript
vuex + keep-alive实现tab标签页面缓存功能
2019/10/17 Javascript
Python实现全角半角转换的方法
2014/08/18 Python
Python中的高级函数map/reduce使用实例
2015/04/13 Python
使用Protocol Buffers的C语言拓展提速Python程序的示例
2015/04/16 Python
python使用paramiko实现远程拷贝文件的方法
2016/04/18 Python
快速实现基于Python的微信聊天机器人示例代码
2017/03/03 Python
Python不使用int()函数把字符串转换为数字的方法
2018/07/09 Python
查看python安装路径及pip安装的包列表及路径
2019/04/03 Python
Python列表(list)所有元素的同一操作解析
2019/08/01 Python
python3 实现爬取TOP500的音乐信息并存储到mongoDB数据库中
2019/08/24 Python
使用Python爬虫库requests发送请求、传递URL参数、定制headers
2020/01/25 Python
关于Python3的import问题(pycharm可以运行命令行import错误)
2020/11/18 Python
一套SQL笔试题
2016/08/14 面试题
大学生职业生涯规划范文
2013/12/31 职场文书
2014银行授权委托书样本
2014/10/04 职场文书
高中生逃课检讨书
2014/10/10 职场文书
复试通知单模板
2015/04/24 职场文书
简单的辞职信模板
2015/05/12 职场文书
创业方案:赚钱的烧烤店该怎样做?
2019/07/05 职场文书
2019年新郎保证书3篇
2019/10/17 职场文书
golang 在windows中设置环境变量的操作
2021/04/29 Golang
golang switch语句的灵活写法介绍
2021/05/06 Golang