刘贵学博客

Node爬虫:使用爬虫下载小说txt

1. 缘起

浏览微博时被一个小说片段勾起了兴趣,如果要继续看,必须加某个微信公众号,回复关键字等,哎,都是套路啊,这种营销方法侮辱智商,阅读体验也非常差。

在百度中搜索小说的开头一句,可以找到一些资源,但是没有txt或epub格式,很多在线小说阅读有广告,没有适配手机端,反正阅读体验也不好。

怎样提高读小说的体验呢?本文将尝试解决这个问题。

其实手机或平板上读书的很多app体验是不错的,比如多看。假如我们可以将小说转成txt传到 多看里,体验问题就可以解决了。

如何获得txt版本的小说呢?江湖盛传三种绝技:
1 最直接的方法:下载。通过云盘、文库、小说站点等直接下载txt的小说格式,这个主要看运气。
2 最笨的方法:复制粘贴。从小说网,打开每个链接复制粘贴到txt文本中,保存可得,现在网络小说章节动不动就几百上千章,能坚持下来用这个方法操作的,毅力肯定不错,当然也傻的可以。
3 真正必杀绝技:使用脚本自动爬取,这个才靠技术。

2. 解决方案

2.1 业务分析

网络小说由多个章节组成,通常每个章节一个页面,如下图:

所以我们的爬虫逻辑分四步:

  1. 获取目录网页
  2. 解析目录网页,获取章节列表
  3. 下载所有章节页面
  4. 解析章节页面,抽取信息合成 txt

2.2 技术分析

实现业务涉及的技术点如下:

  • 获取某个网页内容,这个可以使用 node-fetch 库

    const response = await fetch(url)
    const content = await response.text()
    
  • 编码转换,js中只处理utf8的中文,小说网通常为gbk

    const buff = await response.buffer()
    // 要将GBK 编码转换为 UTF-8
    const iconv = new Iconv('GBK', 'UTF-8//TRANSLIT//IGNORE');
    let str = iconv.convert(buff).toString()
    
    // 将网页中的编码gbk 改为UTF-8
    str = str.replace('charset=gbk','charset=UTF-8')
    
  • 使用async库 并发爬取,如:每次获取10个

    const ASYNC = require("async");
    ASYNC.mapLimit(LIST,10, async (item) => {
        fetchPage(item)
    }, (err, results) => {
        if (err) {
            console.log('error', err)
        }
    });
    
  • 抽取网页信息 cheerio + 正则表达式

    const cheerio = require('cheerio')
    
    const $ = cheerio.load(html);
    let content = $('#content').text()
    
    // 去除行首多余空格、空行
    content = content.replace(/\n\s+/g, "\n");
    

3. 代码实现

请参考: https://coding.net/u/guixue/p/novel2txt/git/tree/level1?public=true

4. 使用方法与效果预览

4.1 下载目录页面

npm run fetch.index

将目录页面保存到 data/index.html

4.2 解析章节列表

npm run parse.index

章节目录列表为json格式,一个大数组,包含标题和链接。

4.3 下载所有章节页面

npm run fetch.list  

将所有的章节html下载到本地 data目录下:

4.4 解析章节页面合成txt文件

npm run parse.chapter   

解析每个章节的html文件后,产生一个2.8m的 data/all.txt,妥了。

将此txt文件通过QQ 或微信发送到移动设备,右上角选择【用其他应用打开】,选择多看或其他阅读器即可。

  • 效果预览,可以自动生成目录

img_0002

  • 效果预览,阅读效果:

img_0003

5. 免责声明

本文以技术学习为目的,如侵犯了您的权益,请来信告知: guixue@outlook.com