使用 node 爬取数据并导出到 excel
1. 为什么要导出为excel
2. 依赖
3. 具体实现
文件结构
├── config.js # 配置数据分隔符、存储文件名
├── index.js # 发起请求,处理文档,存储内容
└── save.js # 转存文本内容到excel配置项
爬取请求
转存为excel
4. 改进
Last updated
├── config.js # 配置数据分隔符、存储文件名
├── index.js # 发起请求,处理文档,存储内容
└── save.js # 转存文本内容到excelLast updated
module.exports = {
// 如果将分隔符定义为空格,有可能错误的截取爬取到的数据
// 且分隔符要避免使用正则表达式中需要转义的字符
separator: ';;;',
rawDataFileName: 'output/data.txt',
saveFileName: 'output/out.xlsx'
};// 引入依赖
var request = require('request');
var cheerio = require('cheerio');
var fs = require('fs');
var path = require('path');
var config = require('./config.js');
// 请求配置项
const pageSize = 10; // 爬取多个列表页,一共爬取10页
let counter = 0; // 成功爬取的数据计数
let options = {
method: 'GET',
url: 'http://bbs.cnhubei.com/forum.php', // 主机地址
qs: { mod: 'guide', view: 'my', type: 'thread' }, // 请求字符串
headers: {
'cache-control': 'no-cache',
cookie: '*******'
},
};
// 发起请求
function fetchData(cb, page) {
let finalOptions = Object.assign({}, options);
Object.assign(finalOptions.qs, { page });
request(options, (err, res, body) => {
if (err) throw err;
// 请求到文档内容后开始提取内容
extractDocument(body, cb);
});
}
// 内容抽取
function extractDocument(body, cb) {
// 调用cheerio.load方法载入文档,转化为可操作的DOM文档
const $ = cheerio.load(body);
// 根据文档结构进行节点查询
$('#threadlist .bm_c table tbody').each(function (i, el) {
let title = $(this).find('tr .common a').text();
let pageView = $(this).find('tr .num em').text();
let createTime = $(this).find('tr .by').last().find('em a').text();
if (title && pageView && createTime) {
counter++;
cb({ title, pageView, createTime }, counter);
}
});
}
// 将数据保存到本地
function writeFile(data, index) {
// 拼接爬取到的数据
data = Object.keys(data).map(key => data[key]).join(config.separator) + '\n';
let fileRoute = path.resolve(__dirname, config.rawDataFileName);
// 使用node将数据储存到本地,使用appendFile逐条追加
fs.appendFile(fileRoute, data, 'utf-8', (err) => {
console.log(`已读取:${index}`);
});
}
// start
for (let page = 1; page <= pageSize; page++) {
fetchData(writeFile, page);
}var path = require('path');
var fs = require('fs');
var xlsx = require('node-xlsx');
var config = require('./config.js');
let fileRoute = path.resolve(__dirname, config.rawDataFileName);
let fileName = path.resolve(__dirname, config.saveFileName);
// 定义导出配置项
let exportData = {
name: '荆楚网阅读数据',
data: [
['标题', '阅读数', '发布时间'] // 第一行数据,分别对应A1 B1 C1的table cell的内容,即单元格标题
]
};
// 转存文本
function saveFile(data) {
// 剔除无效数据
data = data.split(/\n/).filter(r => !!r);
// 将文本转换为符合要求的数组对象
var seperatorPtn = new RegExp(config.separator, 'g');
data = data.map(r => {
var rst = r.split(seperatorPtn);
rst[1] = parseInt(rst[1]); // 将每行数据的第1项转化为Number类型
return rst;
});
exportData.data = exportData.data.concat(data);
// 转存数据
var buffer = xlsx.build([exportData]); // Returns a buffer
fs.writeFile(fileName, buffer, (err) => {
if (err) throw err;
console.log('保存成功');
});
}
// start
// 读取文本内容并开始转存
fs.readFile(fileRoute, 'utf-8', (err, data) => {
if (err) throw err;
saveFile(data);
});