批量匯出某個簡書使用者的所有文章列表和文章超連結
簡書改版後,根據文章標題搜尋文章的功能就不見了。
雖然簡書提供了批量下載文章的功能,但是下載到本地的文章都是markdown格式的,不包含文章的連結,這不滿足我的需求。
既然我是程式設計師,沒有這個功能我就自己實現一個。
開啟簡書首頁,發現預設只顯示8篇文章,用滑鼠滑動到螢幕底部後,會觸發一個懶載入事件,到後臺讀取更多的文章列表,所以文章讀取在伺服器端是採取的分頁實現。
開啟Chrome開發者工具,觀察網路請求,請求url中99b8712e8850是我簡書使用者id,page=2,3,4這些是分頁程式碼。
每頁的文章內容以html格式包含在響應結構裡:
我關心的只是文章標題和文章連結,如上圖高亮欄位所示。
最開始我寫了一個nodejs應用,程式碼如下:
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,向簡書網站同時發起多個請求,每個請求讀取一頁的簡書文章。
後來發現這種方法在併發請求數大於10個的時候就無法工作,簡書網站會拒絕該類請求,返回HTTP 429狀態碼。
所以最後我採用了最簡單的同步請求實現,使用了nodejs提供的sync-request在迴圈裡發起請求。
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應用執行後,會在本地生成一個html檔案,包含每篇文章的標題和超連結。
要獲取更多Jerry的原創文章,請關注公眾號"汪子熙":
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/24475491/viewspace-2643507/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 開發一個簡單的工具,匯出github倉庫所有issue列表Github
- 某微信公眾號2019年度文章列表
- wordpress 文章的釋出和修改時定製文章標題
- PbootCMS 文章列表序號boot
- python批量新增hexo文章封面PythonHexo
- [譯]將你的Medium文章匯出成Markdown格式
- 啥?Fiddler 證書匯出失敗,莫慌,看這篇文章就能搞定!
- Rust本週精彩文章連結Rust
- 一個SAP成都研究院開發工程師2020年所有文章列表工程師
- Chrome瀏覽器如何匯出所有書籤並匯入書籤Chrome瀏覽器
- easyExcel匯出多個list列表的excelExcel
- 怎麼刪除某個使用者的所有帖子?
- vue實現對文章列表的點贊Vue
- ssycms不常用的文章列表呼叫程式碼
- Python爬蟲-獲得某一連結下的所有超連結Python爬蟲
- 超強彙總:學習Python列表,只需這篇文章就夠了Python
- 『輕鬆部署 Laravel 應用』系列文章快捷連結Laravel
- 連載四:Oracle升級文章大全(完結篇)Oracle
- WordPress自動採集釋出文章04-如何批量定時釋出文章
- 連結串列基礎2(超簡單)--單連結串列的插入和刪除
- 用weexplus從0到1寫一個app(2)-頁面跳轉和文章列表及文章詳情的編寫APP
- mysql下批量清空某個庫下的所有表(庫不要刪除,保留空庫)MySql
- WordPress自動採集釋出文章03-如何批量把文章上傳到wordpress
- 你的文章裡為什麼不放原始碼Github連結了原始碼Github
- 文章經典總結
- Oracle統計某個使用者下所有表的各自行數Oracle
- 某微信公眾號AI文章清單AI
- 如何搭建文章結構——常見技術文章的邏輯框架框架
- chrome獲取書籤目錄下收藏的所有連結Chrome
- 利用Powershell快速匯出域控所有使用者Hash
- AD 批量匯入使用者(利用 for……do……dsadd user 批量建使用者)
- 織夢DedeCMS獲取文章連結的函式GetOneArchive使用方法函式Hive
- Java Profilers探查器使用指南-部落格園文章連結Java
- pbootcms模板首頁如何某個指定的欄目名稱和連結boot
- 釋出的文章,怎麼生成HTML?HTML
- 如何將一個PDF檔案裡的圖片批量匯出
- (分享連結製作)防封,微信文章分享活動推廣連結製作
- 最近在讀的一些文章和書