爬虫

作者:yuyuyu
链接:https://zhuanlan.zhihu.com/p/24730075
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

序言

闲的无聊,看到一个段子网站的美女福利还不错,迫于福利加载太慢看的不过瘾,就想用Nodejs写个简单爬虫全部爬下来看多好….. 此处省略5000字…..

准备

要爬,首先得要有目标,我呢,就把目标锁定到了 某哈,然后呢就是用浏览器来分析分析其中的规律

从中可以看到每一条段子都是一个 .joke-list-item, 当点击下一页的时候 url中地址的最后一位数就表示分页的页码。有些图片是缩略图,我们把缩略图和正常图的地址进行了比较,发现他们的地址格式是一样的,缩略图在small文件夹下,大图在big文件夹下。分析完了我们就可以写代码了。

开始

这个简单爬虫分两个部分,1、获取图片地址。2、进行下载。因为下载是一个耗时的操作,所以两个部分分开了,这样也有利于后期改动。

导入必要的模块,使用cheerio 是第三方模块,可以使用 npm install cheerio 进行安装

var http = require(‘http’); // http 网路
var cheerio = require(‘cheerio’); // html 解析
var fs = require(“fs”); // 流

var queryHref = “http://www.haha.mx/topic/1/new/“; // 设置被查询的目标网址
var querySearch = 1; // 设置分页位置

var urls = []; // 所有待下载的图片地址

这个是解析图片地址方法

/**
* 根据url和参数获取分页内容
* @param {String}: url
* @param {int}: serach
*/
function getHtml(href, serach) {
var pageData = “”;
var req = http.get(href + serach, function(res) {
res.setEncoding(‘utf8’);
res.on(‘data’, function(chunk) {
pageData += chunk;
});

res.on('end', function() {
  $ = cheerio.load(pageData);
  var html = $(".joke-list-item .joke-main-content a img");

  for(var i = 0; i < html.length; i++) {
    var src = html[i].attribs.src;
    // 筛选部分广告,不是真的段子
    if (src.indexOf("http://image.haha.mx") > -1) {
      urls.push(html[i].attribs.src)
    }
  }

});

});
}

这个是下载图片的方法

/**
* 下载图片
* @param {String} imgurl:图片地址
*/
function downImg(imgurl) {
var narr = imgurl.replace(“http://image.haha.mx/“, “”).split(“/”)

http.get(imgurl.replace(“/small/”, “/big/”), function(res) {
var imgData = “”;
//一定要设置response的编码为binary否则会下载下来的图片打不开
res.setEncoding(“binary”);

res.on("data", function(chunk) {
  imgData += chunk;
});

res.on("end", function() {
  var savePath = "./upload/topic1/" + narr[0]  + narr[1] + narr[2] + "_" + narr[4];
  // 保存图片
  fs.writeFile(savePath, imgData, "binary", function(err) {
    if(err) {
      console.log(err);
    }
  });
});

});
}

好,到这里核心的东西就写完了,然后就是组装一下,让他运行起来

附一个完整代码:

var http = require(‘http’); // http 网路
var cheerio = require(‘cheerio’); // html 解析
var fs = require(“fs”); // 流

// 设置被查询的目标网址
var queryHref = “http://www.haha.mx/topic/1/new/“;
// 设置分页位置
var querySearch = 1;

var urls = [];

/**
* 根据url和参数获取分页内容
* @param {String}: url
* @param {int}: serach
*/
function getHtml(href, serach) {
var pageData = “”;
var req = http.get(href + serach, function(res) {
res.setEncoding(‘utf8’);
res.on(‘data’, function(chunk) {
pageData += chunk;
});

res.on('end', function() {
  $ = cheerio.load(pageData);
  var html = $(".joke-list-item .joke-main-content a img");

  for(var i = 0; i < html.length; i++) {
    var src = html[i].attribs.src;
    // 筛选部分广告,不是真的段子
    if (src.indexOf("http://image.haha.mx") > -1) {
      urls.push(html[i].attribs.src)
    }
  }
  if (serach == pagemax) {
    console.log("图片链接获取完毕!" + urls.length);
    console.log("链接总数量:" + urls.length);
    if (urls.length > 0) {
      downImg(urls.shift());
    } else {
      console.log("下载完毕");
    }
  }
});

});
}

/**
* 下载图片
* @param {String} imgurl:图片地址
*/
function downImg(imgurl) {
var narr = imgurl.replace(“http://image.haha.mx/“, “”).split(“/”)

http.get(imgurl.replace(“/small/”, “/big/”), function(res) {
var imgData = “”;
//一定要设置response的编码为binary否则会下载下来的图片打不开
res.setEncoding(“binary”);

res.on("data", function(chunk) {
  imgData += chunk;
});

res.on("end", function() {
  var savePath = "./upload/topic1/" + narr[0]  + narr[1] + narr[2] + "_" + narr[4];
  fs.writeFile(savePath, imgData, "binary", function(err) {
    if(err) {
      console.log(err);
    }  else {
      console.log(narr[0]  + narr[1] + narr[2] + "_" + narr[4]);
      if (urls.length > 0) {
        downImg(urls.shift());
      } else {
        console.log("下载完毕");
      }
    }
  });
});

});
}

var pagemax = 10; // 获取10页的内容
function start(){
console.log(“开始获取图片连接”);
for (var i = 1 ; i <= pagemax ; i++) {
getHtml(queryHref, i);
}
}

start();

因为nodejs是异步的,所以在 start 方法中的for之后调用下载是不行,这个时候显示的 urls 中是没有数据的。

所以就是在 getHtml 中 等所有的连接分析完毕之后在调用 downImg,downImg下载完成之后在进行下一个下载。

项目目录很简单,如图:

然后我们切换到项目目录,执行 node app , 然后就静静的等待把,每次下载完一个会有对应的文件名打印出来的。

最后会出现 下载完毕!,之后就……. 你懂得……

这个是一个很简单的,当然后续你可以加上数据库,数据更新之类的…..

放几张我爬到的图
这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值