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 socket实现的服务端和客户端功能示例
Jun 02 NodeJs
NodeJS链接MySql数据库的操作方法
Jun 27 NodeJs
nodejs Assert中equal(),strictEqual(),deepEqual(),strictDeepEqual()比较
Sep 18 NodeJs
nodejs实现简单的gulp打包
Dec 21 NodeJs
nodejs使用http模块发送get与post请求的方法示例
Jan 08 NodeJs
nodejs基于WS模块实现WebSocket聊天功能的方法
Jan 12 NodeJs
原生nodejs使用websocket代码分享
Apr 07 NodeJs
nodeJS模块简单用法示例
Apr 21 NodeJs
基于Koa(nodejs框架)对json文件进行增删改查的示例代码
Feb 02 NodeJs
nodejs实现日志读取、日志查找及日志刷新的方法分析
May 20 NodeJs
NodeJS实现一个聊天室功能
Nov 25 NodeJs
NodeJS多种创建WebSocket监听的方式(三种)
Jun 04 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做的端口嗅探器--可以指定网站和端口
2006/10/09 PHP
探讨:web上存漏洞及原理分析、防范方法
2013/06/29 PHP
PHP实现的简单操作SQLite数据库类与用法示例
2017/06/19 PHP
PHP单例模式简单用法示例
2017/06/23 PHP
JavaScript入门教程(12) js对象化编程
2009/01/31 Javascript
js鼠标点击事件在各个浏览器中的写法及Event对象属性介绍
2013/01/24 Javascript
禁用页面部分JavaScript方法的具体实现
2013/07/31 Javascript
JQuery实现的购物车功能(可以减少或者添加商品并自动计算价格)
2015/01/13 Javascript
kindeditor修复会替换script内容的问题
2015/04/03 Javascript
innerHTML中标签可以换行的方法汇总
2015/08/14 Javascript
jquery实现在网页指定区域显示自定义右键菜单效果
2015/08/25 Javascript
12种JavaScript常用的MVC框架比较分析
2015/11/16 Javascript
基于jQuery实现的仿百度首页滑动选项卡效果代码
2015/11/16 Javascript
jQuery购物网页经典制作案例
2016/08/19 Javascript
JavaScript实现垂直向上无缝滚动特效代码
2016/11/23 Javascript
Vuex 使用 v-model 配合 state的方法
2018/11/13 Javascript
JS用最简单的方法实现四舍五入
2019/08/27 Javascript
vue 检测用户上传图片宽高的方法
2020/02/06 Javascript
一文秒懂JavaScript构造函数、实例、原型对象以及原型链
2020/08/25 Javascript
讲解python参数和作用域的使用
2013/11/01 Python
python中cPickle用法例子分享
2014/01/03 Python
Python实现对excel文件列表值进行统计的方法
2015/07/25 Python
Python构建网页爬虫原理分析
2017/12/19 Python
Python数据结构之图的应用示例
2018/05/11 Python
python使用response.read()接收json数据的实例
2018/12/19 Python
更新修改后的Python模块方法
2019/03/03 Python
详解爬虫被封的问题
2019/04/23 Python
python3-flask-3将信息写入日志的实操方法
2019/11/12 Python
戴森西班牙官网:Dyson西班牙
2020/02/04 全球购物
璀璨的珍珠、密钉和个性化珠宝:Lily & Roo
2021/01/21 全球购物
毕业生求职找工作的自我评价范文
2013/11/27 职场文书
酒店管理毕业生自我鉴定
2014/03/02 职场文书
三八红旗手先进事迹材料
2014/05/13 职场文书
暑期辅导班宣传单
2015/07/14 职场文书
毕业典礼致辞
2015/07/29 职场文书
小学校长开学致辞
2015/07/29 职场文书