大家好,我是米洛,求三连!关注
米洛的测开日记
,每天解锁一个小知识!
# mdnice
官网: https://mdnice.com/ (opens new window)
mdnice是一款非常好看的Markdown编辑器
,它为大家提供了很漂亮显示效果。但是非常遗憾的是,对于typora用户,或者习惯本地编写.md文件的朋友们来说,这个web版的编辑器,始终好像缺了点
什么。
回首望去,这半年的时间
,本卷魔已经肝了很多文章了,用一个汽车品牌形容我就是日产
!
所以无敌卷魔也积累了许多文章,但自己的文章都放到别人那里,始终是不太放心,如果能定期同步到本地
,那将是极好的。
# 那么该怎么做呢?
其实mdnice一眼看上去,是可以看到
文章列表和文章内容的。
首先我们得先拿到文章列表,再拿到每一篇文章
里面的内容,根据文章标题+文本内容,就可以写入到我们本地了。
先来看看mdnice的关键接口:
# 文章列表
打开F12
,鼠标在左侧文章滚动几下,可以看到F12里面请求文章列表的接口。
可以看到他们的url是https://api.mdnice.com/articles?currentPage=2&pageSize=20
, 敏锐的我们可以知道,后面的currentPage
和pageSize
分别是一页的数量和当前的页数。
仔细检查接口返回,发现并没有total这样的字段,所以我们请求的时候,一次性拉个500,1000条的,基本上
就能把文章拉完。
# 获取文本内容
因为文章列表接口里面没有带上文本内容信息,所以我们继续暗中观察
。
# 绕过登录部分
由于每个人文章都不一样,所以他的获取文章列表
接口必须是要登录
的。
但是我们要做免登陆还算麻烦
,因为他是微信扫码登录,没有提供直接的登录接口
,所以我们的脚本还得用户输入一下authorization
。
# 话不投机,干就完事
- 初始化Markdown类
初始化一个markdown类,把用户要保存的目录和认证信息传进来。
- 编写获取文章列表方法
我们用aiohttp加快读取速度,如果不看async with,他和requests.get没啥区别
,大家不要想的太难了。
- 编写写入文本内容的方法
利用os.path.join拼接目录,给文件加上md
后缀。
- 编写获取文本内容并写入的方法
挨个儿获取文本内容,并写入到文件里面去。整个过程一气呵成
,轻松写意。
这边文本列表的每一条数据,文章名称是title,outid则用来查询文本具体内容。
- 编写主方法
因为获取文件列表的数据在data字段里面,所以这边定义了data变量。
- 编写获取参数的方法
获取输入的文件目录+auth信息,组成最强战斗机
!
# 看看时间和效果
帅就完事儿了~
# 脚本给有需要的人
记得安装aiohttp
和aiofiles
import asyncio
import os
import sys
import time
import aiofiles
import aiohttp
import requests
class Markdown(object):
article_list_url = "https://api.mdnice.com/articles?currentPage=1&pageSize=1000"
article_detail = "https://api.mdnice.com/articles/{}"
def __init__(self, authorization, directory='./'):
self.directory = directory
self.headers = {"Authorization": authorization}
async def write_file(self, filename, content):
filepath = os.path.join(self.directory, f"{filename}.md")
async with aiofiles.open(filepath, 'w', encoding='utf-8') as f:
await f.write(content)
async def get_articles(self):
try:
async with aiohttp.ClientSession(headers=self.headers) as session:
async with session.get(self.article_list_url, headers=self.headers) as response:
return await response.json(encoding='utf-8')
except Exception as e:
print(f"获取用户文章列表失败")
raise e
async def get_article_content(self, title, article_id):
url = self.article_detail.format(article_id)
try:
async with aiohttp.ClientSession() as session:
async with session.get(url, headers=self.headers) as response:
data = await response.json(encoding='utf-8')
await self.write_file(title.replace("/", ""), data.get("data").get("markdown"))
except Exception as e:
print(f"写入文章: {title} 失败, error: {e}")
async def main(auth, directory_path):
before = time.perf_counter()
m = Markdown(auth, directory_path)
articles = await m.get_articles()
data = articles.get("data")
await asyncio.gather(*(m.get_article_content(x.get("title"), x.get("outId")) for x in data))
print(time.perf_counter() - before)
if __name__ == "__main__":
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
directory = input("请输入要写入的目录, 不输入则为当前目录:")
directory_path = directory if directory else "./"
auth = input("请输入mdnice官网headers中的Authorization: \n")
asyncio.run(main(auth, directory_path))
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58