背景

前言

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

  早就听过爬虫,这几天开始学习nodejs,写了个爬虫,爬取
博客园首页的文章标题、用户名、阅读数、推荐数和用户头像,现做个小总结。

依赖

  使用到这几个点:

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

  1、node的核心模块– 文件系统

日志配置

  2、用于http请求的第三方模块 —
superagent

话不多说,直接上代码:

  3、用于解析DOM的第三方模块 —
cheerio

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;

  几个模块详细的讲解及API请到各个链接查阅,demo中只有简单的用法。

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

准备工作

爬取内容并处理

  使用npm管理依赖,依赖信息会存放在package.json中

 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));
   });
  });
 });
//安装用到的第三方模块
cnpm install --save superagent cheerio

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

  引入所需要用到的功能模块

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

//引入第三方模块,superagent用于http请求,cheerio用于解析DOM
const request = require('superagent');
const cheerio = require('cheerio');
const fs = require('fs');

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

请求 + 解析页面

读写本地文件

  想要爬到博客园首页的内容,首先要请求首页地址,拿到返回的html,这里使用superagent进行http请求,基本的使用方法如下:

创建文件夹

request.get(url)
      .end(error,res){
      //do something     
}    
function mkdirSync(dirname) {
 if (fs.existsSync(dirname)) {
  return true;
 }
 if (mkdirSync(path.dirname(dirname))) {
  fs.mkdirSync(dirname);
  return true;
 }

 return false;
}

  向指定的url发起get请求,请求错误时,会有error返回(没有错误时,error为null或undefined),res为返回的数据。

读写文件

  拿到html内容后,要拿到我们想要的数据,这个时候就需要用cheerio解析DOM了,cheerio要先load目标html,然后再进行解析,API和jquery的API非常类似,熟悉jquery上手非常快。直接看代码实例

   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));
//目标链接 博客园首页
let targetUrl = 'https://www.cnblogs.com/';
//用来暂时保存解析到的内容和图片地址数据
let content = '';
let imgs = [];
//发起请求
request.get(targetUrl)
    .end( (error,res) => {
      if(error){ //请求出错,打印错误,返回
        console.log(error)
        return;
      }
      // cheerio需要先load html
      let $ = cheerio.load(res.text);
      //抓取需要的数据,each为cheerio提供的方法用来遍历
      $('#post_list .post_item').each( (index,element) => {
        //分析所需要的数据的DOM结构
        //通过选择器定位到目标元素,再获取到数据
        let temp = {
          '标题' : $(element).find('h3 a').text(),
          '作者' : $(element).find('.post_item_foot > a').text(),
          '阅读数' : +$(element).find('.article_view a').text().slice(3,-2),
          '推荐数' : +$(element).find('.diggnum').text()
        }
        //拼接数据
        content += JSON.stringify(temp) + '\n';
        //同样的方式获取图片地址
        if($(element).find('img.pfs').length > 0){
          imgs.push($(element).find('img.pfs').attr('src'));
        }
      });
      //存放数据
      mkdir('./content',saveContent);
      mkdir('./imgs',downloadImg);
    })

批量下载资源

存储数据

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

  上面解析DOM之后,已经拼接了所需要的信息内容,也拿到了图片的URL,现在就进行存储,把内容存放到指定目录的txt文件中,而且下载图片到指定目录

使用Bagpipe处理异步并发 参考

  先创建目录,使用nodejs核心的文件系统

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}`);
  });
//创建目录
function mkdir(_path,callback){
  if(fs.existsSync(_path)){
    console.log(`${_path}目录已存在`)
  }else{
    fs.mkdir(_path,(error)=>{
      if(error){
        return console.log(`创建${_path}目录失败`);
      }
      console.log(`创建${_path}目录成功`)
    })
  }
  callback(); //没有生成指定目录不会执行
}

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

  有了指定目录之后,可以写入数据了,txt文件的内容已经有了,直接写入就可以了使用writeFile()

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);
   });
  }
 });
}
//将文字内容存入txt文件中
function saveContent() {
  fs.writeFile('./content/content.txt',content.toString());
}

编码

  取到了图片的链接,所以需要再使用superagent下载图片,存在本地。superagent可以直接返回一个响应流,再配合nodejs的管道,直接把图片内容写到本地

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

//下载爬到的图片
function downloadImg() {
  imgs.forEach((imgUrl,index) => {
    //获取图片名 
    let imgName = imgUrl.split('/').pop();

    //下载图片存放到指定目录
    let stream = fs.createWriteStream(`./imgs/${imgName}`);
    let req = request.get('https:' + imgUrl); //响应流
    req.pipe(stream);
    console.log(`开始下载图片 https:${imgUrl} --> ./imgs/${imgName}`);     
  } )
}
const $ = cheerio.load(buf, { decodeEntities: false });

效果  

来禁止编码,

  执行下demo,看下效果,数据已经正常爬下来了

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

永利开户送38元体验金 1

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

   非常简单的一个demo,可能也没有那么严谨,不过总是走出了node的第一小步。

const reg = /<.*?>/g;

总结

您可能感兴趣的文章:

  • nodejs爬虫初试superagent和cheerio
  • NodeJS爬虫实例之糗事百科
  • nodeJS实现简单网页爬虫功能的实例(分享)
  • 基于nodejs
    的多页面爬虫实例代码
  • nodejs制作爬虫实现批量下载图片
  • nodejs爬虫遇到的乱码问题汇总
  • 永利开户送38元体验金,详解nodejs爬虫程序解决gbk等中文编码问题
  • 简单好用的nodejs
    爬虫框架分享
  • nodeJs爬虫获取数据简单实现代码
  • Nodejs爬虫进阶教程之异步并发控制
  • nodejs爬虫抓取数据之编码问题
  • nodejs爬虫抓取数据乱码问题总结
  • NodeJS制作爬虫全过程(续)
  • NodeJS制作爬虫全过程

以上所述是小编给大家介绍的nodejs爬虫初试superagent和cheerio,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对脚本之家网站的支持!

您可能感兴趣的文章:

  • NodeJS爬虫实例之糗事百科
  • nodeJS实现简单网页爬虫功能的实例(分享)
  • 基于nodejs
    的多页面爬虫实例代码
  • nodejs制作爬虫实现批量下载图片
  • nodejs爬虫遇到的乱码问题汇总
  • 详解nodejs爬虫程序解决gbk等中文编码问题
  • 简单好用的nodejs
    爬虫框架分享
  • nodeJs爬虫获取数据简单实现代码
  • Nodejs爬虫进阶教程之异步并发控制
  • nodejs爬虫抓取数据之编码问题
  • nodejs爬虫抓取数据乱码问题总结
  • NodeJS制作爬虫全过程(续)
  • NodeJS制作爬虫全过程
  • nodeJs爬虫的技术点总结

相关文章