爬取CSDN博客保存成PDF的方法
2018-11-14中国电波传播研究所
中国电波传播研究所 刘 士
中国电子科技集团公司第五十二研究所 支 浩
本文阐述了一种爬取指定CSDN账号的所有博文进行内容提并批量合并成PDF的方法,对该方法给出了Python语言的实现方式。实验结果证明,该方法具有可操作性和实用性。
引言:在实际工作中常常需要对感兴趣的CSDN博文保存成电子书,从而可以达到多设备、无网络的情况下进行阅读。本文介绍了如何使用Chrome浏览器和Python语言将目标博客内容爬取后进行信息提取,然后合并成PDF格式的方法。除Python自带的标准库外,所用到的Python库为BeautifulSoup、pdfkit、PyPDF2。本文一个主要成果是对爬取到的网页进行有效的数据清洗和自定义,在博客篇数较多时进行快速合并。
1.实现步骤
本文的实现符合爬虫的一般步骤即:“目标爬取、数据清洗、内容整合”。首先针对某一个感兴趣的作者爬取他的所有博文,然后进行信息提取后保存为PDF格式,最后将所有的PDF进行合并得到目标PDF。
1.1 爬取原始网页(Python 3 documentation;https://docs.python.org/3/.)
①爬取文章列表,使用chrome浏览器打开网址“https://blog.csdn.net/用户名/article/list/页码”可以获取指定用户某一页的所有文章。其中“用户名”为博客作者的用户名,页码为从1开始的整数。从“页码”为1开始依次递增遍历可以获取所有页面文章列表,当页码超出范围后网页会有“空空如野”提示,可作为终止条件;
②在上一步中进行网页内容解析后发现class=’article-list’中的所有<a>链接为具体某一篇博文的地址,可使用BeautifulSoup进行内容提取;
③提取上一步中的a链接的href属性后使用urlopen获取某一篇博文内容并保存到数据库。
在本步骤中,为了减少服务器的压力,爬取前先查询数据库表,如果存在则跳过该篇文章;同时在打开目标网址时最好带上请求“数据头”并保存cookie,在爬取内容成功后修眠几秒钟来减小爬虫被封的可能。
1.2 内容整理(Html教程;www.w3school.com.cn/html/index.asp.)
在获取到所有博文后需要对网页内容进行提取去掉不感兴趣的内容,比如去广告、去掉评论以及添加自定义声明等,该部分涉及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标签,观察通信内容来自行采集。
1.3 转化成pdf(wkhtmltopdf doc;https://github.com/wkhtmltopdf/wkhtmltopdf/.)
①遍历数据库表读取上一步中保存的网页内容;
②将网页内容调用pdfkit的库(wkhtmltopdf后端)函数转化成pdf后保存所有博文PDF到指定路径;
需要注意的是,在转化过程中有些网页图片可能不能正常加载,这时需要重定向系统stdout来获取错误信息,如果发生错误可重新尝试转化;同时由于转化成PDF的过程比较耗时,本文采用30个线程并行处理。一个实现技巧为:使用自定义线程池即先将线程句柄append到列表中,然后启动线程;在同一个函数中,循环遍历上述列表对每个线程执行join操作,从而达到在主函数退出前等待各个线程结束的目的。
1.4 批量合并pdf
在博客篇数比较少(几十篇)时,可以直接将各个网页的内容合并复制到一个html文件中使用上一步的方法进行转化,也可利用chrome打开后直接保存成pdf,从而跳过本步骤。但是当博文篇数较多时,经长时间测试运行(几十个小时),上述两种方法都会导致内存耗尽而导致转化失败。更为通用的方法为使用PyPDF2库,方法如下:
①生成PDF索引,使用PdfFileReader打开某一博文PDF获取页码数、文章标题和文章内容,然后添加到书签;
②将读取到的内容使用PdfFileWriter函数将所有内容进行保存合并到一个pdf中;
需要注意的是,在合并时由于合并的PDF页数过多,可能导致合并失败;经测试,可修改系统的最大递归深度为5000(编写本文的实际环境为Ubuntu 18.04 64bit,该系统的递归深度为1000)。
2.结论
本方法在python 3开发环境下,爬取雷霄骅(FFMPEG视频领域专家)的博文共558篇,经提取、整理、合并,如图1所示:
图1 某博客整理效果图
在实际使用时,只需要在第一步“爬取原始网页”时修改爬取目标网址中的用户名即可爬取不同用户的所有博客内容。