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 特殊字符串
Feb 25 Javascript
前端开发部分总结[兼容性、DOM操作、跨域等](持续更新)
Mar 04 Javascript
JQuery上传插件Uploadify使用详解及错误处理
Apr 27 Javascript
javascript中的注释使用与注意事项小结
Sep 20 Javascript
更换select下拉菜单背景样式的实现代码
Dec 20 Javascript
jquery 实现input输入什么div图层显示什么
Jun 15 Javascript
jquery实现点击查看更多内容控制段落文字展开折叠效果
Aug 06 Javascript
js实现点击向下展开的下拉菜单效果代码
Sep 01 Javascript
js带点自动图片轮播幻灯片特效代码分享
Sep 07 Javascript
基于JS2Image实现圣诞树代码
Dec 24 Javascript
微信小程序(六):列表上拉加载下拉刷新示例
Jan 13 Javascript
利用Vconsole和Fillder进行移动端抓包调试方法
Mar 05 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乱码问题,UTF-8乱码常见问题小结
2012/04/09 PHP
php使用PDO操作MySQL数据库实例
2014/12/30 PHP
php实现可逆加密的方法
2015/08/11 PHP
PHP重定向与伪静态区别
2017/02/19 PHP
php中html_entity_decode实现HTML实体转义
2018/06/13 PHP
用jquery实现等比例缩放图片效果插件
2010/07/24 Javascript
jquery中ajax使用error调试错误的方法
2015/02/08 Javascript
React.js入门学习第一篇
2016/03/30 Javascript
深入理解$.each和$(selector).each
2016/05/15 Javascript
jQuery日期范围选择器附源码下载
2017/05/23 jQuery
Vue二次封装axios为插件使用详解
2018/05/21 Javascript
在vue中给列表中的奇数行添加class的实现方法
2018/09/05 Javascript
在vue项目中,将juery设置为全局变量的方法
2018/09/25 Javascript
jQuery动态操作表单示例【基于table表格】
2018/12/06 jQuery
Layui事件监听的实现(表单和数据表格)
2019/10/17 Javascript
vue2.0 解决抽取公用js的问题
2020/07/31 Javascript
[00:33]2018DOTA2亚洲邀请赛TNC出场
2018/04/04 DOTA
利用Python爬取微博数据生成词云图片实例代码
2017/08/31 Python
python实现搜索文本文件内容脚本
2018/06/22 Python
Django框架反向解析操作详解
2019/11/28 Python
python几种常用功能实现代码实例
2019/12/25 Python
Nginx+Uwsgi+Django 项目部署到服务器的思路详解
2020/05/08 Python
python 删除excel表格重复行,数据预处理操作
2020/07/06 Python
python如何编写类似nmap的扫描工具
2020/11/06 Python
html5声频audio和视频video等新特性详细说明
2012/12/26 HTML / CSS
英国在线药房:Chemist.co.uk
2019/03/26 全球购物
阿迪达斯英国官方网站:adidas英国
2019/08/13 全球购物
怎么样写好简历中的自我评价
2013/10/25 职场文书
绝对经典成功的大学生推荐信
2013/11/08 职场文书
同学聚会老师邀请函
2014/01/28 职场文书
党员公开承诺践诺书
2014/03/25 职场文书
项目申请汇报材料
2014/08/16 职场文书
工地例会施工汇报材料
2014/08/22 职场文书
答谢词范文
2015/01/05 职场文书
国庆放假通知怎么写
2015/07/30 职场文书
小学数学教师研修感悟
2015/11/18 职场文书