好好学习,认真工作

基于nodeJS的小说爬虫实战

背景与需求分析

最近迷恋于王者荣耀、斗鱼直播与B站吃播视频,中毒太深,下班之后无心看书。

为了摆脱现状,能习惯看书,我开始看小说了,然而小说网站广告多而烦,屌丝心态不愿充钱,于是想到了爬虫。

功能分析

为了将网上小说内容获取到本地,进行了功能分析:

1、获取每个章节列表地址
2、更加每个章节地址,获取每个章节的内容
3、将获取的各个章节内容有序的写入文件

技术调研

作为一个前端er,实现爬虫nodeJS必须是首选,虽然数据挖掘Python才是真理

npm依赖如下

1、爬取内容 superagent
2、分析爬取的内容 cheerio
3、并发 async
4、文件写入 fs

编码实现

xiaoshuo.js代码如下

const cheerio = require('cheerio')
const superagent = require('superagent')
require('superagent-charset')(superagent)
const async = require('async');
const fs = require('fs');



let baseUrl = 'http://www.xxx.com/book/14435/';
let infos = [];
let urls = [];
let titles = [];
let fileName = '';
superagent.get(baseUrl).charset('UTF-8').end((err,res)=>{
    var $ = cheerio.load(res.text); 
    // 读取章节列表页面
    $('.am-book-list').eq(1).find('.am-u-lg-4 a').each((i, v) => {
        let link = 'http://www.xxx.com' + $(v).attr('href')
        urls.push(link);
        fileName = $('.am-book-info h2').text()+'.txt';
    })
    let id = 0;
    //获取每个章节列表
    async.mapLimit(urls,urls.length,(url,callback)=>{
        id++
        fetchUrl(url,callback,id);
    },(err,results)=>{
        //将文件写入本地
        fs.existsSync(fileName);
        for(var i = 0;i<results.length-1;i++){
            fs.appendFileSync(fileName, results[i].title) //
            fs.appendFileSync(fileName, results[i].content)
        }

    })
})

function fetchUrl(url,callback,id){
    superagent.get(url)
        .charset('UTF-8')
        .end(function(err,res){
            let $ = cheerio.load(res.text);
            let arr = []
            let content = reconvert($("#am-read-centent").text())
            const obj = {
                id: id,
                err: 0,
                title: '\n'+$('#am-book-h3').text(), //标题
                content: '\n'+trim(content.toString()) //内容
            }
            callback(null,obj)
        })
}
function reconvert(str) {
  str = str.replace(/(&#x)(\w{1,4});/gi, function ($0) {
    return String.fromCharCode(parseInt(escape($0).replace(/(%26%23x)(\w{1,4})(%3B)/g, "$2"), 16));
  });
  return str
}
function trim(str){
  return str.replace(/(^\s*)|(\s*$)/g, '').replace(/&nbsp;/g, '')
}

为了避免坐牢,站点使用xxx代替,

运行效果

在命令行运行 node xiaoshuo,试验了本小说,好像还是ok的,哈哈哈

 

posted on 2019-06-18 11:31  peace_1  阅读(455)  评论(0编辑  收藏  举报