Node.js之爬取点我达技术博客上的数据(-)

干玲昌

前言

最近几天在看node.js方面的东西,想着结合一些小实例进行学习,这样可以更好的掌握所学的内容。于是就定了一个小demo,爬取点我达技术博客上面的文章标题+文章作者+发布时间。有不对的地方欢迎指正。


环境搭建

  • 下载node.js
  • 下载webStorm 这两个东西的下载网上都有很详细的下载过程。

需要的一些基础知识

  • html
  • javascript
  • jquery
  • node.js

创建项目

  1. 进入到项目存放的路径下
  2. mkdir dirname 创建文件夹
  3. cd dirname 进入文件夹路径
  4. npm init 初始化项目
    如果没有特殊的要求,接下去的过程可以一路回车键,这样就可以完成项目的初始化过程了
  5. 安装cheerio包
    npm install cheerio
  6. 在dirname中创建一个js文件用于编写代码

cheerio

  • 为服务器特别定制的,快速、灵活、实施的jQuery核心实现
  • Cheerio 包括了 jQuery 核心的子集。Cheerio 从jQuery库中去除了所有 DOM不一致性和浏览器尴尬的部分,揭示了它真正优雅的API
  • Cheerio 工作在一个非常简单,一致的DOM模型之上。解析,操作,呈送都变得难以置信的高效。基础的端到端的基准测试显示Cheerio 大约比JSDOM快八倍(8x)
  • Cheerio 封装了兼容的htmlparser。Cheerio 几乎能够解析任何的 HTML 和 XML document

<1> 首先来点我达技术博客网站看下html文档的结构

我们需要title,author和time,因此不难可以找到网页中的元素。 如上图所示,我们所需要的属性都被找到了!

<2> 从找到的标签,可以比较简单的写出得到这些属性的代码。
1)获取title
var title = $(".post-title a:first-child");
2)获取author
var author = $(".post-meta a:first-child");
3)获取time
var time = $(".post-date");
这样,我们就分别得到了三个存储这属性标签的数组。由于得到的都是元素的数组,因此我们需要定义三个字符串数组分别来存储这三个元素中的内容。

author.each(function () {  
  authorArray.push($(this).text());
});
time.each(function () {  
  timeArray.push($(this).text());
});
title.each(function () {  
  titleArray.push($(this).text());
});

这样,我们就将一个页面中的所有的title,time,author都存到了三个数组中。但是,点我达技术博客是分页的,会有很多个页面,这个时候光读取一个页面是远远不够的。接下去我们继续分析html代码。比较页面和最后一个页面,我发现最后一个页面少了一个元素。代码如下
没错,就是类名为older-posts的a标签,所以我们可以通过判断页面是否存在older-posts标签来确定是否存在下一页,若有下一页,则进入进入下一页再读取数据。

<3> 因此,在页面存在older-posts标签的时候,则获取到标签中的href属性,同时进入到下个页面。代码如下

if ($(".older-posts").length > 0) {  
       var nextUrl = $(".older-posts").attr("href");
       var newUrl = url.substring(0, 24);
       startSpider(newUrl + nextUrl);//startSpider()是开启爬取数据的函数
 }

<4> 最后我们只需要将全局的三个存储着title,author和time的三个字符串连在一起,打印出来就可以了。

function test() {  
for (var i = 0; i < titleArray.length; i++) {   console.log(titleArray[i]+":"+timeArray[i]+":"+authorArray[i]);  
    }
}

这样,整个过程就完成了。下面是完整的代码。

/**
 * Created by glc on 2017/9/20.
 */
var http = require("http");  
var fs = require("fs");  
var cheerio = require("cheerio");  
var url = "http://tech.dianwoda.com";  
var authorArray = new Array();//存储作者的名称数组  
var titleArray = new Array();//存储文章标题数组  
var timeArray = new Array();//存储发表时间数组  
function startSpider(url) {  
    http.get(url, function (res) {
            var html = "";//存储网页html
            res.setEncoding("utf-8");
            //监听获取到数据
            res.on("data", function (data) {
                html += data;
            })
            res.on("end", function () {
                var $ = cheerio.load(html);
                var author = $(".post-meta a:first-child");
                var time = $(".post-date");
                var title = $(".post-title a:first-child");
                author.each(function () {
                    authorArray.push($(this).text());
                });
                time.each(function () {
                    timeArray.push($(this).text());
                });
                title.each(function () {
                    titleArray.push($(this).text());
                })
                if ($(".older-posts").length > 0) {
                    var nextUrl = $(".older-posts").attr("href");
                    var newUrl = url.substring(0, 24);
                    startSpider(newUrl + nextUrl);
                }
            })
        }
    )
}
startSpider(url)  
setTimeout(test,2000);//因为网络请求会消耗时间,会导致异步执行,这里阻塞2秒钟,再执行test方法。

function test() {  
    for (var i = 0; i < titleArray.length; i++) {
        console.log(titleArray[i]+":"+timeArray[i]+":"+authorArray[i]);
    }
}

运行的结果如图所示


总结:虽然这个项目非常的简单,但是在完成这个项目的时候,对于jquery操作dom和nodejs有了更好的掌握。


下一篇,是将每一篇文章全部抓取出来,以作者-时间-标题为文件名,以txt文件存储在本地。