[JavaScript] 纯文本查看 复制代码
"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} 保存成功!`);
});
})
});
})
[/size][size=4]