簡書改版后,根據(jù)文章標題搜索文章的功能就不見了。
創(chuàng)新互聯(lián)公司服務(wù)項目包括閩清網(wǎng)站建設(shè)、閩清網(wǎng)站制作、閩清網(wǎng)頁制作以及閩清網(wǎng)絡(luò)營銷策劃等。多年來,我們專注于互聯(lián)網(wǎng)行業(yè),利用自身積累的技術(shù)優(yōu)勢、行業(yè)經(jīng)驗、深度合作伙伴關(guān)系等,向廣大中小型企業(yè)、政府機構(gòu)等提供互聯(lián)網(wǎng)行業(yè)的解決方案,閩清網(wǎng)站推廣取得了明顯的社會效益與經(jīng)濟效益。目前,我們服務(wù)的客戶以成都為中心已經(jīng)輻射到閩清省份的部分城市,未來相信會繼續(xù)擴大服務(wù)區(qū)域并繼續(xù)獲得客戶的支持與信任!
雖然簡書提供了批量下載文章的功能,但是下載到本地的文章都是markdown格式的,不包含文章的鏈接,這不滿足我的需求。
既然我是程序員,沒有這個功能我就自己實現(xiàn)一個。
打開簡書首頁,發(fā)現(xiàn)默認只顯示8篇文章,用鼠標滑動到屏幕底部后,會觸發(fā)一個懶加載事件,到后臺讀取更多的文章列表,所以文章讀取在服務(wù)器端是采取的分頁實現(xiàn)。
打開Chrome開發(fā)者工具,觀察網(wǎng)絡(luò)請求,請求url中99b8712e8850是我簡書用戶id,page=2,3,4這些是分頁代碼。
每頁的文章內(nèi)容以html格式包含在響應(yīng)結(jié)構(gòu)里:
我關(guān)心的只是文章標題和文章鏈接,如上圖高亮字段所示。
最開始我寫了一個nodejs應(yīng)用,代碼如下:
var request = require('request');var jsdom = require("jsdom");var JSDOM = jsdom.JSDOM;const PREFIX = "https://www.jianshu.com";const PAGE = "https://www.jianshu.com/u/99b8712e8850?order_by=shared_at&page=";const MAX = 2;var mArticleResult = new Map();var pageNumber;/* a given article: https://www.jianshu.com/p/963cd23fb092 value got from API: /p/5c1d0319dc42 */var lastPageReached = false;var url = "";var aHandlers = [];// use limited for loop to ease testingfor(var i = 0; i < MAX; i++){ pageNumber = i + 1; var url = PAGE + pageNumber; // console.log("current page: " + url); var pageOptions = { url: url, method: "GET", headers: { "Accept": "text/html" } }; aHandlers.push(getArticles(pageOptions, pageNumber)); if( lastPageReached) break; }console.log("promise handler size: " + aHandlers.length);Promise.all(aHandlers).then(function(){ var articleIndex = 0; for (var [key, value] of mArticleResult) { console.log("Article[" + articleIndex++ + "]: " + key + " = " + value); } console.log("done"); } );function getArticles(pageOptions, pageNumber) { return new Promise(function(resolve,reject){ var requestC = request.defaults({jar: true}); requestC(pageOptions,function(error,response,body){ if( error){ console.log("error: " + error); resolve(error); } var document = new JSDOM(body).window.document; var content = document.getElementsByTagName("li"); for( var i =0; i < content.length; i++){ var li = content[i]; var children = li.childNodes; for( var j = 0; j < children.length; j++){ var eachChild = children[j]; if( eachChild.nodeName == "DIV"){ var grandChild = eachChild.childNodes; for( var k = 0; k < grandChild.length; k++){ var grand = grandChild[k]; if( grand.nodeName == "A"){ var fragment = grand.getAttribute("href"); if( fragment.indexOf("/p") < 0) continue; console.log("title: " + grand.text); var wholeURL = PREFIX + fragment; console.log("url: " + wholeURL); if( mArticleResult.has(grand.text)){ lastPageReached = true; console.log("article size: " + mArticleResult.size); resolve(pageNumber); } mArticleResult.set(grand.text, wholeURL); } } } } }// end of outer loop resolve(pageNumber); }); }); }
原理就是使用nodejs的request module,向簡書網(wǎng)站同時發(fā)起多個請求,每個請求讀取一頁的簡書文章。
后來發(fā)現(xiàn)這種方法在并發(fā)請求數(shù)大于10個的時候就無法工作,簡書網(wǎng)站會拒絕該類請求,返回HTTP 429狀態(tài)碼。
所以最后我采用了最簡單的同步請求實現(xiàn),使用了nodejs提供的sync-request在循環(huán)里發(fā)起請求。
var request = require("sync-request");var jsdom = require("jsdom");var JSDOM = jsdom.JSDOM;var textEncoding = require('text-encoding'); var textDecoder = textEncoding.TextDecoder;const PREFIX = "https://www.jianshu.com";const PAGE = "https://www.jianshu.com/u/99b8712e8850?order_by=shared_at&page=";const MAX = 100;var mArticleResult = new Map();var lastPageReached = false;var pageNumber;/* a given article: https://www.jianshu.com/p/963cd23fb092 value got from API: /p/5c1d0319dc42 */try { // use limited for loop to ease testing for (var i = 0; i < MAX; i++) { if( lastPageReached) break; pageNumber = i + 1; var url = PAGE + pageNumber; console.log("current page: " + url); var response = request('GET', url); var html = new textDecoder("utf-8").decode(response.body); handleResponseHTML(html); } } catch (e) { }var articleIndex = 0;var resultHTML = "<html>";const fs = require('fs');/* <HTML> <p> <a href="https://www.baidu.com">eee</a> </p> <p><a>22</a></p> <p><a>33</a></p> </HTML> */var index = 1;for (var [key, value] of mArticleResult) { var article = "<p><a href=\"" + key + "\">" + index++ + ". " + value + "</a></p>" + "\n"; resultHTML = resultHTML + article; console.log("Article[" + articleIndex++ + "]: " + value + " = " + key); } resultHTML = resultHTML + "</html>";var pwd = process.cwd() + "/jianshu.html"; fs.appendFileSync(pwd, resultHTML);console.log("done");function handleResponseHTML(html) { var document = new JSDOM(html).window.document; var content = document.getElementsByTagName("li"); for (var i = 0; i < content.length; i++) { var li = content[i]; var children = li.childNodes; for (var j = 0; j < children.length; j++) { var eachChild = children[j]; if (eachChild.nodeName == "DIV") { var grandChild = eachChild.childNodes; for (var k = 0; k < grandChild.length; k++) { var grand = grandChild[k]; if (grand.nodeName == "A") { var fragment = grand.getAttribute("href"); if (fragment.indexOf("/p") < 0) continue; // console.log("title: " + grand.text); var wholeURL = PREFIX + fragment; // console.log("url: " + wholeURL); if (mArticleResult.has(wholeURL)) { lastPageReached = true; console.log("article size: " + mArticleResult.size); return; } mArticleResult.set(wholeURL, grand.text); } } } } } }
這個nodejs應(yīng)用執(zhí)行后,會在本地生成一個html文件,包含每篇文章的標題和超鏈接。
要獲取更多Jerry的原創(chuàng)文章,請關(guān)注公眾號"汪子熙":
網(wǎng)站題目:批量導(dǎo)出某個簡書用戶的所有文章列表和文章超鏈接
轉(zhuǎn)載注明:http://jinyejixie.com/article2/ppeoic.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)頁設(shè)計公司、Google、網(wǎng)站維護、小程序開發(fā)、營銷型網(wǎng)站建設(shè)、搜索引擎優(yōu)化
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)