技术笔记: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日

相关文章
|
3月前
|
数据采集 数据可视化 JavaScript
用 通义灵码和 PyQt5 爬虫智能体轻松爬取掘金,自动化采集技术文章和数据
本文介绍了如何利用智能开发工具通义灵码和Python的PyQt5框架,构建一个自动化爬取掘金网站技术文章和数据的智能爬虫系统。通过通义灵码提高代码编写效率,使用PyQt5创建可视化界面,实现对爬虫任务的动态控制与管理。同时,还讲解了应对反爬机制、动态内容加载及数据清洗等关键技术点,帮助开发者高效获取并处理网络信息。
|
4月前
|
数据采集 Java API
深度解析:爬虫技术获取淘宝商品详情并封装为API的全流程应用
本文探讨了如何利用爬虫技术获取淘宝商品详情并封装为API。首先介绍了爬虫的核心原理与工具,包括Python的Requests、BeautifulSoup和Scrapy等库。接着通过实战案例展示了如何分析淘宝商品页面结构、编写爬虫代码以及突破反爬虫策略。随后讲解了如何使用Flask框架将数据封装为API,并部署到服务器供外部访问。最后强调了在开发过程中需遵守法律与道德规范,确保数据使用的合法性和正当性。
|
18天前
|
数据采集 存储 XML
Python爬虫技术:从基础到实战的完整教程
最后强调: 父母法律法规限制下进行网络抓取活动; 不得侵犯他人版权隐私利益; 同时也要注意个人安全防止泄露敏感信息.
472 19
|
8天前
|
数据采集 机器学习/深度学习 人工智能
反爬虫机制深度解析:从基础防御到高级对抗的完整技术实战
本文系统阐述了反爬虫技术的演进与实践,涵盖基础IP限制、User-Agent检测,到验证码、行为分析及AI智能识别等多层防御体系,结合代码实例与架构图,全面解析爬虫攻防博弈,并展望智能化、合规化的发展趋势。
反爬虫机制深度解析:从基础防御到高级对抗的完整技术实战
|
8天前
|
数据采集 运维 监控
爬虫与自动化技术深度解析:从数据采集到智能运维的完整实战指南
本文系统解析爬虫与自动化核心技术,涵盖HTTP请求、数据解析、分布式架构及反爬策略,结合Scrapy、Selenium等框架实战,助力构建高效、稳定、合规的数据采集系统。
爬虫与自动化技术深度解析:从数据采集到智能运维的完整实战指南
|
5月前
|
数据采集 Web App开发 JavaScript
基于Selenium的Python爬虫抓取动态App图片
基于Selenium的Python爬虫抓取动态App图片
362 68
|
2月前
|
数据采集 机器学习/深度学习 数据可视化
Python量化交易:结合爬虫与TA-Lib技术指标分析
Python量化交易:结合爬虫与TA-Lib技术指标分析
|
3月前
|
数据采集 自然语言处理 分布式计算
大数据岗位技能需求挖掘:Python爬虫与NLP技术结合
大数据岗位技能需求挖掘:Python爬虫与NLP技术结合
|
4月前
|
数据采集 Web App开发 JavaScript
无头浏览器技术:Python爬虫如何精准模拟搜索点击
无头浏览器技术:Python爬虫如何精准模拟搜索点击
|
6月前
|
数据采集 XML 存储
Headers池技术在Python爬虫反反爬中的应用
Headers池技术在Python爬虫反反爬中的应用
下一篇
oss教程