1.主要用的的环境和工具包
开发环境:Webstorm+win7+Node.js
需要用到的工具包:request和cheerio这两个工具包(使用npm install的方式安装即可)
2.主要源码如下:
"use strict";
const request = require('request');
const cheerio = require('cheerio');
const fs = require('fs');
const path = require('path');
const url = 'http://blog.sina.com.cn/s/articlelist_1196037175_0_1.html';
// 获取模板字符串, 慧姐使用同步的方式读取数据
// 在外部拿到模板字符串,为了多次使用
const templateStr = fs.readFileSync(path.join(__dirname, 'template.html'));
/**
* 用户获取文章的列表信息
* @param url
* @param callback
*/
function getArticleList(url, callback) {
request(url, function (err, res, body) {
if (err) {
//throw new Error('error');
return callback(err, null);
//return;
}
// 开始解析body
let $ = cheerio.load(body);
// 定义一个数组,用于存储解析的结果信息
let articleList = ;
//console.log($.html());
// 注意: 在使用箭头函数的时候, 函数内部的this并不是绑定的每一项
$('.articleList .articleCell ').each(function () {
// 拿到每一行的元素, 这里如果使用箭头函数的时候访问this的话,就会找不到了
let $this = $(this);
//console.log(this); error
//console.log($this);
// 得到文章标题链接
let $title = $this.find('.atc_title a');
// 得到时间(注意事项:一个class标签可能是会有多个class的属性)
let $time = $this.find('.atc_tm');
articleList.push({
title: $title.text(),
url: $title.attr('href'),
time: $time.text()
});
});
// 实现递归抓取文件的思路
// 1. 递归条件: 是否有下一页
// 当前页面内容抓取完毕之后,开始抓取下一页的内容
let nextURL = $('.SG_pgnext a').attr('href');
if (nextURL){
// 如果有下一下的话,就进行递归抓取
getArticleList(nextURL, function (err, list) {
if (err){
return callback(err, null);
}
// 如果有下一次的话,就把本次的数据集合和上一次结果集合放在一起
callback(null, articleList.concat(list));
});
} else{
// 打印输出得到的文件列表
//console.log(articleList);
callback(null, articleList);
}
});
}
/**
* 获取文章的细节信息
* @param url
* @param callback
*/
function getDetailByUrl(url, callback) {
// 进入到文章的细节信息
request(url, function (err, res, body) {
if (err) {
return callback(err, null);
}
// 把body转换为一个类似于JQuery的对象
let $ = cheerio.load(body, {
decodeEntities: false // 把内容的编码设置一下
});
// 获取博客的内容信息
let html = $('.articalContent').html();
let content = (html === null ? html : html.toString().trim());
callback(null, content);
})
}
// 获取所有的文章列表信息
/**
* 这是一个函数调用,用于获取文章列表之后所执行的一系列操作
*/
getArticleList(url, function (err, articleList) {
if (err) {
throw new Error('error');
}
//console.log(articleList);
articleList.forEach(function (item, index) {
let url = item.url;
// 根据博客的URL信息偶去博客的内容信息
// 获取信息这实际上是一个异步信息,会直接把这么多的信息加入到事件队列中区
getDetailByUrl(url, function (err, detail) {
if (err) {
return console.log(err, url);
}
// 获取到数据之后保存信息到本地
// 【注意事项: 在Nodejs中向一个文件中写入数据的时候必须保证这个文件夹路径存在,否则会报错!】
let filePath = path.join(__dirname, 'data', item.title.toString().trim() + '.html');
// 使用 replace的方式来设置模板中的内容信息
detail = templateStr.toString().replace('<%content%>' , detail);
fs.writeFile(filePath, detail, (err) => {
if (err) {
return console.log(filePath + '文件保存失败!')
}
console.log(`文件: ${filePath} 保存成功!`);
});
})
});
})
实现思路剖析:
1.可以通过新浪博客的内容看到这个上面抓取的网址,一页基本上有20篇文章左右,关键就用到了那个cheerio工具包,当然你也可以使用原生的JavaScript和正则表达式进行操作
2.实现原理:首先使用request获取请求的url,得到网址的源码,然后使用cheerio将源码解析成为一个JQuery对象,然后使用JQuery直接操作DOM元素解析文章内容
3.关键点:有于当前测试的是一页的博客抓取,对于多页的博客,使用递归的方式进行抓取,主要是通过判断当前博客是不是有下一页的链接,有的话就进行递归,没有的话就停止(递归条件)
4.其他:其他涉及到的就是一些node.js文件的基本读写操作,熟悉的朋友应该都看的懂
评论
填写昵称与邮箱即可评论,无需登录。