爬虫实现csdn文章一键(批量)更换阅读类型(全部可见、粉丝可见、vip可见)
- 2019 年 10 月 6 日
- 笔记
“ 动手创造美好” – bigsai
前言
- 在IT首屈一指的交流平台上,我们可以看得到csdn在最近的一些进步和变化:如
blink
,文章收益
,等等方面。促进和提升文章价值,激发笔者写作分享!这无疑是一件好事。 - 但csdn依然还有很多不够完善或者需要优化的地方,如
推荐算法
、新出的收益
无法一键更改文章阅读类型
。这让一些大的博主或者干货很多的博主(成百上千文章)很难有精力一个一个手动修改、维护自己权益。 - 作为社会新青年、IT从事者。我们清楚公作人员每天为我们服务很忙,不一定照顾到所有群体。笔者本着乐于助人的精神,故自己动手,写个脚本,帮助大家解决
心理生理
难题! - 该方案针对
markdown
用户。富文本可参考类推。 - 功能上分为
直接全部更改
和分类更改
,分类更改需要多输入
一个分类进去的首页url。其他一致!按照提升即可。 - 如有问题可以联系作者!

分析
- 需求既然有了,那么技术上怎么实现呢?
- 我们以前彻底的分析过csdn的登录机制,发现csdn很容易登录的。那么我们就可以用着登录的cookie进行我们想要的操作。
获取文章链接、id
我们要找到自己站点的所有文章的url和id。因为我们可能会根据文章id
进行操作。 思路:
- 从登录的cookie种找到你的id,进入csdn主页。
- 解析主页的信息获取页数,这里说一下。他的页数是
js动态加载
进去的,并不是直接渲染,如果非得头铁debug找也没问题。但是页数和总文章数有关系。因为一页
最多只能有20
篇文章!解析这些,你就能获取所有文章链接
、id
。

分析markdown文本
- 对任意一个文章、检查编辑。查看元素获取下来链接。你会发现链接是有规律的。跟文章id有关。

- 进入之后,你会发现这个是md好像提不出什么信息。点击提交看看ajax请求把。


- 这些参数没加密。都是原文。我想这个md文件csdn怎么提取。还能根据h5规则反向提取?csdn没那么强吧。肯定有其他方案。仔细观察发现加载时候有个
xhr
文件有了所有信息。我们只需要进行修改部分即可。

代码编写
- 思路清晰,流程大致为

依赖外部包:bs4
、requests
python代码为(没用多进程,简单用了下多线程,执行完手动结束关闭)
import requests from bs4 import BeautifulSoup import json import threading from queue import Queue queue= Queue() 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':'https://passport.csdn.net/login', 'origin':'https://passport.csdn.net', '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': 'passport.csdn.net' } data={"loginType":"1","pwdOrVerifyCode":"",' '"userIdentification":"","uaToken":"",' '"webUmidToken":""} cookies="" type='public' ## 登录 def login(usename,password): global cookies global data loginurl = 'https://passport.csdn.net/v1/register/pc/login/doLogin' data['userIdentification']=usename data['pwdOrVerifyCode']=password data=str(data) print(data) req = requests.post(loginurl, data=data, headers=header) cookies = requests.utils.dict_from_cookiejar(req.cookies) res = req.text print(req.status_code) print(cookies) url="https://blog.csdn.net/"+str(cookies['UN']) return url #将url文章添加到queue def addurl(url): req2 = requests.get(url, cookies=cookies) soup = BeautifulSoup(req2.text, 'lxml') ##获取页数 pagetotal = soup.select(".text-center")[0].get("title") pagetotal = (int)(((int)(pagetotal) + 19) / 20); print(pagetotal) for index in range(pagetotal): url2 = url+"/article/list/" + str(index + 1) print(url2) req = requests.get(url2, cookies=cookies) soup = BeautifulSoup(req.text, 'lxml') pages = soup.find(id='mainBox').find_all(attrs={'class': 'article-item-box'}) for page in pages: try: href = page.find("a").get("href") id = href.split("/") id = id[len(id) - 1] print(href, id) queue.put(id) except Exception as e: print(e) def addurl_by_type(url): req2 = requests.get(url, cookies=cookies) soup = BeautifulSoup(req2.text, 'lxml') ##获取页数 pagetotal = soup.select(".text-center")[0].get("title") pagetotal = (int)(((int)(pagetotal) + 19) / 20); print(pagetotal) for index in range(pagetotal): url2 = url + "/" + str(index + 1)+"?" print(url2) req = requests.get(url2, cookies=cookies) soup = BeautifulSoup(req.text, 'lxml') pages = soup.find(id='mainBox').find_all(attrs={'class': 'article-item-box'}) for page in pages: try: href = page.find("a").get("href") id = href.split("/") id = id[len(id) - 1] print(href, id) queue.put(id) except Exception as e: print(e) def change(id): global read_needType url3 = "https://mp.csdn.net/mdeditor/" + str(id) + "#" # req = requests.get(url3, cookies=cookies) url = "https://mp.csdn.net/mdeditor/getArticle?id=" + str(id) req = requests.get(url, cookies=cookies) res = req.json() data = res['data'] # for i in data: # print(i) print(res) data['readType'] = read_needType #print(data['readType']) url = "https://mp.csdn.net/mdeditor/saveArticle" req = requests.post(url, cookies=cookies, data=data) res = req.text #print(res) class downspider(threading.Thread): def __init__(self, threadname, que): threading.Thread.__init__(self) self.threadname = threadname self.que = que def run(self): print('start thread' + self.threadname) while True: try: print(self.name,end='') id=queue.get() change(id) except Exception as e: print(e) break if __name__ == '__main__': url="" threads=[] read_needType=['public','read_need_fans','read_need_vip'] name=input("name:") password=input("password:") print("type:n1:全部可看 n2关注可看 n3vip会员可看") value=input("请输入数字") value=int(value)-1 read_needType=read_needType[value] print("type:n1:全部更改 n2更改一个分类") all_or_type=input("输入更改范围(数字)") all_or_type=int(all_or_type) if all_or_type==1: url=login(name,password) addurl(url) else: print("输入分类首页url:") url=input("url:") login(name,password) addurl_by_type(url) print(url) threadList = ['thread-1', 'thread-2', 'thread-3', 'thread-4', 'thread-5'] for j in threadList: thread = downspider(j, queue) thread.start() threads.append(thread) for t in threads: t.join()
执行测试
- 执行


- 粉丝可见

- 还原
