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 相关文章推荐
基于NodeJS的前后端分离的思考与实践(一)全栈式开发
Sep 26 NodeJs
NodeJS学习笔记之(Url,QueryString,Path)模块
Jan 13 NodeJs
NodeJS实现阿里大鱼短信通知发送
Jan 17 NodeJs
Nodejs--post的公式详解
Apr 29 NodeJs
NodeJS实现微信公众号关注后自动回复功能
May 31 NodeJs
nodejs密码加密中生成随机数的实例代码
Jul 17 NodeJs
Nodejs实现文件上传的示例代码
Sep 26 NodeJs
nodejs读取并去重excel文件
Apr 22 NodeJs
nodejs 使用 js 模块的方法实例详解
Dec 04 NodeJs
Nodejs异步流程框架async的方法
Jun 07 NodeJs
nodejs简单抓包工具使用详解
Aug 23 NodeJs
Nodejs封装类似express框架的路由实例详解
Jan 05 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生成文件
2007/01/15 PHP
随时给自己贴的图片加文字的php水印
2007/03/16 PHP
php过滤XSS攻击的函数
2013/11/12 PHP
PHP反射原理与用法深入分析
2019/09/28 PHP
Javascript调试工具(下载)
2007/01/09 Javascript
doctype后如何获得body.clientHeight的方法
2007/07/11 Javascript
javascript 动态table添加colspan\rowspan 参数的方法
2009/07/25 Javascript
YUI的Tab切换实现代码
2010/04/11 Javascript
Javascript根据指定下标或对象删除数组元素
2012/12/21 Javascript
jQuery.Highcharts.js绘制柱状图饼状图曲线图
2015/03/14 Javascript
js实现select跳转菜单新窗口效果代码分享(超简单)
2015/08/21 Javascript
jQuery实现分章节锚点“回到顶部”动画特效代码
2015/10/23 Javascript
jQuery Mobile开发中日期插件Mobiscroll使用说明
2016/03/02 Javascript
JS基于MSClass和setInterval实现ajax定时采集信息并滚动显示的方法
2016/04/18 Javascript
完美实现八种js焦点轮播图(上篇)
2016/07/18 Javascript
javascript中json对象json数组json字符串互转及取值方法
2017/04/19 Javascript
Angular2下使用pdf插件的方法详解
2017/04/29 Javascript
vue2.0 兄弟组件(平级)通讯的实现代码
2018/01/15 Javascript
JS sort排序详细使用方法示例解析
2020/09/27 Javascript
[34:41]夜魇凡尔赛茶话会 第二期02:你画我猜
2021/03/11 DOTA
使用python实现baidu hi自动登录的代码
2013/02/10 Python
Python操作MySQL数据库的两种方式实例分析【pymysql和pandas】
2019/03/18 Python
Python实现计算长方形面积(带参数函数demo)
2020/01/18 Python
魔幻般冒泡背景的CSS3按钮动画
2016/02/27 HTML / CSS
Oral-B荷兰:牙医最推荐的品牌
2020/02/25 全球购物
书香校园活动方案
2014/02/28 职场文书
升国旗仪式主持词
2014/03/19 职场文书
车辆转让协议书
2014/04/15 职场文书
我的祖国演讲稿
2014/05/04 职场文书
公司委托书格式
2014/08/01 职场文书
报到证办理个人委托书
2014/10/06 职场文书
大学生逃课检讨书
2015/05/04 职场文书
100句拼搏进取的名言警句,值得一读!
2019/10/07 职场文书
详解Nginx启动失败的几种错误处理
2021/04/01 Servers
python数据分析之用sklearn预测糖尿病
2021/04/22 Python
Win11怎么进入安全模式?Windows 11进入安全模式的方法
2021/11/21 数码科技