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/jquery对上传文件格式过滤的方法
Jul 25 Javascript
jQuery设置div一直在页面顶部显示的方法
Oct 24 Javascript
利用jquery写的左右轮播图特效
Feb 12 Javascript
Javascript浮点数乘积运算出现多位小数的解决方法
Feb 17 Javascript
解决jquery版本冲突的有效方法
Sep 02 Javascript
JS iFrame加载慢怎么解决
May 13 Javascript
省市联动效果的简单实现代码(推荐)
Jun 06 Javascript
js中的面向对象入门
Mar 06 Javascript
JavaScript字符串_动力节点Java学院整理
Jun 27 Javascript
bootstrap multiselect下拉列表功能
Aug 22 Javascript
Laravel整合Bootstrap 4的完整方案(推荐)
Jan 25 Javascript
微信小程序点击列表跳转到对应详情页过程解析
Sep 26 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
关于我转生变成史莱姆这档事:第二季PV上线,萌王2021年回归
2020/05/06 日漫
require(),include(),require_once()和include_once()的异同
2007/01/02 PHP
PHP读取txt文本文件并分页显示的方法
2015/03/11 PHP
PHP实现的常规正则验证helper公共类完整实例
2017/04/27 PHP
基于thinkphp6.0的success、error实现方法
2019/11/05 PHP
jQuery 动画弹出窗体支持多种展现方式
2010/04/29 Javascript
JS随机生成不重复数据的实例方法
2013/07/17 Javascript
Jquery实现图片放大镜效果的思路及代码(自写)
2013/10/18 Javascript
JS弹出层单纯的绝对定位居中示例代码
2014/02/18 Javascript
javascript实现切换td中的值
2014/12/05 Javascript
深入解读JavaScript中的Hoisting机制
2015/08/12 Javascript
jquery.mousewheel实现整屏翻屏效果
2015/08/30 Javascript
JavaScript动态检验密码强度的实现方法
2016/11/09 Javascript
ionic开发中点击input时键盘自动弹出
2016/12/23 Javascript
JS实现颜色梯度与渐变效果完整实例
2016/12/30 Javascript
AngularJS日程表案例详解
2017/08/15 Javascript
jQuery实现文件编码成base64并通过AJAX上传的方法
2018/04/12 jQuery
layer ui插件显示tips时,修改字体颜色的实现方法
2019/09/11 Javascript
vue 表单输入框不支持focus及blur事件的解决方案
2020/11/17 Vue.js
vue3自定义dialog、modal组件的方法
2021/01/04 Vue.js
[01:14]2019完美世界城市挑战赛(秋季赛)全国总决赛精彩花絮
2020/01/08 DOTA
[45:18]完美世界DOTA2联赛循环赛 PXG vs IO 第二场 11.06
2020/11/09 DOTA
谈谈如何手动释放Python的内存
2016/12/17 Python
python爬虫入门教程--利用requests构建知乎API(三)
2017/05/25 Python
Python列表list内建函数用法实例分析【insert、remove、index、pop等】
2017/07/24 Python
PyQt5 对图片进行缩放的实例
2019/06/18 Python
python对矩阵进行转置的2种处理方法
2019/07/17 Python
python实现大量图片重命名
2020/03/23 Python
关于Python3 lambda函数的深入浅出
2019/11/27 Python
python 输入字符串生成所有有效的IP地址(LeetCode 93号题)
2020/10/15 Python
临床医师专业个人自我评价
2014/01/08 职场文书
农村文化建设标语
2014/10/07 职场文书
员工自我工作评价
2015/03/06 职场文书
行政助理岗位职责范本
2015/04/11 职场文书
童年读书笔记
2015/06/26 职场文书
分享7个 Python 实战项目练习
2022/03/03 Python