最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Node.js 實(shí)現(xiàn)簡(jiǎn)單小說爬蟲實(shí)例

 更新時(shí)間:2016年11月18日 13:06:37   作者:leeonway  
現(xiàn)在爬蟲在很多web項(xiàng)目中都有應(yīng)用,這篇文章主要介紹了Node.js 實(shí)現(xiàn)簡(jiǎn)單小說爬蟲實(shí)例,有興趣的可以了解一下。

最近因?yàn)閯』模洗笞妨藧燮嫠嚨囊徊烤W(wǎng)劇,由丁墨的同名小說《美人為餡》改編,目前已經(jīng)放出兩季,雖然整部劇槽點(diǎn)滿滿,但是老大看得不亦樂乎,并且在看完第二季之后跟我要小說資源,直接要奔原著去看結(jié)局……

隨手搜了下,都是在線資源,下載的話需要登錄,注冊(cè)登錄好麻煩,寫個(gè)爬蟲玩玩也好,于是動(dòng)手用 node 寫了一個(gè),這里做下筆記

工作流程

  • 獲取 URLs 列表(請(qǐng)求資源 request模塊)
  • 根據(jù) URLs 列表獲取相關(guān)頁面源碼(可能遇到頁面編碼問題,iconv-lite模塊)
  • 源碼解析,獲取小說信息( cheerio模塊)
  • 保存小說信息到 Markdown 文件,并且加適當(dāng)修飾以及章節(jié)信息(寫文件 fs、同步請(qǐng)求資源 sync-request 模塊)
  • Markdown 轉(zhuǎn) PDF (使用 Pandoc 或者 Chrome 的打印功能)

獲取 URLs

根據(jù)小說的導(dǎo)航頁,獲取小說所有章節(jié)的 URL,并且以 JSON 數(shù)組的方式存儲(chǔ)。

  • 首選通過 http.get() 方法獲取頁面源碼
  • 獲取到源碼,打印發(fā)現(xiàn)中文亂碼,查看發(fā)現(xiàn) charset = 'gbk',需要進(jìn)行轉(zhuǎn)碼
  • 使用 iconv-lite 模塊進(jìn)行轉(zhuǎn)碼,中文顯示正常后開始解析源碼,獲取需要的 URL,為了更方便地解析,需要引進(jìn) cheerio 模塊,cheerio 可以理解為運(yùn)行在后臺(tái)的 jQuery,用法與 jQuery 也十分相似,熟悉 jQuery 的同學(xué)可以很快的上手
  • 將源碼加載進(jìn) cheerio,分析了源碼后得知所有章節(jié)信息都存于被 div 包裹的 a 標(biāo)簽中,通過 cheerio 取出符合條件的 a 標(biāo)簽組,進(jìn)行遍歷,獲取章節(jié)的 title 和 URL,保存為對(duì)象,存進(jìn)數(shù)組,(因?yàn)殒溄又写鎯?chǔ)的 URL 不完整,所以存儲(chǔ)時(shí)需要補(bǔ)齊)
  • 將對(duì)象數(shù)組序列化,寫進(jìn) 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) { //資源請(qǐng)求
  var chunks = []
  res.on('data', function(chunk) {
    chunks.push(chunk)
  })
  res.on('end', function() {
    var html = iconv.decode(Buffer.concat(chunks), 'gb2312') //轉(zhuǎn)碼操作
    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') //補(bǔ)齊 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("網(wǎng)頁訪問出錯(cuò)")
  })
})

獲取的列表示例

[{
  "title": "3 法醫(yī)司白",
  "link": "http://www.17fa.com/files/article/html/90/90747/16548771.html"
}, {
  "title": "4 第1個(gè)夢(mèng) ",
  "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 最初之戰(zhàn)",
  "link": "http://www.17fa.com/files/article/html/90/90747/16548774.html "
}]

獲取數(shù)據(jù)

有了 URLs 列表,接下來的工作就很機(jī)械了,遍歷 URLs 列表請(qǐng)求資源,獲取源碼,解析源碼,獲取小說,寫文件,但是,因?yàn)樽罱K將所有的章節(jié)保存入一個(gè)文件,要保證章節(jié)的順序,因此寫文件需要 同步操作,實(shí)際上,我在編碼的時(shí)候所有的操作都改成了同步方式

獲取源碼

通過解析讀取的 list.json 文件,獲取到 URLs 列表,遍歷列表獲取資源,因?yàn)樾枰_保章節(jié)的順序,所以這里引進(jìn) sync-request 模塊進(jìn)行同步 request 請(qǐng)求資源,請(qǐng)求資源后照例轉(zhuǎn)碼

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])
}

解析源碼,獲取小說

還是通過 cheerio 模塊獲取小說內(nèi)容,避免影響觀感,寫操作之前去除內(nèi)容中的的 html 標(biāo)簽

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(/\&nbsp;/g, '')
}

保存小說

寫操作也需要同步操作,因此使用了同步寫函數(shù) fs.writeFileSync() 和 同步添加函數(shù) fs.appendFileSync(),第一次寫使用寫函數(shù),之后的內(nèi)容都是進(jìn)行 append 操作,為了改善閱讀體驗(yàn),每個(gè)章節(jié)前添加標(biāo)題

也可以在內(nèi)容前添加 拍 [TOC],作為導(dǎo)航鏈接

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(/\&nbsp;/g, '')
      if (fs.existsSync('美人為餡.md')) {
        fs.appendFileSync('美人為餡.md', '### ' + chapter.title)
        fs.appendFileSync('美人為餡.md', content)
      } else {
        fs.writeFileSync('美人為餡.md', '### ' + chapter.title)
        fs.appendFileSync('美人為餡.md', content)
      }
    })
  }).on('error', function() {
    console.log("爬取" + chapter.link + "鏈接出錯(cuò)!")
  })
}
for (let i = 0; i < urlList.length; i++) {
  console.log(urlList[i])
  getContent(urlList[i])
}

Markdown 轉(zhuǎn) PDF

我將小說保存在 Markdown 文件中,為了提升閱讀體驗(yàn),可以將 Markdown 文件轉(zhuǎn)換成 PDF 文件,目前我較為喜歡的兩種方式,通過 Chrome 的打印功能 以及 pandoc 轉(zhuǎn)換

Chrome 打印

SublimeText 有個(gè)插件 markdown preview ,可通過 Alt + m 快捷鍵在 Chrome 中預(yù)覽 Markdown,在 Chrome 頁面中右鍵,選擇打印,調(diào)整好參數(shù)后,選擇另存為 PDF,簡(jiǎn)單,粗暴,深得我心

打印效果:

pandoc 轉(zhuǎn)換
pandoc 是十分強(qiáng)大的文件格式轉(zhuǎn)換工具,可以將 Markdown 文件轉(zhuǎn)換成多種格式,今晚在 windows10 下折騰了半天,始終檢索不到 pdflatex,關(guān)于 pandoc,后面會(huì)專門寫一篇總結(jié)。

PDF 已經(jīng)發(fā)給老大了,現(xiàn)在正在看

關(guān)于python、node、爬蟲

在之前很長(zhǎng)的一段時(shí)間里,很想用 Python,很想寫爬蟲,更想用 Python 寫爬蟲,甚至成為了心里的一塊執(zhí)念,隨著接觸的知識(shí)更全面,執(zhí)念也逐漸淡去,少了很多“想”,遇事想著多去動(dòng)手,實(shí)踐出真知。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • 利用Node.js手寫一個(gè)簡(jiǎn)單的koa

    利用Node.js手寫一個(gè)簡(jiǎn)單的koa

    這篇文章主要為大家詳細(xì)介紹了如何手動(dòng)寫一個(gè)簡(jiǎn)單的koa,通過這個(gè)流程就可以較好的掌握koa2中的基本概念,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2024-01-01
  • 詳解webpack打包nodejs項(xiàng)目(前端代碼)

    詳解webpack打包nodejs項(xiàng)目(前端代碼)

    這篇文章主要介紹了webpack打包nodejs項(xiàng)目(前端代碼),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-09-09
  • npm?install?XXX安裝路徑文件夾權(quán)限問題的解決過程

    npm?install?XXX安裝路徑文件夾權(quán)限問題的解決過程

    這篇文章主要給大家介紹了關(guān)于npm?install?XXX安裝路徑文件夾權(quán)限問題(npm?ERR!?The?operation?was?rejected?by?your?operating?system.errno?-4080)的解決過程,文中通過圖文介紹的非常詳細(xì),需要的朋友可以參考下
    2023-04-04
  • 詳解基于node的前端項(xiàng)目編譯時(shí)內(nèi)存溢出問題

    詳解基于node的前端項(xiàng)目編譯時(shí)內(nèi)存溢出問題

    本篇文章主要介紹了基于node的前端項(xiàng)目編譯時(shí)內(nèi)存溢出問題,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-08-08
  • nodejs判斷文件、文件夾是否存在及刪除的方法

    nodejs判斷文件、文件夾是否存在及刪除的方法

    這篇文章主要介紹了nodejs判斷文件、文件夾是否存在及刪除的方法,結(jié)合實(shí)例形式分析了nodejs基于文件模塊針對(duì)文件與文件夾的存在判斷、刪除等操作技巧,需要的朋友可以參考下
    2017-11-11
  • Node.js實(shí)現(xiàn)在目錄中查找某個(gè)字符串及所在文件

    Node.js實(shí)現(xiàn)在目錄中查找某個(gè)字符串及所在文件

    這篇文章主要介紹了Node.js實(shí)現(xiàn)在目錄中查找某個(gè)字符串及所在文件,文中代碼簡(jiǎn)潔,而且速度相當(dāng)?shù)目?需要的朋友可以參考下
    2014-09-09
  • node.js實(shí)現(xiàn)微信開發(fā)之獲取用戶授權(quán)

    node.js實(shí)現(xiàn)微信開發(fā)之獲取用戶授權(quán)

    這篇文章主要介紹了node.js實(shí)現(xiàn)微信開發(fā)之獲取用戶授權(quán),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-03-03
  • nvm查看所有node包命令失效原因解決方案

    nvm查看所有node包命令失效原因解決方案

    使用nvm時(shí)可能會(huì)遇到超時(shí)問題,這是由于node的包存放在國外服務(wù)器上,解決方法是在nvm的配置文件中添加鏡像地址,下面就來具體介紹一下步驟,感興趣的可以了解一下
    2024-09-09
  • Node發(fā)出HTTP POST請(qǐng)求的方法實(shí)例小結(jié)

    Node發(fā)出HTTP POST請(qǐng)求的方法實(shí)例小結(jié)

    這篇文章主要介紹了Node發(fā)出HTTP POST請(qǐng)求的方法,結(jié)合實(shí)例形式總結(jié)分析了三種常用的post請(qǐng)求操作方法,以及相關(guān)庫操作注意事項(xiàng),需要的朋友可以參考下
    2023-05-05
  • nodejs 最新版安裝npm 的使用詳解

    nodejs 最新版安裝npm 的使用詳解

    本篇文章主要介紹了nodejs 最新版安裝npm 的使用詳解,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-01-01

最新評(píng)論

青河县| 沧州市| 类乌齐县| 南昌县| 比如县| 浏阳市| 当涂县| 花莲县| 金坛市| 璧山县| 丰都县| 洛扎县| 饶阳县| 广宗县| 长治市| 宁化县| 白玉县| 和平县| 垦利县| 栾川县| 乾安县| 阳泉市| 蓬溪县| 泸州市| 池州市| 东丰县| 得荣县| 双鸭山市| 林甸县| 安图县| 阿勒泰市| 六安市| 普洱| 固始县| 屏东市| 洞口县| 宁陵县| 松原市| 永兴县| 施甸县| 禹州市|