日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

NodeJs ES6 写简单爬虫 爬小说网站《我当方士那些年》

發(fā)布時(shí)間:2024/1/8 编程问答 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 NodeJs ES6 写简单爬虫 爬小说网站《我当方士那些年》 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

個(gè)人網(wǎng)站地址 www.wenghaoping.com

Vue + express + Mongodb構(gòu)建 請(qǐng)大家多支持一下。

先上代碼,然后在慢慢逼逼

Git地址,有需要的Clone

==先從小說(shuō)網(wǎng)站開始練手,然后爬電影網(wǎng)站,可以下最新的電影,這是我的需求。哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈==

演示:

大致流程

1 獲取 URLs 列表(請(qǐng)求資源 http模塊) 2 根據(jù) URLs 列表獲取相關(guān)頁(yè)面源碼(可能遇到頁(yè)面編碼問(wèn)題,iconv-lite 模塊) 3 源碼解析,獲取小說(shuō)信息( cheerio 模塊) 4 保存小說(shuō)信息到 txt 文件,并且加適當(dāng)修飾以及章節(jié)信息(寫文件 fs)

具體

根據(jù)小說(shuō)的導(dǎo)航頁(yè),獲取到當(dāng)前章節(jié),然后獲取鏈接

首選通過(guò) http.get() 方法獲取頁(yè)面源碼 獲取到源碼,打印發(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é)可以很快的上手

// 請(qǐng)求標(biāo)題 let titleRequest = (url) => {return new Promise((resolve, reject) => {//采用http模塊向服務(wù)器發(fā)起一次get請(qǐng)求http.get(url, function (res) {let html = ''; //用來(lái)存儲(chǔ)請(qǐng)求網(wǎng)頁(yè)的整個(gè)html內(nèi)容//監(jiān)聽data事件,每次取一塊數(shù)據(jù)res.on('data', function (chunk) {html += iconv.decode(chunk, 'GBK');});//監(jiān)聽end事件,如果整個(gè)網(wǎng)頁(yè)內(nèi)容的html都獲取完畢,就執(zhí)行回調(diào)函數(shù)res.on('end', function () {let $ = cheerio.load(html); //采用cheerio模塊解析html// 總的長(zhǎng)度endNumber = $('#list a').length;let title = $('#list a').eq(number).text();let mainUrl = baseUrl + $('#list a').eq(number).attr('href');let item = {// 小說(shuō)標(biāo)題title: title,// 小說(shuō)詳情mainUrl: mainUrl,//i是用來(lái)判斷獲取了多少篇文章i: number}// console.log(item); //打印新聞信息resolve(item);});}).on('error', function (err) {console.log(err);reject(err);});}); };復(fù)制代碼

將源碼加載進(jìn) cheerio,分析了源碼后得知所有章節(jié)信息都存于被 div 包裹的 a 標(biāo)簽中,通過(guò) cheerio 取出符合條件的 a 標(biāo)簽組,進(jìn)行遍歷,獲取章節(jié)的 title 和 URL,保存為對(duì)象,存進(jìn)數(shù)組,(因?yàn)殒溄又写鎯?chǔ)的 URL 不完整,所以存儲(chǔ)時(shí)需要補(bǔ)齊) 然后在寫一個(gè)獲取詳情的爬蟲

// 請(qǐng)求內(nèi)容 let mainRequest = (mainUrl) => {return new Promise((resolve, reject) => {//采用http模塊向服務(wù)器發(fā)起一次get請(qǐng)求http.get(mainUrl, function (res) {let html = ''; //用來(lái)存儲(chǔ)請(qǐng)求網(wǎng)頁(yè)的整個(gè)html內(nèi)容//監(jiān)聽data事件,每次取一塊數(shù)據(jù)res.on('data', function (chunk) {html += iconv.decode(chunk, 'GBK');});//監(jiān)聽end事件,如果整個(gè)網(wǎng)頁(yè)內(nèi)容的html都獲取完畢,就執(zhí)行回調(diào)函數(shù)res.on('end', function () {let $ = cheerio.load(html); //采用cheerio模塊解析htmllet detail = $('#content').text().replace(/\s+/g,"\r\n\r\n    ");// console.log(detail); // 打印詳情resolve(detail);});}).on('error', function (err) {console.log(err);reject(err);});}); } 復(fù)制代碼

下面是所有代碼

const http = require('http'); const fs = require('fs'); const cheerio = require('cheerio'); const iconv = require('iconv-lite'); let baseUrl='http://www.biquge.com.tw';// 筆趣閣公共地址 let url='http://www.biquge.com.tw/3_3142/';// 筆趣閣 《我當(dāng)方士那些年》 首頁(yè) ===== 要變小說(shuō),只需要更改此處地址就可以 let urlOne = 'http://www.biquge.com.tw/3_3142/1788029.html'; // 筆趣閣 《我當(dāng)方士那些年》 第一章地址 測(cè)試用 let number = 0; // 請(qǐng)求次數(shù) let endNumber = 0; // 總數(shù) 或者可以控制爬取次數(shù)。// 開始請(qǐng)求,并且寫入數(shù)據(jù) let startRequest = async function(url) {let title = await titleRequest(url);let detail = await mainRequest(title.mainUrl);console.log(`開始爬取 ${title.title}`);number++;await savedContent('./data/', `${number} ${title.title}`, detail);console.log(`寫入 ${title.title}`);if (number <= endNumber) {startRequest(url);} else {console.log('===========================全部完成===========================');} };// 在本地存儲(chǔ) let savedContent = (path, title, detail) => {fs.appendFile(path + title + '.txt', detail, (err) => {if (err) {console.log(err);}}); } // 請(qǐng)求標(biāo)題 let titleRequest = (url) => {return new Promise((resolve, reject) => {//采用http模塊向服務(wù)器發(fā)起一次get請(qǐng)求http.get(url, function (res) {let html = ''; //用來(lái)存儲(chǔ)請(qǐng)求網(wǎng)頁(yè)的整個(gè)html內(nèi)容//監(jiān)聽data事件,每次取一塊數(shù)據(jù)res.on('data', function (chunk) {html += iconv.decode(chunk, 'GBK');});//監(jiān)聽end事件,如果整個(gè)網(wǎng)頁(yè)內(nèi)容的html都獲取完畢,就執(zhí)行回調(diào)函數(shù)res.on('end', function () {let $ = cheerio.load(html); //采用cheerio模塊解析html// 總的長(zhǎng)度endNumber = $('#list a').length;let title = $('#list a').eq(number).text();let mainUrl = baseUrl + $('#list a').eq(number).attr('href');let item = {// 小說(shuō)標(biāo)題title: title,// 小說(shuō)詳情mainUrl: mainUrl,//i是用來(lái)判斷獲取了多少篇文章i: number}// console.log(item); //打印新聞信息resolve(item);});}).on('error', function (err) {console.log(err);reject(err);});}); };// 請(qǐng)求內(nèi)容 let mainRequest = (mainUrl) => {return new Promise((resolve, reject) => {//采用http模塊向服務(wù)器發(fā)起一次get請(qǐng)求http.get(mainUrl, function (res) {let html = ''; //用來(lái)存儲(chǔ)請(qǐng)求網(wǎng)頁(yè)的整個(gè)html內(nèi)容//監(jiān)聽data事件,每次取一塊數(shù)據(jù)res.on('data', function (chunk) {html += iconv.decode(chunk, 'GBK');});//監(jiān)聽end事件,如果整個(gè)網(wǎng)頁(yè)內(nèi)容的html都獲取完畢,就執(zhí)行回調(diào)函數(shù)res.on('end', function () {let $ = cheerio.load(html); //采用cheerio模塊解析htmllet detail = $('#content').text().replace(/\s+/g,"\r\n\r\n&emsp;&emsp;&emsp;&emsp;");// console.log(detail); // 打印詳情resolve(detail);});}).on('error', function (err) {console.log(err);reject(err);});}); } // 開始執(zhí)行 startRequest(url); 復(fù)制代碼

::: hljs-center

2.8更新

:::

::: hljs-center

=====================================================================

:::

** 本來(lái)是獲取一次標(biāo)題,然后在獲取一次內(nèi)容,這樣每一章都要去請(qǐng)求兩次,所以導(dǎo)致速度比較慢。 現(xiàn)在修改為,標(biāo)題就一次性全部獲取,保存起來(lái),然后去在一次次去獲取內(nèi)容,這樣標(biāo)題請(qǐng)求一次就好了,省了一半的請(qǐng)求,速度能不快嘛。 直接貼關(guān)鍵代碼,剩下的自己去對(duì)比吧**

請(qǐng)求標(biāo)題的時(shí)候,修改了一下

// 請(qǐng)求標(biāo)題 let titleRequest = (url) => {return new Promise((resolve, reject) => {//采用http模塊向服務(wù)器發(fā)起一次get請(qǐng)求http.get(url, function (res) {let html = ''; //用來(lái)存儲(chǔ)請(qǐng)求網(wǎng)頁(yè)的整個(gè)html內(nèi)容//監(jiān)聽data事件,每次取一塊數(shù)據(jù)res.on('data', function (chunk) {html += iconv.decode(chunk, 'GBK');});let allData = [];//監(jiān)聽end事件,如果整個(gè)網(wǎng)頁(yè)內(nèi)容的html都獲取完畢,就執(zhí)行回調(diào)函數(shù)res.on('end', function () {let $ = cheerio.load(html); //采用cheerio模塊解析html$('#list a').each(function(index, item){let title = $(this).text();let mainUrl = $(this).attr('href');let itemData = {// 小說(shuō)標(biāo)題title: title,// 小說(shuō)詳情mainUrl: baseUrl + mainUrl,//i是用來(lái)判斷獲取了多少篇文章i: number};allData.push(itemData);});// console.log(allData); //打印新聞信息resolve(allData);});}).on('error', function (err) {console.log(err);reject(err);});}); }; 復(fù)制代碼

然后是總的請(qǐng)求修改了一下

// 開始請(qǐng)求,并且寫入數(shù)據(jù) let startSave = async function (){// 獲取所有標(biāo)題以及內(nèi)容的地址,整合成一個(gè)json,這樣標(biāo)題獲取一次就好了,和上次比,少了好多好多請(qǐng)求。let urlArr = await titleRequest(url);for(let i = 0; i < urlArr.length; i++) {number++;console.log(`開始爬取 ${urlArr[i].title}`);// 開始獲取單章內(nèi)容let mainDetail = await mainRequest(urlArr[i].mainUrl);console.log(`寫入 ${urlArr[i].title}`);await savedContent('./data/', `${number} ${urlArr[i].title}`, mainDetail);}console.log('===========================全部完成==========================='); }; 復(fù)制代碼

這里就不上全部代碼了,可以去git庫(kù)看。

::: hljs-center

年輕就是折騰,來(lái)加我啊

:::

轉(zhuǎn)載于:https://juejin.im/post/5a9f967d6fb9a028ca528495

總結(jié)

以上是生活随笔為你收集整理的NodeJs ES6 写简单爬虫 爬小说网站《我当方士那些年》的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。