Node爬取大批量文件的方法示例


Posted in Javascript onJune 28, 2019

有个朋友在搞留学工作室,经常访问的一个网站叫留学者指南,然而每次都要去访问该网站,显得极其不专业。于是托俺帮忙写脚本去爬他家的东西,我观察了下,这次,我们要爬的东西就有点多了——大概就20多万个文件吧~~~

在20多万个文件中,下载极有可能会被中断,因此需要做下载进度备份,下载进度恢复。

那么针对这样子的需求,我们开始吧!

上代码!

const cheerio = require("cheerio"); //用于处于HTML文档流,用法类似jQuery
const http = require("http"); //用于发起请求
const fs = require("fs"); //用于检测、写入文件等其他文件操作

// "http://www.compassedu.hk/sitemap1.txt",
// "http://www.compassedu.hk/sitemap2.txt", //重复的链接
var source = [ //Robots.txt显示的数据源
  "http://m.compassedu.hk/sitemap3.txt",
  "http://m.compassedu.hk/sitemap4.txt",
  "http://m.compassedu.hk/sitemap6.txt",
  "http://m.compassedu.hk/sitemap7.txt",
  "http://m.compassedu.hk/sitemap8.txt"
]
var s = 0; //控制源的序号
var arr = []; //合并的下载地址数组
var sou = []; //源下载地址数组
var i = 0; //当前下载地址数组序号

fs.exists(__dirname+"/compassedu", function(flag){ //下载路径检测
  if(!flag) fs.mkdirSync(__dirname+"/compassedu"); //创建下载存放目录
})
fs.exists(__dirname+"/logs", function(flag){ //日志路径检测
  if(!flag) fs.mkdirSync(__dirname+"/logs"); //创建日志存放目录
})

if(fs.existsSync(__dirname+"/logs/compassedu_backup")){ //是否存在断连恢复下载的控制文档
  let obj = JSON.parse(fs.readFileSync(__dirname+"/logs/compassedu_backup")); //存在则读取上次下载的位置
  i = obj.index;
  init(); //开始初始化程序
}
else{
  init(); //开始初始化程序
}

function init(){ //初始化
  http.get(source[s], function(res){ //获取源下载地址文件

    //将源文件的内容存储到数组
    let rawData = "";
    res.setEncoding("utf8");
    res.on("data", function(chunk){ //监听数据流
      rawData += chunk;
    });
    res.on("end", function(){ //监听结束
      sou[s] = rawData.split("\n");
      console.log("源", s+1, ": ", sou[s].length, "条数据");
      s++;
      if(s<source.length){ //源文件还未读取完
        init();
      }
      else{ //源文件读取完毕
        for(let m=0;m<sou.length;m++){ //将所有的地址数组合并
          arr = arr.concat(sou[m]);
        }
        arr = [...new Set(arr)]; //去重
        console.log("总计: ", arr.length, "条数据", "\n爬虫配置完毕!!\n开始爬取 >>");
        start(); //开始爬取程序
      }
    });
  })
}

function start(){ //开始
  let url = arr[i];
  console.log(url); //打印当前爬取的URL
  
  http.get(url,function(res){ //发起请求
    let obj = { //将当前的信息存储到对象中
     "time": new Date().toLocaleTimeString(),
      "index": i,
      "url": url,
      "status": res.statusCode
    };
    fs.appendFileSync("./logs/download.log", JSON.stringify(obj), "utf8"); //写入日志文件
    fs.writeFileSync("./logs/compassedu_backup", JSON.stringify({"index": i}), "utf8"); //将当前的下载URL序号写入断连恢复文件
    //读取请求到的数据流
    let rawData = "";
    res.setEncoding("utf8");
    res.on("data", function(chunk){ //监听数据流事件
      rawData += chunk;
    });
    res.on("end", function(){ //监听结束事件
      $ = cheerio.load(rawData); //启用类jQuery插件
      title = $(".container-public h1").text().replace(/\s/,"").trim(); //读取数据流部分的标题
      body = $(".container-public").html(); //读取数据流部分的内容
      body = body.split("visible-xs")[0]; //剥离多于的数据或其他处理,准备写入文件
      i++; //序号+1
      fs.writeFile(__dirname+"/compassedu/"+title+".html", body, "utf8", function(err){ //将处理好的数据写入文件
        if(!err) console.log(title, "写入成功");
        else{
          console.log(err);
        }
      });
      if(i>=arr.length) { //若序号达到数组的最后,结束程序
        console.log("爬取结束");
        fs.unlinkSync("./logs/compassedu_backup");//爬取结束,销毁断连恢复文件
        return;
      }
      else { //否则递归运行
        start();
      }
    });
    res.on("error", function(err){ //监听其他错误
      console.log(err);
    });
  })
}

至此,就结束了,是否有bug还不清楚,数据还没爬完呢~

有bug的话,我后续补充修复~

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
Javascript读取cookie函数代码
Oct 16 Javascript
深入理解JavaScript系列(12) 变量对象(Variable Object)
Jan 16 Javascript
Jquery网页内滑动缓冲导航的实现代码
Apr 05 Javascript
Javascript页面跳转常见实现方式汇总
Nov 28 Javascript
JavaScript数组合并的多种方法
May 22 Javascript
jQuery获取select选中的option的value值实现方法
Aug 29 Javascript
AngularJS Controller作用域
Jan 09 Javascript
AngularJS 验证码60秒倒计时功能的实现
Jun 05 Javascript
全新打包工具parcel零配置vue开发脚手架
Jan 11 Javascript
微信小程序rich-text富文本用法实例分析
May 20 Javascript
原生JS运动实现轮播图
Jan 02 Javascript
关于JavaScript 中 if包含逗号表达式
Nov 27 Javascript
JavaScript实现单英文金山打字通
Jul 24 #Javascript
javascript实现导航栏分页效果
Jun 27 #Javascript
编写更好的JavaScript条件式和匹配条件的技巧(小结)
Jun 27 #Javascript
原生js实现抽奖小游戏
Jun 27 #Javascript
JavaScript实现图片放大镜效果
Jun 27 #Javascript
详解Jest结合Vue-test-utils使用的初步实践
Jun 27 #Javascript
微信小程序自定义组件实现环形进度条
Nov 17 #Javascript
You might like
用PHP实现文件上传二法
2006/10/09 PHP
在数据量大(超过10万)的情况下
2007/01/15 PHP
PHP连接MySQL的2种方法小结以及防止乱码
2014/03/11 PHP
利用php下载xls文件(自己动手写的)
2014/04/18 PHP
php gd等比例缩放压缩图片函数
2016/06/12 PHP
php中替换字符串函数strtr()和str_repalce()的用法与区别
2016/11/25 PHP
使用 PHP Masked Package 屏蔽敏感数据的实现方法
2019/10/15 PHP
Thinkphp框架+Layui实现图片/文件上传功能分析
2020/02/07 PHP
thinkphp5.1框架模板赋值与变量输出示例
2020/05/25 PHP
CL vs ForZe BO5 第四场 2.13
2021/03/10 DOTA
JS自动缩小超出大小的图片
2012/10/12 Javascript
Extjs实现进度条的两种便捷方式
2013/09/26 Javascript
深入探讨JavaScript、JQuery屏蔽网页鼠标右键菜单及禁止选择复制
2014/06/10 Javascript
jQuery实现垂直半透明手风琴特效代码分享
2015/08/21 Javascript
jQuery实现返回顶部功能
2016/02/23 Javascript
关于在vue-cli中使用微信自动登录和分享的实例
2017/06/22 Javascript
vue登录注册及token验证实现代码
2017/12/14 Javascript
javascript Canvas动态粒子连线
2020/01/01 Javascript
VUE中V-IF条件判断改变元素的样式操作
2020/08/09 Javascript
js实现简单的点名器随机色实例代码
2020/09/20 Javascript
[01:09]DOTA2次级职业联赛 - 99战队宣传片
2014/12/01 DOTA
[47:48]DOTA2上海特级锦标赛D组小组赛#2 Liquid VS VP第三局
2016/02/28 DOTA
python 时间戳与格式化时间的转化实现代码
2016/03/23 Python
python django 访问静态文件出现404或500错误
2017/01/20 Python
Python使用functools实现注解同步方法
2018/02/06 Python
python3.6+django2.0+mysql搭建网站过程详解
2019/07/24 Python
Matplotlib使用Cursor实现UI定位的示例代码
2020/03/12 Python
拿来就用!Python批量合并PDF的示例代码
2020/08/10 Python
教师党的群众路线教育实践活动剖析材料
2014/10/09 职场文书
任命书怎么写
2015/03/02 职场文书
2015年销售部工作总结范文
2015/04/27 职场文书
护士工作心得体会
2016/01/25 职场文书
一文带你理解vue创建一个后台管理系统流程(Vue+Element)
2021/05/18 Vue.js
【海涛教你打DOTA】虚空假面第一视角骨弓3房29杀
2022/04/01 DOTA
mysql 8.0.27 绿色解压版安装教程及配置方法
2022/04/20 MySQL
Java设计模式中的命令模式
2022/04/28 Java/Android