node爬虫之图片下载
背景:针对一些想换头像的玩家,而又不知道用什么头像的,作为一名代码爱好者,能用程序解决的,就不用程序来换头像,说干就干,然后就整理了一下。
效果图

环境配置
- 安装node环境
- node -v
- node版本最好在8.11.1以上
项目结构

assets是存放所下载的图片
static是静态资源页面
eg.js是下载图片示例(node eg.js)
img.json是网页所获取的json数据
index.js属于服务端
安装依赖
npm init ( 会生成一个package.json) npm i express --save-dev npm i cheerio--save-dev npm i superagent--save-dev npm i superagent-charset--save-dev npm i request--save-dev
- SuperAgent 是一个轻量级、灵活的、易读的、低学习曲线的客户端请求代理模块,使用在NodeJS环境中
- superagent-charset 防止爬取下来的数据乱码,更改字符格式
- cheerio 是jquery核心功能的一个快速灵活而又简洁的实现,主要是为了用在服务器端需要对DOM进行操作的地方。
- request 的功能比较强大,在 这里只是为了下载图片用的
代码区
1. eg.js
var fs = require('fs');
var request = require("request");
var path = require('path');
var src = "https://pic.qqtn.com/up/2019-6/2019061811092772406.jpg";
var writeStream = fs.createWriteStream('./assets/aa.png');
var readStream = request(src)
readStream.pipe(writeStream);
readStream.on('end', function() {
console.log('文件下载成功');
});
readStream.on('error', function() {
console.log("错误信息:" + err)
})
writeStream.on("finish", function() {
console.log("文件写入成功");
writeStream.end();
});
2.index.js
var superagent = require('superagent');
var charset = require('superagent-charset');
charset(superagent);
var express = require('express');
var baseUrl = 'https://www.qqtn.com/';
const cheerio = require('cheerio');
var request = require("request");
var fs = require('fs')
var path = require('path')
var checkDir = fs.existsSync("assets");
var app = express();
app.use(express.static('static'))
app.get('/index', function (req, res) {
//设置请求头
res.header("Access-Control-Allow-Origin", "*");
res.header('Access-Control-Allow-Methods', 'PUT, GET, POST, DELETE, OPTIONS');
res.header("Access-Control-Allow-Headers", "X-Requested-With");
res.header('Access-Control-Allow-Headers', 'Content-Type');
//类型
console.log(req.query, '类型')
var type = req.query.type;
//页码
var page = req.query.page;
type = type || 'weixin';
page = page || '';
var route = `tx/${type}tx_${page}.html`
//网页页面信息是gb2312,所以chaeset应该为.charset('gb2312'),一般网页则为utf-8,可以直接使用.charset('utf-8')
superagent.get(baseUrl + route)
.charset('gb2312')
.end(function (err, sres) {
var items = [];
if (err) {
console.log('ERR: ' + err);
res.json({ code: , msg: err, sets: items });
return;
}
var $ = cheerio.load(sres.text);
$('div.g-main-bg ul.g-gxlist-imgbox li a').each(function (idx, element) {
var $element = $(element);
var $subElement = $element.find('img');
var thumbImgSrc = $subElement.attr('src');
items.push({
title: $(element).attr('title'),
href: $element.attr('href'),
thumbSrc: thumbImgSrc
});
});
if (!checkDir) {
fs.mkdir('assets', function (error) {
if (error) {
console.log(error);
return false;
}
console.log('创建目录成功');
})
}
fs.access(path.join(__dirname, '/img.json'), fs.constants.F_OK, err => {
if (err) { // 文件不存在
fs.writeFile(path.join(__dirname, '/img.json'), JSON.stringify([
{
route,
items
}
]), err => {
if (err) {
console.log(err)
return false
}
console.log('保存成功')
})
} else {
fs.readFile(path.join(__dirname, '/img.json'), (err, data) => {
if (err) {
return false
}
data = JSON.parse(data.toString())
let exist = data.some((page, index) => {
return page.route == route
})
if (!exist) {
fs.writeFile(path.join(__dirname, 'img.json'), JSON.stringify([
...data,
{
route,
items
},
]), err => {
if (err) {
return false
}
})
}
})
}
res.json({ code: , msg: "", data: items });
})
try {
fs.readFile(path.join(__dirname, '/img.json'), (err, data) => {
if (err) {
return false
}else{
data = JSON.parse(data.toString());
data.map((v, i) => {
v.items.map((v,i) => {
i = request(v.thumbSrc)
// 后缀.jpg可用正则匹配
i.pipe(fs.createWriteStream('./assets/' + v.title + '.jpg'));
})
})
}
})
} catch(err){}
})
});
app.get('/show', (req, res) => {
fs.readFile(path.join(__dirname, 'img.json'), (err, data) => {
if (err) {
console.log(err)
return false
}
res.json(data.toString())
})
})
var server = app.listen(, function () {
var host = server.address().address
var port = server.address().port
})
3.static文件夹下index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<script src="./index.js"></script>
</body>
</html>
4.static文件夹下index.js
fetch('/index', {
method: 'GET'
}).then(res => {
return res.json()
}).then(res => {
if (res.code == ) {
fetch('/show', {
method: 'GET'
}).then(res => {
return res.json()
}).then(res => {
res = JSON.parse(res)
console.log(res, res.length)
document.body.innerHTML = res.map((page, index) => {
console.log(page)
return page.items.map((item, itemIndex) => {
return `<a href="${item.thumbSrc}" ><img src="${item.thumbSrc}" width="" height=""/></a>`
}).join('')
}).join('')
})
}
})
总结
写到这里基本是结束了,对于node我还是怀着一个敬畏的心,摸摸索索终于把这个demo写完了,项目也传到gitHub了如有需要可私信
node爬虫之图片下载的更多相关文章
- Node.js制作图片下载爬虫的一般步骤
图片下载爬虫分两部分:爬页面和下载图片. 爬页面时先看网址是https还是http的,然后选择不同的内置对象: 其次看编码,如果是charset=gb2312的网页就需要iconv帮忙转码,好在大部分 ...
- node爬虫 -- 网页图片
相信大家都听说过爬虫,我们也听说过Python是可以很方便地爬取网络上的图片,但是奈何本人不会Python,就只有通过 Node 来实践一下了. 接下来看我如何 板砖 ! !!
- Node.js mimimn图片批量下载爬虫 1.00
这个爬虫在Referer设置上和其它爬虫相比有特殊性.代码: //====================================================== // mimimn图片批 ...
- Node.js meitulu图片批量下载爬虫1.01版
在 http://www.cnblogs.com/xiandedanteng/p/7614051.html 一文我曾经书写过一个图片下载爬虫,但原有程序不是为下载图片而设计故有些绕,于是稍微改写了一下 ...
- node 爬虫 --- 批量下载图片
步骤一:创建项目 npm init 步骤二:安装 request,cheerio,async 三个模块 request 用于请求地址和快速下载图片流. https://github.com/reque ...
- python简易爬虫来实现自动图片下载
菜鸟新人刚刚入住博客园,先发个之前写的简易爬虫的实现吧,水平有限请轻喷. 估计利用python实现爬虫的程序网上已经有太多了,不过新人用来练手学习python确实是个不错的选择.本人借鉴网上的部分实现 ...
- (8)分布式下的爬虫Scrapy应该如何做-图片下载(源码放送)
转载主注明出处:http://www.cnblogs.com/codefish/p/4968260.html 在爬虫中,我们遇到比较多需求就是文件下载以及图片下载,在其它的语言或者框架中,我们可能 ...
- 第三百四十一节,Python分布式爬虫打造搜索引擎Scrapy精讲—编写spiders爬虫文件循环抓取内容—meta属性返回指定值给回调函数—Scrapy内置图片下载器
第三百四十一节,Python分布式爬虫打造搜索引擎Scrapy精讲—编写spiders爬虫文件循环抓取内容—meta属性返回指定值给回调函数—Scrapy内置图片下载器 编写spiders爬虫文件循环 ...
- 手把手教你写基于C++ Winsock的图片下载的网络爬虫
手把手教你写基于C++ Winsock的图片下载的网络爬虫 先来说一下主要的技术点: 1. 输入起始网址,使用ssacnf函数解析出主机号和路径(仅处理http协议网址) 2. 使用socket套接字 ...
随机推荐
- CF53E Dead Ends
CF53E Dead Ends 洛谷评测传送门 题目描述 Life in Bertown has become hard. The city has too many roads and the go ...
- java(三)基础类型之间的转换
自动类型转换:容量小的类型自动转换成为容量大的数据类型,数据类型按容量大小排序为: 有多种类型的数据混合运算时,系统首先自动将所有数据转换成容量最大的那种数据类型,然后在进行运算: byte.shor ...
- Java连载40-参数传递、this关键字
一.对象和引用 1.对象:目前在使用new运算符在堆内存中开辟的内存空间成为对象. 2.引用:是一个变量,不一定是局部变量,好可能是成员变量,引用保存了内存地址,指向了堆内存中对象.所有访问实例的相关 ...
- EventBus 使用/架构/源码分析
EventBus是针对Android优化的发布-订阅事件总线,简化了Android组件间的通信.EventBus以其简单易懂.优雅.开销小等优点而备受欢迎. github 地址:https://git ...
- Java泛型类型擦除与运行时类型获取
Java的泛型大家都知道是类型擦除的方式实现的,“编译器会进行泛型擦除”是一个常识了(实际擦除的是参数和自变量的类型).“类型擦除” 并非像许多开发者认为的那样,在 <..> 符号内的东西 ...
- CSAPP lab3 bufbomb-缓冲区溢出攻击实验(上)smoke fizz
前言 完成这个实验大概花费一天半的时间,看了很多大佬的博客,也踩了很多的坑,于是打算写一篇博客重新梳理一下思路和过程,大概会有两篇博客吧. CSAPP lab3 bufbomb-缓冲区溢出攻击实验(上 ...
- SpringBoot2.0.4部署在tomcat容器中
1. 修改启动类继承自SpringBootServletInitializer. 2. 重写config方法: @Overrideprotected SpringApplicationBuilder ...
- Chrome浏览器Json查看插件JsonHandle下载以及无法安装插件的解决方法
场景 在使用Chrome浏览器查看Json数据时如果没有插件会挤作一团. 安装JsonHandle插件后 博客: https://blog.csdn.net/badao_liumang_qizhi 关 ...
- Dynamics CRM 客户端程序开发:在实体的列表界面添加按钮
关注本人微信和易信公众号: 微软动态CRM专家罗勇 ,回复114或者20140312可方便获取本文,同时可以在第一时间得到我发布的最新的博文信息,follow me! 如果没有安装Ribbon Wor ...
- Model赋值返回json
DataTable resultList = bll.GetResultListByCondition(bureauCode, deptCode, fileTitle); IList<GanBu ...