详尽分享用Node.js写爬虫,撸羞羞的图片

简介: 详尽分享用Node.js写爬虫,撸羞羞的图片

  说到爬虫,很多人都认为是很高大上的东西。哇塞,是不是可以爬妹纸图啊,是不是可以爬小片片啊。答案就是对的。爬虫可以完成这些东西的操作。但是,作为一个正直的程序员,我们要在法律允许范围内用爬虫来为我们服务,而不是为所欲为。(ps:此处应有掌声,谢谢。)

  今天,我带来一个用Node.js写的爬虫。一说到教程呢,可能大多数人认为比较枯燥无味。那这样好了,我教大家爬妹纸图,上干货:

  是不是瞬间有了动力了?

  说到爬虫呢,其实从客观上来说,“所有网站皆可爬”。互联网的内容都是人写出来的,而且都是偷懒写出来的(不会第一页是a,下一页是8),所以肯定有规律,这就给人有了爬取的可能,可以说,天下没有不能爬的网站。而且即使网站不同,但是原理都类似,大部分爬虫都是从 发送请求——>获得页面——>解析页面——>下载内容——>储存内容 这样的流程来进行,只是用的工具不同,可能你用python,我用Node,他用PHP,但是思路也是与上面相同。

  既然是用node完成爬虫,那么我们就要用到node环境,如果不会配的话,请参考我的第一篇博客。

  好的,我们从爬虫流程开始分析我们需要的一些模块。

  首先,我们需要发送请求获得页面,在这里呢,我们用到了request-promise模块。

const rp = require("request-promise"), //进入request-promise模块

async getPage(URL) {

const data = {

url,

res: await rp({

url: URL

})

};

return data //这样,我们返回了一个对象,就是这个页面的url和页面内容。

}

  其次,解析页面,我们使用一个叫做Cheerio的模块将上面返回的对象中的res解析成类似JQ的调用模式。Cheerio使用一个非常简单,一致的DOM模型。因此解析,操作和渲染非常高效。初步的端到端基准测试表明cheerio 比JSDOM快大约8倍。

const cheerio = require("cheerio");//引入Cheerio模块

const $ = cheerio.load(data.res); //将html转换为可操作的节点

  此时,我们要对我们即将进行爬取的页面进行分析。“这是我们进行爬取的网址,F12查看DOM结构:

  根据这个结构我们可以使用$(".main-image").find("img")【0】.attribs.src来爬取这张图片的地址(如果不知道为什么是attribs.src的话可以一步一步console.log()一下看看)。

  最后,到了最关键的时候,我们使用fs模块进行创建文件夹以及下载文件。这里用到了fs模块的几个指令:

    1.fs.mkdirSync(downloadPath):查看是否存在这个文件夹。

    2.fs.mkdirSync(downloadPath):创建文件夹。

    3.fs.createWriteStream(${downloadPath}/${index}.jpg):写入文件,这里需要注意的是fs.createWriteStream 似乎不会自己创建不存在的文件夹,所以在使用之前需要注意,保存文件的文件夹一定要提前创建。

  好的,大体的方法就是以上的几个模块和步骤。

  在这里,我针对这个网站的一些情况进行一下分析:

    1.这个网站一个页面只有一张图片,但是每个页面的网址都是有根据的。“当你输入“时也会跳转此页面),“等等。那么我们可以根据这个规律去爬取,并且我们需要在页面的下方的页码栏中获得这一组图图片的页码:

    2.我们一般不会只爬取一组图片,但是这个网站的图片的标题也就是最后的六位数基本没有规律可言,那么我们只能从最开始的首页入手。具体方法不多做描述,与获取图片的URL方式相同。

    3.同理,我们爬取完一页的目录之后会进行对第二个目录的爬取,“其原理和第一条相同。

    4.但是,有的网站存在防盗链的情况,面对这种措施,我们需要伪造一个请求头来避开这个情况。这个可以从F12的Network中查到,看到这里的朋友我想也会明白。

let headers = {

Accept: "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,/;q=0.8",

"Accept-Encoding": "gzip, deflate",

"Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8",

"Cache-Control": "no-cache",

Host: "i.meizitu.net",

Pragma: "no-cache",

"Proxy-Connection": "keep-alive",

Referer: data.url,//根据爬取的网址跟换

"Upgrade-Insecure-Requests": 1,

"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.19 Safari/537.36"

};

  以上就是我的全部思路。

  代码:

    业务代码:

const rp = require("request-promise"), //进入request-promise模块

fs = require("fs"), //进入fs模块

cheerio = require("cheerio"), //进入cheerio模块

depositPath = "D:/blog/reptile/meizi/"; //存放照片的地址

let downloadPath; //下载图片的文件夹地址

module.exports = {

async getPage(url) {

const data = {

url,

res: await rp({

url: url

})

};

return data;

},

getUrl(data) {

let list = 【】;

const $ = cheerio.load(data.res); //将html转换为可操作的节点

$("#pins li a")

.children()

.each(async (i, e) => {

let obj = {

name: e.attribs.alt, //图片网页的名字,后面作为文件夹名字

url: e.parent.attribs.href //图片网页的url

};

list.push(obj); //输出目录页查询出来的所有链接地址

});

return list;

},

getTitle(obj) {

downloadPath = depositPath + obj.name;

if (!fs.existsSync(downloadPath)) {//查看是否存在这个文件夹

fs.mkdirSync(downloadPath);//不存在就建文件夹

console.log(${obj.name}文件夹创建成功);

return true;

} else {

console.log(${obj.name}文件夹已经存在);

return false;

}

},

getImagesNum(res, name) {

if (res) {

let $ = cheerio.load(res);

let len = $(".pagenavi")

.find("a")

.find("span").length;

if (len == 0) {

fs.rmdirSync(${depositPath}${name});//删除无法下载的文件夹

return 0;

}

let pageIndex = $(".pagenavi")

.find("a")

.find("span")【len - 2】.children【0】.data;

return pageIndex;//返回图片总数

}

},

//下载相册照片

async downloadImage(data, index) {

if (data.res) {

var $ = cheerio.load(data.res);

if ($(".main-image").find("img")【0】) {

let imgSrc = $(".main-image").find("img")【0】.attribs.src;//图片地址

let headers = {

Accept: "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,/;q=0.8",

"Accept-Encoding": "gzip, deflate",

"Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8",

"Cache-Control": "no-cache",

Host: "i.meizitu.net",

Pragma: "no-cache",

"Proxy-Connection": "keep-alive",

Referer: data.url,

"Upgrade-Insecure-Requests": 1,

"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.19 Safari/537.36"

};//反防盗链

await rp({

url: imgSrc,

resolveWithFullResponse: true,

headers

}).pipe(fs.createWriteStream(${downloadPath}/${index}.jpg));//下载

console.log(${downloadPath}/${index}.jpg下载成功);

}//代码效果参考:http://www.zidongmutanji.com/bxxx/115062.html

else {

console.log(${downloadPath}/${index}.jpg加载失败);

}

}

}

};

    主体逻辑代码:

const model = require("./model"),

basicPath = "";

let start = 1,

end = 10;

const main = async url => {

let list = 【】,

index = 0;

const data = await model.getPage(url);

list = model.getUrl(data);

downLoadImages(list, index);//下载

};

const downLoadImages = async (list, index) => {

if (index == list.length) {

start++;

if (start [span style="color: rgba(0, 0, 0, 1)"> end) {

main(basicPath + start);//进行下一页图片组的爬取。

}

return false;

}

if (model.getTitle(list【index】)) {

let item = await model.getPage(list【index】.url),//获取图片所在网页的url

imageNum = model.getImagesNum(item.res,list【index】.name);//获取这组图片的数量

for (var i = 1; i <= imageNum; i++) {

let page = await model.getPage(list【index】.url + /${i});//遍历获取这组图片每一张所在的网页

await model.downloadImage(page, i);//下载

}

index++;

downLoadImages(list, index);//循环完成下载下一组

} else {

index++;

downLoadImages(list, index);//下载下一组

}

};

main(basicPath + start);

  此次项目已上传我的Github仓库求star,谢谢。

  总结:

  至于后续操作,比如存到分类保存到本地和MongoDB数据库这样的操作,我下次再写,请关注我。

  郑重提升,爬虫虽好,一定不能触犯法律。

  如果本本文触犯您的利益,请留言。

  如果觉得本文不错,不要吝啬您的点赞和关注。谢谢。

博文为原创,允许转载,但请注明出处,谢谢。

相关文章
|
11月前
|
Python
使用OpenPyXL库实现Excel单元格其他对齐方式设置
本文介绍了如何使用Python的`openpyxl`库设置Excel单元格中的文本对齐方式,包括文本旋转、换行、自动调整大小和缩进等,通过具体示例代码展示了每种对齐方式的应用方法,适合需要频繁操作Excel文件的用户学习参考。
513 85
使用OpenPyXL库实现Excel单元格其他对齐方式设置
|
9月前
|
人工智能 Prometheus 监控
容器化AI模型的监控与治理:确保模型持续稳定运行
在前几篇文章中,我们探讨了AI模型的容器化部署及构建容器化机器学习流水线。然而,将模型部署到生产环境只是第一步,更重要的是确保其持续稳定运行并保持性能。为此,必须关注容器化AI模型的监控与治理。 监控和治理至关重要,因为AI模型在生产环境中面临数据漂移、概念漂移、模型退化和安全风险等挑战。全面的监控涵盖模型性能、数据质量、解释性、安全性和版本管理等方面。使用Prometheus和Grafana可有效监控性能指标,而遵循模型治理最佳实践(如建立治理框架、定期评估、持续改进和加强安全)则能进一步提升模型的可信度和可靠性。总之,容器化AI模型的监控与治理是确保其长期稳定运行的关键。
|
12月前
|
消息中间件 存储 监控
深度写作:深入源码理解MQ长轮询优化机制
【11月更文挑战第22天】在分布式系统中,消息队列(Message Queue, MQ)扮演着至关重要的角色。MQ不仅实现了应用间的解耦,还提供了异步消息处理、流量削峰等功能。而在MQ的众多特性中,长轮询(Long Polling)机制因其能有效提升消息处理的实时性和效率,备受关注。
399 12
|
机器学习/深度学习 人工智能 物联网
2024年软件开发趋势
【10月更文挑战第29天】本文概述了2024年软件开发领域的五大新趋势,涵盖人工智能与机器学习的深入整合、JAMstack架构的广泛采纳、对网络安全的强化关注、远程办公模式的持续影响,以及物联网技术的迅速扩张。这些趋势不仅反映了技术的进步,也展示了软件开发行业对效率、安全性和用户体验的不断追求。
|
存储 缓存 安全
阿里云服务器通用型实例规格特点、适用场景、收费标准和活动价格参考
阿里云服务器通用型实例规格有哪些?最新价格是多少?阿里云服务器通用型实例规格有X86计算和ARM计算两种架构,每种架构都包含了不同类型的通用型实例,所以相同cpu和内存配置的通用型实例云服务器,收费价格标准也大不相同,下面小编为大家汇总一下哪些实例属于通用型实例规格,它们的最新收费价格标准又是怎样的,以供参考选择。
阿里云服务器通用型实例规格特点、适用场景、收费标准和活动价格参考
|
IDE Linux 开发工具
linux镜像下载和vmware虚拟主机部署
linux镜像下载和vmware虚拟主机部署
1110 0
linux镜像下载和vmware虚拟主机部署
|
机器学习/深度学习 人工智能 安全
Yolov5:强大到你难以想象──新冠疫情下的口罩检测
Yolov5:强大到你难以想象──新冠疫情下的口罩检测
853 0
Yolov5:强大到你难以想象──新冠疫情下的口罩检测
|
Python
Python获取指定目录下的所有文件路径、获取指定目录下所有文件名(但是不包含子目录中文件名)、获取指定目录下所有pdf文件名(但是不包含子目录中pdf文件名)
Python获取指定目录下的所有文件路径、获取指定目录下所有文件名(但是不包含子目录中文件名)、获取指定目录下所有pdf文件名(但是不包含子目录中pdf文件名)
453 0
|
机器学习/深度学习 弹性计算 运维
WSDM 2021 | 构建动态图分析时间序列状态的演化
本文简要介绍我们刚刚被WSDM2021会议录用并即将发表的论文&quot;Time-Series Event Prediction with Evolutionary State Graph&quot;,在文中我们提出了一种将时序转化为图进行表示建模的方法。同时我们把所实现的方法落地为阿里云·SLS的智能巡检服务,可以应用于大规模的时间序列异常检测与分析,辅助运维、运营、研发等诸多场景。
6292 0
WSDM 2021 | 构建动态图分析时间序列状态的演化
|
云安全 弹性计算 运维
阿里云重磅发布云原生裸金属方案:裸金属+容器,解锁云计算的新方式
新一代容器服务ACK,可以将最新神龙弹性裸金属实例的强大性能发挥得淋漓尽致,具备极致性能、高效调度、全面安全的特点。
2223 0
阿里云重磅发布云原生裸金属方案:裸金属+容器,解锁云计算的新方式