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 相关文章推荐
基于promise.js实现nodejs的promises库
Jul 06 NodeJs
Nodejs为什么选择javascript为载体语言
Jan 13 NodeJs
nodejs实现HTTPS发起POST请求
Apr 23 NodeJs
nodejs爬虫抓取数据之编码问题
Jul 03 NodeJs
NodeJs下的测试框架Mocha的简单介绍
Feb 22 NodeJs
nodejs个人博客开发第四步 数据模型
Apr 12 NodeJs
nodeJS实现简单网页爬虫功能的实例(分享)
Jun 08 NodeJs
nodejs操作mongodb的增删改查功能实例
Nov 09 NodeJs
详解NODEJS的http实现
Jan 04 NodeJs
nodejs(officegen)+vue(axios)在客户端导出word文档的方法
Jul 31 NodeJs
nodejs实现获取本地文件夹下图片信息功能示例
Jun 22 NodeJs
nodejs一个简单的文件服务器的创建方法
Sep 13 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 和 MySQL 基础教程(二)
2006/10/09 PHP
解析php curl_setopt 函数的相关应用及介绍
2013/06/17 PHP
ThinkPHP调试模式与日志记录概述
2014/08/22 PHP
Yii2中Restful API原理实例分析
2016/07/25 PHP
PHP加密技术的简单实现
2016/09/04 PHP
Expandable &quot;Detail&quot; Table Rows
2007/08/29 Javascript
数组Array进行原型prototype扩展后带来的for in遍历问题
2010/02/07 Javascript
通过DOM脚本去设置样式信息
2010/09/19 Javascript
关于event.cancelBubble和event.stopPropagation()的区别介绍
2011/12/11 Javascript
JSON 数据格式介绍
2012/01/13 Javascript
js获取网页高度(详细整理)
2012/12/28 Javascript
探讨JavaScript中声明全局变量三种方式的异同
2013/12/03 Javascript
jquery实现点击文字可编辑并修改保存至数据库
2014/04/15 Javascript
jquery实现保存已选用户
2014/07/21 Javascript
JavaScript插件化开发教程(五)
2015/02/01 Javascript
JavaScript中字符串分割函数split用法实例
2015/04/07 Javascript
浅谈jQuery.easyui的datebox格式化时间
2015/06/25 Javascript
jQuery可见性过滤选择器用法示例
2016/09/09 Javascript
vue element-ui 绑定@keyup事件无效的解决方法
2018/03/09 Javascript
Vue-cli3多页面配置详解
2020/03/22 Javascript
python实现简单ftp客户端的方法
2015/06/28 Python
在matplotlib的图中设置中文标签的方法
2018/12/13 Python
python获取服务器响应cookie的实例
2018/12/28 Python
Python2和Python3之间的str处理方式导致乱码的讲解
2019/01/03 Python
python递归函数用法详解
2020/10/26 Python
卡骆驰德国官方网站:Crocs德国
2019/03/29 全球购物
写一个方法,输入一个文件名和一个字符串,统计这个字符串在这个文件中出现的次数
2016/04/13 面试题
党员教师一句话承诺
2014/05/30 职场文书
企业2014年度工作总结
2014/12/10 职场文书
2015年春训学习心得体会范文
2015/03/09 职场文书
教师节主题班会教案
2015/08/17 职场文书
关于应聘教师的自荐信
2016/01/28 职场文书
2019财务毕业实习报告
2019/06/27 职场文书
导游词之开封禹王台风景区
2019/12/02 职场文书
PHP实现考试倒计时功能代码
2021/04/16 PHP
如何使用Tkinter进行窗口的管理与设置
2021/06/30 Python