最近因為劇荒,老大追了愛奇藝的一部網劇,由丁墨的同名小說《美人為餡》改編,目前已經放出兩季,雖然整部劇槽點滿滿,但是老大看得不亦樂乎,並且在看完第二季之後跟我要小說資源,直接要奔原著去看結局……
隨手搜了下,都是在線資源,下載的話需要登錄,註冊登錄好麻煩,寫個爬蟲玩玩也好,於是動手用node 寫了一個,這裡做下筆記
工作流程
獲取URLs 列表(請求資源 request模組)
根據URLs 列表獲取相關頁面源碼(可能遇到相關頁源(頁面編碼問題,iconv-lite模組)
源碼解析,獲取小說資訊( cheerio模組)
保存小說資訊到Markdown 文件,並且加適當修飾以及章節資訊(寫文件fs、同步請求資源 sync-request 模組)
Markdown 轉PDF (使用Pandoc 或Chrome 的列印功能)
取得URLs
根據小說的導航頁,取得小說所有章節的URL,並以JSON 陣列的方式儲存。
首選透過 http.get() 方法取得頁面原始碼
取得到原始碼,列印發現中文亂碼,檢視發現 charset = 'gbk',需要進行轉碼
使用iconv-lite 模組進行轉碼,中文顯示正常顯示後來開始解析源碼,取得所需的URL,為了更方便地解析,需要引進 cheerio 模組,cheerio 可以理解為運行在後台的jQuery,用法與jQuery 也十分相似,熟悉jQuery 的同學可以很快的上手
將原始碼載入進 cheerio,分析了原始碼後得知所有章節資訊都存於被div 包裹的a 標籤中,透過 cheerio 取出符合條件的 a 標籤組,進行遍歷,取得章節的title 和URL,儲存為對象,存進數組,(因為連結中儲存的URL 不完整,所以儲存時需要補齊)
將物件陣列序列化,寫進 list.json 檔案
var http = require("http") var fs = require("fs") var cheerio = require("cheerio") var iconv = require("iconv-lite") var url = 'http://www.17fa.com/files/article/html/90/90747/index.html' http.get(url, 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 = $("tbody") var links = [] $('div').children('a').each(function(i, elem) { var link = new Object() link.title = $(this).text() link.link = 'http://www.17fa.com/files/article/html/90/90747/' + $(this).attr('href') //补齐 URL 信息 if (i > 5) { links.push(link) } }) fs.writeFile("list.json", JSON.stringify(links), function(err) { if (!err) { console.log("写文件成功") } }) }).on('error', function() { console.log("网页访问出错") }) })
獲取數據
有了URLs 列表,接下來的工作就很機械了,遍歷URLs 列表請求資源,獲取源碼,解析源碼,獲取小說,寫文件,但是,因為最終將所有的章節保存入一個文件,要確保章節的順序,因此寫文件需要同步操作,實際上,我在編碼的時候所有的操作都改成了同步方式獲取源碼[{ "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 " }]
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]) }
也可以在內容前添加拍[TOC],作為導航連結
function getContent(chapter) { var res = request('GET',chapter.link) var html = iconv.decode(res.body, 'gb2312') var $ = cheerio.load(html, { decodeEntities: false }) var content = ($("div#r1c").text()).replace(/\ /g, '') }
我將小說保存在Markdown 文件中,為了提升閱讀體驗,可以將Markdown 文件轉換成PDF 文件,目前我較為喜歡的兩種方式,透過Chrome 的列印功能以及pandoc 轉換
Chrome 列印
SublimeText 有個插件markdown preview ,可透過Alt + m 快鍵在Chrome 中預覽Markdown,在Chrome 頁面中按鍵選擇另存為PDF,簡單,粗暴,深得我心
打印效果:
pandoc 轉換
pandoc 是十分強大的文件格式轉換工具,可以將Markdown 文件轉換成多種格式,今晚在windows10下折騰了半天,總是檢索不到pdflatex,關於pandoc,後面會特別寫一篇總結。
PDF 已經發給老大了,現在正在看
關於python、node、爬蟲
在之前很長的一段時間裡,很想用Python,很想寫爬蟲,更想用Python 寫爬蟲,甚至成為了心裡的一塊執念,隨著接觸的知識更全面,執念也逐漸淡去,少了很多“想”,遇事想著多去動手,實踐出真知。