求人不如求己,自己动手写一个CSDN博客备份小工具?
如果觉得对你有帮助,能否点个赞或关个注,以示鼓励笔者呢?!博客目录 | 先点这里
前提概要背景cabtool实践基础爬虫实践(一)分析如何爬取博客的markdown内容(二)分析如何批量爬取博客的markdown(三)如何模拟登录,获得cookies使用说明方式一方式二
前提概要
背景
因为笔者在上个月的时候,突然想扩展一下技术栈,不能仅仅局限于Java,还是得掌握一门工具语言,不然显得太low。所以也就对Python和Golang类的语言有了一些兴趣。也就在上个月简单的学习了Python3。但是呢,苦于没有时间也没有项目可以实践,所以爬虫就成为了避免忘记python的最佳实践
同时笔者发现在CSDN写的笔记好像也堆积了八九十篇啦。但是CSDN好像却没有类似简书一键导出的备份功能。于是之前没有数据备份意识的我本来想着从GayHub找找现成的Tool, 也不知道为什么GayHub上Tool不是过时了,就是效果不太符合我的意愿。个人琢磨着应该是大牛们嫌太简单,懒得放出来。于是,求人不如求己,虽然之前没有实践过爬虫,但还是花了半天的时间,把这个cab-tool
小工具是写出来啦
本着记录笔记的,分享大众的原则,于是本博就出来了
cabtool
什么是CAB-Tool
?这是什么玩意。其实就是csdn-article-backup-tool的缩写。为什么要缩写,本质就是装的一手好逼(狗头)
所以有需要的童鞋,可以去GibHub - CAB-Tool上顺手牵羊,支持小白式exe文件启动哈
实践基础
基本的python语法基础,懂一丢丢requests,beautifulsoup4库(简单的即可)会使用fiddle4对网络请求抓包需要知道基础的web知识因为博客备份工具还挺简单的,所以涉及内容并不复杂,主要是CSDN本身也没有防爬机制,所以只要了解简单爬虫知识的同学,都可以自己动手做一份,实践一下。
爬虫实践
(一)分析如何爬取博客的markdown内容
首先我们并不是根据爬取html,然后根据博文的html解析成markdown文本,因为每个编辑器都有自己的一些特俗规则。使用第三方库解析html,很可能得不到我自己想要的效果。所以我的直接策略就是,看能否直接从平时我们写markdown文字的编辑器中获取。
我们可以随便选择自己写过的一篇文章,点击编辑(必须是markdown文章,非富文本写的),同时打开浏览器的开发者工具(我是Chrome)
因为点击编辑,就会触发/mdeditor/95618910#
请求,我们就会进入markdown编辑器,编辑器会请求获取文章的markdown内容。所以我们就点开浏览器的开发者工具的Network
选项,勾选XHR
。于是我们就可以看到只剩两条请求。逐行分析那个URL才是获得markdown文本内容的请求。经过在response,preview简单的查看,很容易就能够知道第一个并没有什么卵用。只有第二个/mdeditor/getArticle?id=95618910
才是我们需要的。而95618910
就是这篇文章在csdn中的唯一文章id
从上面的开发者工具中,我们就可以知道编辑器请求markdown内容的url是什么了,这就是成功的第一步,所以这个要记住!既/mdeditor/getArticle?id=
。因为已经得到请求数据的url,所以我们就要开始模拟请求,让程序可以请求该url, 并获得数据。也因为要模拟请求,那我肯定得知道url是什么类型的请求,请求头带有什么数据,是否有body对吧。所以我们继续从浏览器的开发者工具对该请求进行分析
从上,我们就可以知道请求是get请求,走的https协议,请求头数据也都有了。包括cookies!(额,我之前应该是无法通过浏览器直接看到https请求的header的,也就是说这个url的headers是对我隐藏的。可能是在用fiddler4分析时,安装了证书吧,毕竟这方面的知识有些十分薄弱。总之,如果你在浏览器的开发者工具中无法分析出url的请求头,可以使用fiddler4对其分析,fiddler4默认是不监听https请求,但可以开启,这个方法百度即可)
请求的所有参数,我们都知道了。我们就可以在程序中模拟请求,让其自动化啦!(之前,可以用postman模拟)
以上,我们就可以得到单篇的文章的markdown内容啦!!Wow !剩下的就要做如何把所有文章的markdown内容都获取到 。同时这里提醒一下。因为markdown编辑器是需要用户登录才能访问的,所以必须要带有正确的cookies,否则是会提醒你权限不足,要求登录的奥,既Cookies的获取也是十分重要的一步
(二)分析如何批量爬取博客的markdown
从上面,我们知道了如何爬取单篇文章的markdown ,很简单,只要通过url + 文章id就可以了。那我们如何批量爬取呢?也很简单。如果我们一开始就知道自己所有文章的id集合, 然后遍历请求不就可以了嘛。
没错,但是我们怎么拿到所有文章的ID集合呢?这就是我们要解决的问题
如何爬取所有文章的ID集合,思路也很简单,我们知道自己的主页,会显示一列列的博客,点击博客就能跳转到对应的博文,所以简单的分析一下,我们就可以知道,自己主页一页会列出大概20篇文章的URL, 而这些URL的后缀就是文章ID。我们要做的就是得到请求主页的URL, 获得返回的HTML ,从HTML中找到一页的所有文章的URL, 并用正则表达式,从URL中截取出文章ID
从上,我们就可以知道主页是/SnailMann
, 主页中文章列表会存在文章ID,可以爬取获取。所以我们在通过requests获取主页的html之后,通过bs4先找到文章列的对应的article-list
的div内容,再递归找到article-item-box csdn-tracking-statistics
的div内容。然后的通过正则表达式获得每一行data-articleid=
后面的ID
以上,我们就得到主页中一页
所有文章的ID,例如我目前就有5页,所以就需要爬取5页,然后汇总。怎么爬所有页呢?首先要知道跳页的URL/SnailMann/article/list/2?
, 然后要知道自己总共有多少页
跳页URL很容易就知道了,总共多少页要怎么知道呢?这个我也不知道为什么呀,python爬取的html中并没有<div class = pagination-box>
内部的内容。所以最后只能曲线救国,在一个js脚本找到,文章总数和每页大小,通过ceil(文章总数 / 每页大小)
就是用户的总页数,比如我的ceil(89 / 20) = 5
,ceil就是向上取整的意思
总之通过以上的一顿操作,我们就可以通过py爬虫,抓取到所有页的文章ID,汇总成一个集合。然后遍历该集合,我们就可以获得所有文章的markdown内容啦!!!
(三)如何模拟登录,获得cookies
为什么要模拟登录,拿到cookies呢?因为从markdown编辑器中获取markdown文本内容,需要用户登录,所以我们请求markdown内容的请求必须带上cookies,否者是会被提示无权限访问,需要用户登录的。
当然最简单的做法就是从浏览器上把cookies复制下来,放到代码中,写死。但是这样不灵活,每次都需要浏览器登录,复制cookies,写死代码。所以我们就直接在程序上模拟登录,直接获得cookies就好啦!!!
这里浏览器就抓不到登录的链接了,所以我们还得切换成更牛逼的fiddler4, 从中,我们可以知道URL是/v1/register/pc/login/doLogin
, 请求类型是Post
, Headers图中都有。
既然是Post请求,那肯定有Body呀,账号密码也就是在body中传递的,点击TextView
就可以看到Body,然后我们就可以看到登录请求传递了5个属性。pwdOrVerifyCode
是你的密码,userIdentification
是你的账号(为了防止泄露,我这里对内容做了修改)
现在要知道的东西都知道了,我们就可以在程序模拟登录了。url和headers从fiddler4拷贝就行了。主要是body的数据,在代码中就是data字典。我们默认loginType就是1,不变。账号密码修改成自己的,uaToken,webUmidToken经过测试,不用管,为空即可
def dologin(self, username='', password=''):"""Simulated login CSDN account:param username::param password::return:"""url = '/v1/register/pc/login/doLogin'urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)header = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36','referer': '/login','origin': '','content-Type': 'application/json;charset=UTF-8','x-requested-with': 'XMLHttpRequest','accept': 'application/json, text/plain, */*','accept-encoding': 'gzip, deflate, br','accept-language': 'zh-CN,zh;q=0.9','connection': 'keep-alive','Host': ''}data = {'loginType': '1','pwdOrVerifyCode': str(password),'userIdentification': str(username),'uaToken': '','webUmidToken': ''}# login in csdn and get responseres = requests.post(url, data=json.dumps(data), headers=header, verify=False)# login errorif not res.status_code == 200:raise Exception(res.text)# assemble user data (username and cookies)body = res.json()cookies = requests.utils.dict_from_cookiejar(res.cookies)
以上就完成了模拟登录,获取cookies的过程
(四)总结
大体思路分为三个部分:
先做到获取一个文章的markdown内容再做到批量获取所有文章的markdown内容再通过模拟登录获取cookies做到自动化
总之,求人不如求己,简单的小例子,自己动手,丰富实践喔
本节重点讲解的是思路,因为小细节太繁琐,时间也有限呢,代码可以直接去我的GayHub看如果浏览器无法看到https请求的headers,可以使用fiddler4查看,前提是fiddler4开启了https请求监控喔
cabtool使用说明
方式一
如果你是没有任何python基础的同学,或是懒得安装py环境。没有关系,这里也是支持小白式运行的
点击cab-tool releases,下载cabtool.exe
的最新版本双击运行cabtool.exe
就好啦
方式二
第一步
CAB-Tool 开源地址把项目克隆本地git clone git@:SnailMann/CAB-Tool.git
确保本地有python3的环境, 并且可以使用pip安装依赖进入项目目录,命令行输入pip install -r requirements.txt
,使用pip安装py项目的必要依赖
第二步
打开setting.yaml
配置文件按照yaml规范填写CSDN的账号密码按照yaml规范在download-path填写本地导出地址,不填默认为D:\csdn-blog-backup
填写是否开启图片备份(True
,False
)
第三步
确认配置无误后项目路径打开命令行,输入py main.py