3

Node.JS的异步I/O特性很适合I/O密集型任务,再加上JQuery的HTML解析加成,制作简单的网络爬虫非常容易,性能也在可以接受的水平

将用到的知识

  • 基本网络请求

  • JQuery Selector

  • fs 文件操作

准备

首先我们安装所需的依赖

  • superagent
    nodejs里一个非常方便的客户端请求代理模块

  • superagent-charset
    支持更多字符集部分情况可能用到(此例中暂不使用)

  • cheerio
    与jQuery类似的API,用于解析HTML

分析网页与爬虫实现

  • 列表页 http://www.mzitu.com/

  • 示例详情页 http://www.mzitu.com/71235

这里我们使用Paw这款Mac上常用的接口调试软件来测试一下主页(功能与Postman类似)
图片描述

可以看到,访问一切正常,接下来我们进行列表的抓取,
函数原型为function catch_list(url,callback)
首先require一下基本模块

var superagent =  require('superagent-charset')(require('superagent'));
var cheerio = require('cheerio');
var fs= require('fs');
var path = require('path');
var main_url  = 'http://www.mzitu.com/';
var meiziURL  = 'http://www.mzitu.com/71235';

网络请求

在函数中编写基本的网络请求

function catch_list(url,callback) {
    superagent
        .get(url)
        .end(function (err,sres) {
        if(err){
            console.error(err)
        }
        console.log(sres)
    })
}

调用函数,尝试访问,获得了一个Forbidden错误
由此可知网站对于访问进行了检查,我们复制Paw的请求头,重写网络请求

function catch_list(url,callback) {
    superagent
        .get(url)
        .set('Connection','close')
        .set('User-Agent','Paw/2.1 (Macintosh; OS X/10.11.6) GCDHTTPRequest')
        .set('Host', 'www.mzitu.com')
        .end(function (err,sres) {
        if(err){
            console.error(err)
        }
        console.log(sres)
    })
}

HTML解析

这次访问到了数据,我们开始进行网页解析
关于网页的解析,我们可以借助Chrome直接获得元素的Selector
图片描述
我们获得的内容为#pins > li:nth-child(1) > a
可以看出我们想要的数据保存在id为pins的标签下的列表中

//sres.text 里面存储着网页的 html 内容,将它传给 cheerio.load 之后
// 就可以得到一个实现了 jquery 接口的变量,我们习惯性地将它命名为 `$`
var $ = cheerio.load(sres.text)
$('#pins').find('li').each(function (idx,element) {
    $element = $(element)
    var url = $element.find('span:nth-child(2) > a').attr('href')
    var title = $element.find('img').attr('alt')
    console.log(title,url)
})

函数完成

接下来我们观察控制台已经输出了我们需要的内容
我们来将内容放进数组,通过callback传回

function catch_list(url,callback) {
    superagent
        .get(url)
        .set('Connection','close')
        .set('User-Agent','Paw/2.1 (Macintosh; OS X/10.11.6) GCDHTTPRequest')
        .set('Host', 'www.mzitu.com')
        .end(function (err,sres) {
            if(err){
                console.error(err)
            }
            var items = []
            var $ = cheerio.load(sres.text)
            $('#pins').find('li').each(function (idx,element) {
                $element = $(element)
                var url = $element.find('span:nth-child(2) > a').attr('href')
                var title = $element.find('img').attr('alt')
                console.log(title,url)
                items.push({
                    title:title,
                    url:url
                })
            })
            callback(items)
    })
}

数据的本地保存

我们可以看到,这个网站内容非常多,所以我们考虑保存下每个图集的title和url到本地json文件

function write_to_file_in_JSON(items,dir,filename) {
    console.log('完成'+items.length +'个抓取');
    var fs= require('fs');
    var dirname = dir +filename+'.json';
    var path = require('path');
    fs.writeFile(dirname, JSON.stringify(items));
}

for (var i = 1;i<=127;i++){
    var success = 1
    var data = []
    catch_list(main_url+'page/'+String(i),function (items) {
        console.log(items.length)
        data = data.concat(items)
        success++
        if (success == 2) write_to_file_in_JSON(data,'/Users/xxx/Desktop/','妹子图')
    })
}

这时我们已经将每一个图集的基本信息存储到了桌面上的妹子图.json文件中了

图片描述


Hydrogen
2.5k 声望73 粉丝

Write code for fun.