Node.js 实现简单小说爬虫实例

最近因为剧荒,老大追了爱奇艺的一部网剧,由丁墨的同名小说《美人为馅》改编,目前已经放出两季,虽然整部剧槽点满满,但是老大看得不亦乐乎,并且在看完第二季之后跟我要小说资源,直接要奔原著去看结局……

随手搜了下,都是在线资源,下载的话需要登录注册登录好麻烦,写个爬虫玩玩也好,于是动手用 node 写了一个,这里做下笔记

工作流程

  • 获取 URLs 列表(请求资源 ottom: 2px; padding-top: 2px; padding-left: 4px; padding-right: 4px; background-color: rgb(249,242,244)">request模块)
  • 根据 URLs 列表获取相关页面源码(可能遇到页面编码问题,模块)
  • 源码解析,获取小说信息( 模块)
  • 保存小说信息到 Markdown 文件,并且加适当修饰以及章节信息(写文件、同步请求资源 模块)
  • Markdown 转 PDF (使用 Pandoc 或者 Chrome 的打印功能)

获取 URLs

根据小说的导航页,获取小说所有章节的 URL,并且以 JSON 数组的方式存储。

  • 首选通过 方法获取页面源码
  • 获取到源码,打印发现中文乱码,查看发现 ,需要进行转码
  • 使用模块进行转码,中文显示正常后开始解析源码,获取需要的 URL,为了更方便地解析,需要引进 模块,可以理解为运行在后台的 jQuery,用法与 jQuery 也十分相似,熟悉 jQuery 的同学可以很快的上手
  • 将源码加载进 ,分析了源码后得知所有章节信息都存于被 包裹的标签中,通过 取出符合条件的 标签组,进行遍历,获取章节的 title 和 URL,保存为对象,存进数组,(因为链接中存储的 URL 不完整,所以存储时需要补齐)
  • 将对象数组序列化,写进 文件
5) { links.push(link) } }) fs.writeFile("list.json",JSON.stringify(links),function(err) { if (!err) { console.log("写文件成功") } }) }).on('error',function() { console.log("网页访问出错") }) })

获取的列表示例

rush:js;"> [{ "title": "3 法医司白","link": "http://www.17fa.com/files/article/html/90/90747/16548771.html" },{ "title": "4 第1个梦 ","link": "http://www.17fa.com/files/article/html/90/90747/16548772.html" },{ "title": "5 刑警韩沉 ","link": "http://www.17fa.com/files/article/html/90/90747/16548773.html" },{ "title": "6 最初之战","link": "http://www.17fa.com/files/article/html/90/90747/16548774.html " }]

获取数据

有了 URLs 列表,接下来的工作就很机械了,遍历 URLs 列表请求资源,获取源码,解析源码,获取小说,写文件,但是,因为最终将所有的章节保存入一个文件,要保证章节的顺序,因此写文件需要 同步操作,实际上,我在编码的时候所有的操作都改成了同步方式

获取源码

通过解析读取的文件获取到 URLs 列表,遍历列表获取资源,因为需要确保章节的顺序,所以这里引进 模块进行同步 request 请求资源,请求资源后照例转码

rush:java;"> var http = require("http") var fs = require("fs") var cheerio = require("cheerio") var iconv = require("iconv-lite") var request = require('sync-request') var urlList = JSON.parse(fs.readFileSync('list.json','utf8')) function getContent(chapter) { var res = request('GET',chapter.link) var html = iconv.decode(res.body,'gb2312') //获取源码 } for (let i = 0; i < urlList.length; i++) { getContent(urlList[i]) }

解析源码,获取小说

还是通过 模块获取小说内容,避免影响观感,写操作之前去除内容中的的 html 标签

rush:js;"> function getContent(chapter) { var res = request('GET','gb2312') var $ = cheerio.load(html,{ decodeEntities: false }) var content = ($("div#r1c").text()).replace(/\/g,'') }

保存小说

写操作也需要同步操作,因此使用了同步写函数 和 同步添加函数 ,第一次写使用写函数,之后的内容都是进行 append 操作,为了改善阅读体验,每个章节前添加标题

也可以在内容添加 拍 [TOC],作为导航链接

rush:js;"> var http = require("http") var fs = require("fs") var cheerio = require("cheerio") var iconv = require("iconv-lite") var path = require('path') var urlList = JSON.parse(fs.readFileSync('list.json','utf8')) function getContent(chapter) { console.log(chapter.link) http.get(chapter.link,function(res) { var chunks = [] res.on('data',function(chunk) { chunks.push(chunk) }) res.on('end',function() { var html = iconv.decode(Buffer.concat(chunks),'gb2312') var $ = cheerio.load(html,{ decodeEntities: false }) var content = ($("div#r1c").text()).replace(/\/g,'') if (fs.existsSync('美人为馅.md')) { fs.appendFileSync('美人为馅.md','### ' + chapter.title) fs.appendFileSync('美人为馅.md',content) } else { fs.writeFileSync('美人为馅.md',content) } }) }).on('error',function() { console.log("爬取" + chapter.link + "链接出错!") }) } for (let i = 0; i < urlList.length; i++) { console.log(urlList[i]) getContent(urlList[i]) }

Markdown 转 PDF

我将小说保存在 Markdown 文件中,为了提升阅读体验,可以将 Markdown 文件转换成 PDF 文件,目前我较为喜欢的两种方式,通过 Chrome 的打印功能 以及 pandoc 转换

Chrome 打印

SublimeText 有个插件,可通过 快捷键在 Chrome 中预览 Markdown,在 Chrome 页面中右键,选择打印,调整好参数后,选择另存为 PDF,简单,粗暴,深得我心

打印效果

pandoc 转换

pandoc 是十分强大的文件格式转换工具,可以将 Markdown 文件转换成多种格式,今晚在 windows10 下折腾了半天,始终检索不到 pdflatex,关于 pandoc,后面会专门写一篇总结。

PDF 已经发给老大了,现在正在看

关于python、node、爬虫

在之前很长的一段时间里,很想用 Python,很想写爬虫,更想用 Python 写爬虫,甚至成为了心里的一块执念,随着接触的知识更全面,执念也逐渐淡去,少了很多“想”,遇事想着多去动手,实践出真知。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程之家。

相关文章

这篇文章主要介绍“基于nodejs的ssh2怎么实现自动化部署”的...
本文小编为大家详细介绍“nodejs怎么实现目录不存在自动创建...
这篇“如何把nodejs数据传到前端”文章的知识点大部分人都不...
本文小编为大家详细介绍“nodejs如何实现定时删除文件”,内...
这篇文章主要讲解了“nodejs安装模块卡住不动怎么解决”,文...
今天小编给大家分享一下如何检测nodejs有没有安装成功的相关...