技术笔记:Node.jsmm131图片批量下载爬虫1.01增加断点续传功能

简介: 技术笔记:Node.jsmm131图片批量下载爬虫1.01增加断点续传功能

这里的断点续传不是文件下载时的断点续传,而是指在爬行页面时有时会遇到各种网络中断而从中断前的页面及其数据继续爬行的过程,这个过程和断点续传原理上相似故以此命名。我的具体做法是:在下载出现故障或是图片已经全部获得时,将存储目录,当前爬行页面和已经获取的图片地址以json形式存储到数据文件中,而用户选择断点续传模式时提取数据文件中的这三条信息,继而从上次中断之处重新运行。


数据文件示例:


{"url":"","pictures":【"","","",""】,"folder":"pictures(2017-11-18 15_531)"}


Node.js 代码如下:


//======================================================


// mm131图片批量下载爬虫1.01


// 1.00 具备功能


// 1.01 增加断点续传


// 2017年11月15日


//======================================================


// 内置http模块


var http=require("http");


// 内置文件处理模块,用于创建目录和图片文件


var fs=require('fs');


// 用于转码。非Utf8的网页如gb2132会有乱码问题,需要iconv将其转码


var iconv = require('iconv-lite');


// cheerio模块,提供了类似jQuery的功能,用于从HTML code中查找图片地址和下一页


var cheerio = require("cheerio");


// 请求参数JSON。http和https都有使用


var options;


// request请求


var req;


// 图片数组,找到的图片地址会放到这里


var pictures=【】;


// 存放图片的目录


var folder="";


//--------------------------------------


// 爬取网页,找图片地址,再爬


// pageUrl sample:


// pageUrl sample:


// pageUrl sample:


//--------------------------------------


function crawl(pageUrl){


console.log("Current page="+pageUrl);


// 得到hostname和path


var currUrl=pageUrl.replace("","");


var pos=currUrl.indexOf("/");


var hostname=currUrl.slice(0,pos);


var path=currUrl.slice(pos);


//console.log("hostname="+hostname);


//console.log("path="+path);


// 初始化options


options={


hostname:hostname,


port:80,


path:path,// 子路径


method:'GET',


};


req=http.request(options,function(resp){


var html = 【】;


resp.on("data", function(data) {


html.push(data);


})


resp.on("end", function() {


var buffer = Buffer.concat(html);


var body = iconv.decode(buffer,'gb2312'); // 特地增加的,为了让汉字不乱码


//console.log(body);


var $ = cheerio.load(body);


var picCount=0;


// 找图片放入数组


$(".content-pic a img").each(function(index,element){


var picUrl=$(element).attr("src");


//console.log(picUrl);


if(picUrl.indexOf('.jpg')!=-1){


pictures.push(picUrl);


picCount++;


}


})


console.log("找到图片"+picCount+"张.");


var nextPageUrl=null;


// 找下一页


$(".content-page a").each(function(index,element){


var text=$(element).text();


if(text.indexOf('下一页')!=-1){


nextPageUrl=$(element).attr("href");


nextPageUrl=""+nextPageUrl;// 把省略部分加上


console.log("找到下一页.");


}


})


if(nextPageUrl==null){


console.log(pageUrl+"已经是最后一页了.\n");


saveFile(pageUrl,pictures);// 保存


download(pictures);


}else{


//console.log("下一页是"+nextPageUrl);


crawl(nextPageUrl);


}


}).on("error", function() {


saveFile(pageUrl,pictures);// 保存


console.log("crawl函数失败,请进入断点续传模式继续进行");


})


});


// 超时处理


req.setTimeout(7500,function(){


req.abort();


});


// 出错处理


req.on('error',function(err){


console.log('请求发生错误'+err);


saveFile(pageUrl,pictures);// 保存


console.log("crawl函数失败,请进入断点续传模式继续进行");


});


// 请求结束


req.end();


}


//--------------------------------------


// 下载图片


//--------------------------------------


function download(pictures){


var total=0;


total=pictures.length;


console.log("总计有"+total+"张图片将被下载.");


appendToLogfile(folder,"总计有"+total+"张图片将被下载.\n");


for(var i=0;i



var picUrl=pictures【i】;


downloadPic(picUrl,folder);


}


}


//--------------------------------------


// 写log文件


//--------------------------------------


function appendToLogfile(folder,text){


fs.appendFile('./'+folder+'/log.txt', text, function (err) {


if(err){


console.log("不能书写log文件");


console.log(err);


}


});


}


//--------------------------------------


// 取得当前时间


//--------------------------------------


function getNowFormatDate() {


var date = new Date();


var seperator1 = "-";


var seperator2 = "";


var month = date.getMonth() + 1;


var strDate = date.getDate();


if (month >= 1 && month <= 9) {


month = "0" + month;


}


if (strDate >= 0 && strDate <= 9) {


strDate = "0" + strDate;


}


var currentdate =date.getFullYear() + seperator1 + month + seperator1 + strDate


+ " " + date.getHours() + seperator2 + date.getMinutes()


+ seperator2 + date.getSeconds();


return currentdate;


}


//--------------------------------------


// 下载单张图片


// picUrl sample:


//--------------------------------------


function downloadPic(picUrl,folder){


console.log("图片:"+picUrl+"下载开始");


// 得到hostname,path和port


var currUrl=picUrl.replace("","");


var pos=currUrl.indexOf("/");


var hostname=currUrl.slice(0,pos);


var path=currUrl.slice(pos);


// 有端口加端口,没有端口默认80


var port=80;


if(hostname.indexOf(":")!=-1){


var arr=hostname.split(":");


hostname=arr【0】;


port=arr【1】;


}


//console.log("hostname="+hostname);


//console.log("path="+path);


//代码效果参考: http://www.jhylw.com.cn/324937419.html

//console.log("port="+port);


var picName=currUrl.slice(currUrl.lastIndexOf("/"));


// 初始化options


options={


hostname:hostname,


port:port,


path:path,// 子路径


method:'GET',


headers:{


'Referer':'',


}


};


req=http.request(options,function(resp){


var imgData = "";


resp.setEncoding("binary");


resp.on('data',function(chunk){


imgData+=chunk;


});


resp.on('end',function(){


// 创建文件


var fileName="./"+folder+picName;


fs.writeFile(fileName, imgData, "binary", function(err){


if(err){


console.log("【downloadPic】文件 "+fileName+" 下载失败.");


//代码效果参考:http://www.jhylw.com.cn/233941497.html

console.log(err);

appendToLogfile(folder,"文件 "+picUrl+" 下载失败.\n");


}else{


appendToLogfile(folder,"文件 "+picUrl+" 下载成功.\n");


console.log("文件"+fileName+"下载成功");


}


});


});


});


// 超时处理


req.setTimeout(7500,function(){


req.abort();


});


// 出错处理


req.on('error',function(err){


if(err){


console.log('【downloadPic】文件 '+picUrl+" 下载失败,"+'因为'+err);


appendToLogfile(folder,"文件"+picUrl+"下载失败.\n");


}


});


// 请求结束


req.end();


}


//--------------------------------------


// 程序入口


//--------------------------------------


function getInput(){


process.stdin.resume();


process.stdout.write("\033【33m 新建模式输入第一页URL,断点续传模式输入0,请输入: \033【39m");// 草黄色


process.stdin.setEncoding('utf8');


process.stdin.on('data',function(text){


var input=text.trim();


process.stdin.end();// 退出输入状态


if(text.trim()=='0'){


process.stdout.write("\033【36m 进入断点续传模式. \033【39m"); // 蓝绿色


// Read File


fs.readFile('./save.dat','utf8',function(err,data){


if(err){


console.log('读取文件save.dat失败,因为'+err);


}else{


//console.log(data);


var obj=JSON.parse(data);


pictures=obj.pictures;


console.log('提取图片'+pictures.length+'张');


folder=obj.folder;


// 创建目录


fs.mkdir('./'+folder,function(err){


if(err){


console.log("目录"+folder+"已经存在");


}


});


crawl(obj.url);


}


});


// Resume crawl


}else{


process.stdout.write("\033【35m 进入新建模式. \033【039m"); //紫色


folder='pictures('+getNowFormatDate()+")";


// 创建目录


fs.mkdir('./'+folder,function(err){


if(err){


console.log("目录"+folder+"已经存在");


}


});


crawl(input);


}


});


}


//--------------------------------------


// 将爬行中信息存入数据文件


//--------------------------------------


function saveFile(url,pictures){


var obj=new Object;


obj.url=url;


obj.pictures=pictures;


obj.folder=folder;


var text=JSON.stringify(obj);


fs.writeFile('./save.dat',text,function(err){


if(err){


console.log('写入文件save.dat失败,因为'+err);


}


});


}


// 调用getInput函数,程序开始


getInput();


2017年11月16日

相关文章
|
5天前
|
数据采集 存储 JSON
解密网络爬虫与数据抓取技术的奇妙世界
【7月更文挑战第2天】网络爬虫是自动化数据抓取的关键工具,用于解锁互联网数据的潜力。本文深入探讨了爬虫基础,包括模拟HTTP请求、HTML解析和数据存储。通过实例展示如何用Python构建简单爬虫,强调法律与伦理考虑,如遵循robots.txt、尊重版权和隐私,以及应对反爬策略。合法、负责任的爬虫技术在商业、科研等领域发挥着重要作用,要求我们在数据探索中保持透明、最小影响和隐私保护。
8 1
|
5天前
|
数据采集 Python
揭秘淘宝商品信息:Python爬虫技术入门与实战指南
Python爬虫用于获取淘宝商品详情,依赖`requests`和`beautifulsoup4`库。安装这两个库后,定义函数`get_taobao_product_details`,发送GET请求模拟浏览器,解析HTML获取标题和价格。注意选择器需随页面结构更新,遵守爬虫政策,控制请求频率,处理异常,且数据只能用于合法目的。
|
9天前
|
数据采集 XML 存储
技术经验分享:C#构造蜘蛛爬虫程序
技术经验分享:C#构造蜘蛛爬虫程序
|
10天前
|
数据采集 Web App开发 XML
详尽分享用Node.js写爬虫,撸羞羞的图片
详尽分享用Node.js写爬虫,撸羞羞的图片
13 0
|
1月前
|
前端开发
windows10 安装node npm 等前端环境 并配置国内源
windows10 安装node npm 等前端环境 并配置国内源
47 3
|
2月前
|
移动开发 JavaScript 前端开发
为了学习vue3,安装nvm进行node的多版本管理
为了学习vue3,安装nvm进行node的多版本管理
89 2
|
2月前
|
资源调度 jenkins 持续交付
jenkins 自动安装nodejs16.16.0版本报错处理
jenkins 自动安装nodejs16.16.0版本报错处理
108 0
|
1天前
|
JavaScript IDE 开发工具
vue3【2024版】开发环境搭建(含官网和nvm下载切换最新版node,修改node下载源,创建项目,启动项目,安装vscode插件Vue - Official)
vue3【2024版】开发环境搭建(含官网和nvm下载切换最新版node,修改node下载源,创建项目,启动项目,安装vscode插件Vue - Official)
12 3
|
9天前
|
Dart JavaScript 前端开发
npm install node-sass 安装失败的解决方案:利用国内镜像加速安装
npm install node-sass 安装失败的解决方案:利用国内镜像加速安装
35 1
|
11天前
|
JavaScript Linux
Linux安装nodejs
Linux安装nodejs
17 2