中國電波傳播研究所 劉 士
中國電子科技集團公司第五十二研究所 支 浩
本文闡述了一種爬取指定CSDN賬號的所有博文進行內容提并批量合并成PDF的方法,對該方法給出了Python語言的實現方式。實驗結果證明,該方法具有可操作性和實用性。
引言:在實際工作中常常需要對感興趣的CSDN博文保存成電子書,從而可以達到多設備、無網絡的情況下進行閱讀。本文介紹了如何使用Chrome瀏覽器和Python語言將目標博客內容爬取后進行信息提取,然后合并成PDF格式的方法。除Python自帶的標準庫外,所用到的Python庫為BeautifulSoup、pdfkit、PyPDF2。本文一個主要成果是對爬取到的網頁進行有效的數據清洗和自定義,在博客篇數較多時進行快速合并。
本文的實現符合爬蟲的一般步驟即:“目標爬取、數據清洗、內容整合”。首先針對某一個感興趣的作者爬取他的所有博文,然后進行信息提取后保存為PDF格式,最后將所有的PDF進行合并得到目標PDF。
①爬取文章列表,使用chrome瀏覽器打開網址“https://blog.csdn.net/用戶名/article/list/頁碼”可以獲取指定用戶某一頁的所有文章。其中“用戶名”為博客作者的用戶名,頁碼為從1開始的整數。從“頁碼”為1開始依次遞增遍歷可以獲取所有頁面文章列表,當頁碼超出范圍后網頁會有“空空如野”提示,可作為終止條件;
②在上一步中進行網頁內容解析后發現class=’article-list’中的所有<a>鏈接為具體某一篇博文的地址,可使用BeautifulSoup進行內容提??;
③提取上一步中的a鏈接的href屬性后使用urlopen獲取某一篇博文內容并保存到數據庫。
在本步驟中,為了減少服務器的壓力,爬取前先查詢數據庫表,如果存在則跳過該篇文章;同時在打開目標網址時最好帶上請求“數據頭”并保存cookie,在爬取內容成功后修眠幾秒鐘來減小爬蟲被封的可能。
在獲取到所有博文后需要對網頁內容進行提取去掉不感興趣的內容,比如去廣告、去掉評論以及添加自定義聲明等,該部分涉及html知識。
①選取一篇已爬取到的博文內容,新建一個空白的html文件并復制內容到該文件,使用chrome瀏覽器打開,在開發者模式下(F12快捷鍵打開)和原博文進行對比分析;
②在開發者模式下發現博文的有效內容在標簽class=’blogcontent-box’中,可以使用BS4提取所有內容;
③自定義網頁內容,經調試發現,想要“原汁原味”的還原CSDN的博文內容并調整頁面適合閱讀,需要保留原來頁面head標簽中的jquery庫和sphonix系列主題;可以去掉原頁面中其他js代碼來加快頁面加載;修改<main>標簽width屬性CSS為100%,將’hide-articlebox’標簽的display:屬性設置為none,用來顯示全部網頁;同時可以在recommend-box標簽中添加自定義網頁內容,如“本PDF是由spygg生成,請尊重原作者版權”...(見圖1),然后保存為html文件。
需要注意的是,由于實際需要在本文實現時博客的評論部分被剔除。經chrome抓包調試發現博客評論文章是通過ajax來獲取的,如果需要該部分內容可打開chrome的Network標簽下的xhr標簽,觀察通信內容來自行采集。
①遍歷數據庫表讀取上一步中保存的網頁內容;
②將網頁內容調用pdfkit的庫(wkhtmltopdf后端)函數轉化成pdf后保存所有博文PDF到指定路徑;
需要注意的是,在轉化過程中有些網頁圖片可能不能正常加載,這時需要重定向系統stdout來獲取錯誤信息,如果發生錯誤可重新嘗試轉化;同時由于轉化成PDF的過程比較耗時,本文采用30個線程并行處理。一個實現技巧為:使用自定義線程池即先將線程句柄append到列表中,然后啟動線程;在同一個函數中,循環遍歷上述列表對每個線程執行join操作,從而達到在主函數退出前等待各個線程結束的目的。
在博客篇數比較少(幾十篇)時,可以直接將各個網頁的內容合并復制到一個html文件中使用上一步的方法進行轉化,也可利用chrome打開后直接保存成pdf,從而跳過本步驟。但是當博文篇數較多時,經長時間測試運行(幾十個小時),上述兩種方法都會導致內存耗盡而導致轉化失敗。更為通用的方法為使用PyPDF2庫,方法如下:
①生成PDF索引,使用PdfFileReader打開某一博文PDF獲取頁碼數、文章標題和文章內容,然后添加到書簽;
②將讀取到的內容使用PdfFileWriter函數將所有內容進行保存合并到一個pdf中;
需要注意的是,在合并時由于合并的PDF頁數過多,可能導致合并失敗;經測試,可修改系統的最大遞歸深度為5000(編寫本文的實際環境為Ubuntu 18.04 64bit,該系統的遞歸深度為1000)。
本方法在python 3開發環境下,爬取雷霄驊(FFMPEG視頻領域專家)的博文共558篇,經提取、整理、合并,如圖1所示:

圖1 某博客整理效果圖
在實際使用時,只需要在第一步“爬取原始網頁”時修改爬取目標網址中的用戶名即可爬取不同用戶的所有博客內容。