node爬虫(转)
我们先来看看今天的目标: mmjpg.com的美腿频道下的图片
一、实现步骤
使用superagent库来获取页面
分析页面结构,使用cheerio 获取有效信息
保存图片到本地
开撸
不断优化
这儿我们用到了superagent cheerio fs-extra这三个库
$ npm i superagent cheerio fs-extra --save
1.superagent 是nodejs里一个非常方便的客户端请求代理模块
2.cheerio:为服务器特别定制的,快速、灵活、实施的jQuery核心实现
3.fs-extra: 丰富了fs模块,同时支持async/await
二.请求URL获取HTML
app.js 使用superagent发起请求并打印出页面内容
const request = require('superagent')
const cheerio = require('cheerio')
const fs = require('fs-extra') let url = 'http://www.mmjpg.com/tag/meitui/' request.get(url + '1').then(function (res) {
console.log(res.text)
})
// 你就可以看见HTML内容打印到了控制台
三.分析页面结构
使用cheerio来操作了,cheerio语法和jQuery基本一样。
找到class为pic那个div下的列表中,现在我们就可以使用cheerio来获取
async function getUrl() {
const res = await request.get(url + 1)
const $ = cheerio.load(res.text)
$('.pic li').each(function(i, elem) {
const href = $(this).find('a').attr('href')
const title = $(this).find('.title').text()
console.log(title, href)
})
} getUrl()
/*
$ node app.js
长腿美女白一晗巨胸丝袜写真精美图片 http://www.mmjpg.com/mm/1255
大美女尹菲开档网袜写真令人眼花缭乱 http://www.mmjpg.com/mm/1230
宅男女神丰满诱人的胴体令人想入非非 http://www.mmjpg.com/mm/1164
性感美女浴室写真高耸的酥胸诱惑十足 http://www.mmjpg.com/mm/1162
长相清纯甜美的97年妹子苗条美腿图片 http://www.mmjpg.com/mm/1157
丽质美女柔美修长美腿带给你曼妙感受 http://www.mmjpg.com/mm/1153
容貌似杨幂的美女馨怡美腿极致诱惑图 http://www.mmjpg.com/mm/1148
丝袜美腿诱惑!甜美女神杨晨晨私房套图 http://www.mmjpg.com/mm/1130
性感美女刘钰儿透视内衣私密照真撩人 http://www.mmjpg.com/mm/1127
肤白貌美的模特李晨晨十分惹人怜爱 http://www.mmjpg.com/mm/1126
萌妹林美惠子穿黑丝浴室私房写真福利 http://www.mmjpg.com/mm/1124
美女赵小米修长双腿丝袜写真能玩几年 http://www.mmjpg.com/mm/1111
微博高颜值美胸萌妹子少女映画写真集 http://www.mmjpg.com/mm/1107
性感妹子修长的双腿真是让人爱不释目 http://www.mmjpg.com/mm/1106
翘臀妹子绮里嘉饱满胸部美的夺人心目 http://www.mmjpg.com/mm/1103
*/
四.分析URL地址
在很多时候我们都需要分析URL,就像点击不同的页码观察URL变化 http://www.mmjpg.com/home/2,我们可以很容易发现页码对应为URL最后的数字。查看mmjpg.com的美腿频道我们可以发现它一共有10页内容,我们就不写代码判断页数了直接写死为10。当然了这儿你可以自己实现动态判断总页数,就当是留的小练习吧。
async function getUrl() {
let linkArr = []
for (let i = 1; i <= 30; i++) {
const res = await request.get(url + i)
const $ = cheerio.load(res.text)
$('.pic li').each(function(i, elem) {
let link = $(this).find('a').attr('href')
linkArr.push(link)
})
}
console.log(linkArr);
return linkArr;
}
五.获取图片地址
async function getPic(url) {
const res = await request.get(url)
const $ = cheerio.load(res.text)
// 以图集名称来分目录
const dir = $('.article h2').text()
console.log(`创建${title}文件夹`)
await fs.mkdir(path.join(__dirname, '/mm', title))
const pageCount = parseInt($('#page .ch.all').prev().text())
for (let i = 1; i <= pageCount; i++) {
let pageUrl = url + '/' + i
const data = await request.get(pageUrl)
const _$ = cheerio.load(data.text)
// 获取图片的真实地址
const imgUrl = _$('#content img').attr('src')
download(dir, imgUrl) // TODO
}
}
六.保存图片到本地
现在我们就来实现下载保存图片的方法,这儿我们使用了stream(流) 来保存图片 function download(dir, imgUrl) {
console.log(`正在下载${imgUrl}`)
const filename = imgUrl.split('/').pop()
const req = request.get(imgUrl)
.set({ 'Referer': 'http://www.mmjpg.com' }) // mmjpg.com根据Referer来限制访问
req.pipe(fs.createWriteStream(path.join(__dirname, 'mm', dir, filename)))
}
ok,现在我们就来把之前写的各个功能的函数连起来 async function init(){
let urls = await getUrl()
for (let url of urls) {
await getPic(url)
}
} init()
代码:
const request = require('superagent')
const cheerio = require('cheerio')
const fs = require('fs-extra')
const path = require('path') let url = "http://www.u-cpc.com/product/list.html"; // http://www.u-cpc.com/Product/List.html?page=3&cid=0&bid=0 // request.get(url).then(function(res){
// console.log(res.text);
// }) // async function getUrl(){
// const res = await request.get(url);
// const $ = cheerio.load(res.text);
// $(".product_ul li").each(function(i, elem){
// const href = $(this).find("img").attr("data-original")
// const title = $(this).find(".productlist_title").text();
// console.log("标题是: " + title)
// console.log("地址是: " + href)
// })
// }
// getUrl(); /**
* 获取图集的URL
*/
async function getUrl(){
let linkArr = [];
for(let i = 0; i <= 10; i++){
const res = await request.get(url);
const $ = cheerio.load(res.text); $(".product_ul li").each(function(i, elem){
const href = $(this).find("img").attr("data-original")
const title = $(this).find(".productlist_title").text();
linkArr.push(href)
})
}
}
async function getPic(url) {
const res = await request.get(url)
const $ = cheerio.load(res.text)
// 以图集名称来分目录
const dir = $('.curr').text()
console.log(`创建${dir}文件夹`)
await fs.mkdir(path.join(__dirname, '/images', dir))
for(let i = 1; i <= 10; i++){
let pageUrl = url + '?page=' + i + '&cid=0&bid=0';
const data = await request.get(pageUrl)
const _$ = cheerio.load(data.text)
_$(".product_ul li").each(function(i, elem){
const imgUrl = $(this).find("img").attr("data-original");
download(dir, imgUrl)
})
}
} // 下载图片
function download(dir, imgUrl) {
console.log(`正在下载${imgUrl}`)
const filename = imgUrl.split('/').pop()
const req = request.get(imgUrl)
.set({
'Referer': 'http://www.u-cpc.com/product/list.html'
})
req.pipe(fs.createWriteStream(path.join(__dirname, 'images', dir, filename)))
} async function init() {
getUrl();
getPic(url)
}
// init();
download();
function download() {
const url2 = "https://codeload.github.com/cheeriojs/cheerio/zip/master"
const filename = url2.split('/').pop() + ".zip"
const req = request.get(url2)
req.pipe(fs.createWriteStream(path.join(__dirname, 'images', filename)))
}
七: 解决爬取gb2312网页出现乱码
使用superagent爬取网站内容,当网页编码不是utf-8
编码时,中文就会返回乱码,原因是superagent只支持utf-8的网页编码,我们可以使用其扩展的一个npm模块superagent-charset
$ npm i superagent-charset
使用.charset(encoding)
方法,就可以指定编码,详细如下:
const charset = require('superagent-charset');
const request = charset(require('superagent'));
superagent
.get(url) // 获取网页内容
.charset('gb2312') // 转码-将gb2312格式转成utf-8
.then(function(err, res){
});
// 爬公司的器材, 生成json文件
const request = require('superagent')
const cheerio = require('cheerio')
const fs = require('fs-extra')
const path = require('path') let url = "http://www.u-cpc.com/product/list.html"; var toptens = []; // 初始化json数组 /**
* 获取图集的URL
*/ async function getUrl(){
let linkArr = [];
for(let i = 1; i <= 10; i++){
const res = await request.get(url);
const $ = cheerio.load(res.text);
let pageUrl = url + '?page=' + i + '&cid=0&bid=0';
linkArr.push(pageUrl);
}
return linkArr;
}
async function getPic(newUrl) {
const topten = { // 设定爬取的json数组
info: []
};
const res = await request.get(newUrl)
const $ = cheerio.load(res.text)
// 以图集名称来分目录
const dir = $('.curr').text()
console.log(`创建${dir}文件夹`)
await fs.mkdir(path.join(__dirname, '/images', dir))
$(".product_ul li").each(function(i, elem){
i += 1;
const imgUrl = $(this).find("img").attr("data-original");
const imgText = $(this).find(".productlist_title").text();
topten.info.push({
number: i,
title: imgText,
images: imgUrl
})
download(dir, imgUrl);
}); toptens.push({topten: topten}); // 从原有的json数据之前追加json数据
const json = JSON.stringify(toptens); // json格式解析,这步也是一定要有
downloadJson(json);
} // 创建json文件
function downloadJson(json){
const filename = "toptens.json";
const file = path.join(__dirname, filename)
fs.outputFile(file, json, function(err) {
//file has now been created, including the directory it is to be placed in
});
} // 下载图片
function download(dir, imgUrl) {
console.log(`正在下载${imgUrl}`)
const filename = imgUrl.split('/').pop()
const req = request.get(imgUrl)
.set({
'Referer': 'http://www.u-cpc.com/product/list.html'
})
req.pipe(fs.createWriteStream(path.join(__dirname, 'images', dir, filename)))
} async function init() {
const getUrls = await getUrl();
for(let i = 0; i < getUrls.length; i++){
await getPic(getUrls[i])
}
}
init();
八:注意并发的,毕竟爬取频率会有限制
问: err:Error: connect ETIMEDOUT 博主做爬虫的时候有没有遇到报这个错的,我按你的代码写爬我们的网站,好多页面都报这个错误
答: 并发爬取的数量太高 或者爬的太快。你爬的网站有做爬虫保护限制。把并发量调低 把 延迟调大 就可以了。
PHP, Python, Node.js 哪个比较适合写爬虫?
1.PHP对多线程、异步支持较差,不建议采用。PHP 4.3.0以后引入的PHP Command Line特性,实现了让PHP脱离Web服务器,和Phthon一样独立运行。因此用来写爬虫也是非常方便的。
2.NodeJS:对一些垂直网站爬取倒可以,但由于分布式爬取、消息通讯等支持较弱,根据自己情况判断。
3.Python:强烈建议,对以上问题都有较好支持。尤其是Scrapy框架值得作为第一选择, 专门用来做爬虫的一个框架。优点诸多:支持xpath;基于twisted,性能不错;有较好的调试工具;
4.C、C++虽然性能不错,但不推荐,尤其是考虑到成本等诸多因素;
参考: https://github.com/ogilhinn/mm-spider
node爬虫(转)的更多相关文章
- 继续node爬虫 — 百行代码自制自动AC机器人日解千题攻占HDOJ
前言 不说话,先猛戳 Ranklist 看我排名. 这是用 node 自动刷题大概半天的 "战绩",本文就来为大家简单讲解下如何用 node 做一个 "自动AC机&quo ...
- Node爬虫
Node爬虫 参考 http://www.cnblogs.com/edwardstudy/p/4133421.html 所谓的爬虫就是发送请求,并将响应的数据做一些处理 只不过不用浏览器来发送请求 需 ...
- node爬虫gbk中文乱码问题
刚入坑node 写第二个node爬虫时,遇到了这个坑,记录一下. 主要步骤: 1.安装iconv-lite 输入npm install iconv-lite 2.将接收到的网页源码以二进制的方式存储下 ...
- 简单的node爬虫练手,循环中的异步转同步
简单的node爬虫练手,循环中的异步转同步 转载:https://blog.csdn.net/qq_24504525/article/details/77856989 看到网上一些基于node做的爬虫 ...
- node爬虫(简版)
做node爬虫,首先像如何的去做这个爬虫,首先先想下思路,我这里要爬取一个页面的数据,要调取网页的数据,转换成页面格式(html+div)格式,然后提取里面独特的属性值,再把你提取的值,传送给你的页面 ...
- node 爬虫 --- 批量下载图片
步骤一:创建项目 npm init 步骤二:安装 request,cheerio,async 三个模块 request 用于请求地址和快速下载图片流. https://github.com/reque ...
- node爬虫的几种简易实现方式
说到爬虫大家可能会觉得很NB的东西,可以爬小电影,羞羞图,没错就是这样的.在node爬虫方面,我也是个新人,这篇文章主要是给大家分享几种实现node 爬虫的方式.第一种方式,采用node,js中的 s ...
- node爬虫之gbk网页中文乱码解决方案
之前在用 node 做爬虫时碰到的中文乱码问题一直没有解决,今天整理下备忘.(PS:网上一些解决方案都已经不行了) 中文乱码具体是指用 node 请求 gbk 编码的网页,无法正确获取网页中的中文(需 ...
- 有趣的Node爬虫,数据导出成Excel
最近一直没更新了诶,因为学习Backbone好头痛,别问我为什么不继续AngularJs~因为2.0要出来了啊,妈蛋!好,言归正传,最近帮我的好基友扒数据,他说要一些股票债券的数据.我一听,那不就是要 ...
- 200行的Node爬虫花了半天的时间把网易云上的30万首歌曲信息都抓取回来了
早两天在网易云听歌看评论的时候,突然想把网易云上所有歌曲都抓取下来然后按照评论数进行一次排名,把评论数超过10万的歌曲都听一次,于是便有了这个项目. 因为只是一个小前端,所以使用了Node来写这个爬虫 ...
随机推荐
- Linux服务器 java生成的图片验证码乱码问题
问题:如图所示项目中生成的图形验证码不能正常显示出需要的字体 原因: linux下没有对应的字体 查找项目中使用到系统字体的地方,如下: 解决: 1. 在本地 路径 C:\Windows\Fonts ...
- 原来找字也可以这样用ElseIf FindStr 手机按键精灵 跟大漠的区别
原来找字也可以这样用ElseIf FindStr(646, 1109, 776, 1261, "公告小叉", "FFFFFF-333333", 0.9, in ...
- [AngularJS] tips技巧收集
单个参数调用angular.module(),用来取得该模块而不是定义新的 这样就可以在不同的地方定义app的controller而不用通过全局变量 angular.module('myapp') ...
- 【WP8】扩展CM的INavigationService方法
CM支持通过ViewModel进行导航,并通过支持参数传递,但是内部只是通过反射的方式构造Uri的参数进行导航,所以只支持简单类型的参数传递,下面对其进行扩展,在页面导航时支持复杂类型的参数传递,并扩 ...
- VIM技巧:选择文本块
在正常模式下(按ESC进入)按键v进入可视化模式,然后按键盘左右键或h,l键即可实现文本的选择.其它相关命令:v:按字符选择.经常使用的模式,所以亲自尝试一下它. V:按行选择.这在你想拷贝或者移动很 ...
- Oracle-10.2.0.1,打补丁10.2.0.5:在 debian 版本4【不含4】以上,及 ubuntu 7.04【不含7.04】以上都可以安装!
如题. todo 特殊的:ubuntu 16.04 LTS 版本 无法安装成功,原因待查找!!! 最近测试练习安装linux x64上的 oracle10.2.0.5, 都要吐了.
- Windows下使用最新的JDK1.7.0_51以上版本连接Jenkins出现SecurityException
我在slave节点上安装了jdk1.8, 当在节点上启动slave-agent的时候,报安全性限制的错误: java.lang.SecurityException: Missing required ...
- redis的有序集合ZSET(stored set)
相关命令 1.ZADD ZADD key-name score member [score member……] 将带有给定分值的成员添加到有序集合里 2.ZREM ZREM key-name mem ...
- JVM垃圾回收机制之引用类型
一:引用的类型 javac编译器编译源文件后,生成字节码文件,在类加载器加载字节码文件到内存中时,在内存中开辟 空间,栈.堆以及方法区,来存放对象以及引用.引用可以分为四种: 强引用:平常我们在编写程 ...
- 使用monkey技术修改python requests模块
例如请求前和请求后各来一条日志,这样就不需要在自己的每个代码都去加日志了. 其实也可以直接记录'urllib3.connectionpool' logger name的日志. 修改了requests ...