语雀批量导出MarkDown文件

一、背景

笔记写在语雀有时候总想本地再存储一份,但是一个个导出又太麻烦了。需要导出语雀的全部文件,并导出为markdown格式。

二、实现

2.1配置json配置文件

  • 设置token

    登录网页版语雀,点击头像创建token,语雀token链接 👉https://www.yuque.com/settings/tokens/new

    image-20221106233746731

  • 填写配置信息

    配置信息用来设置用户的token等一些基础信息

    # config.json
    {
        "TOKEN": "xxxxxxxx",                                # 用户token
        "USER_AGENT": "Rion",                               # 就是一个用户名称,可以随意写,但必须要有
        "BASE_URL": "https://customspace.yuque.com/api/v2", # 语雀基础api
        "DATA_PATH": "yuque"                                # 数据储存的文件夹名称(默认当前文件夹下创建)
    }
    

2.2 实现代码

"""
    这是一个导出语雀库中所有文档的脚本, 并将文件转为md格式
"""
import json
import sys
import os
import re
import requests
import psutil
from datetime import datetime

if getattr(sys, 'frozen', False):
    APPLICATION_PATH = os.path.dirname(sys.executable)
else:
    APPLICATION_PATH = os.path.dirname('.')
jsonConfig = json.load(open(os.path.join(APPLICATION_PATH, "config.json"), encoding='utf-8'))

class ExportYueQueDoc:
    def __init__(self):
        try:
            if getattr(sys, 'frozen', False):
                APPLICATION_PATH = os.path.dirname(sys.executable)
            else:
                APPLICATION_PATH = os.path.dirname('.')
            self.jsonConfig = json.load(open(os.path.join(APPLICATION_PATH, "config.json"), encoding='utf-8'))
            self.base_url = self.jsonConfig['BASE_URL']
            self.token = self.jsonConfig['TOKEN']
            self.headers = {
                "User-Agent": self.jsonConfig['USER_AGENT'],
                "X-Auth-Token": self.jsonConfig['TOKEN']
            }
            self.data_path = self.jsonConfig['DATA_PATH']
        except:
            raise ValueError("config.json 有误")
        
    def get_user_info(self):
        """获取用户信息"""
        res_obj = requests.get(url=self.base_url + '/user', headers=self.headers)
        if res_obj.status_code != 200:
            raise ValueError("Token 信息错误")
        user_json = res_obj.json()
        self.login_id = user_json['data']['login']
        self.uid = user_json['data']['id']
        self.username = user_json['data']['name']
        print("=========== 用户信息初始化成功 ==========")
    
    def get_repos_data(self):
        """获取知识库"""
        repos_json = requests.get(self.base_url + '/users/' + self.login_id + '/repos', headers=self.headers).json()
        repos_list = []
        for item in repos_json['data']:
            rid = item['id']     # 知识库id
            name = item['name']  # 知识库名称
            repos_list.append({"rid": rid, "repos_name": name})
        return repos_list

    def get_article_data(self, repos_list):
    	"""获取文章数据"""
        article_list = []
        for repos in repos_list:
            article_datas = requests.get(self.base_url + '/repos/' + str(repos['rid']) + '/docs', headers=self.headers).json()
            for item in article_datas['data']:
                bid = repos['rid']       
                title = item['title']       # 文章标题
                desc = item['description']
                slug = item['slug']
                article_list.append({"bid": bid, "title": title, "desc": desc, "slug": slug, "repos_name": repos["repos_name"]})
        
        for item in article_list:
            per_article_data = requests.get(self.base_url + '/repos/' + str(item['bid']) + '/docs/' + item['slug'],  headers=self.headers).json()
            posts_text = re.sub(r'\\n', "\n", per_article_data['data']['body'])
            result = re.sub(r'<a name="(.*)"></a>', "", posts_text)
            # all_datas.append({"title": item['title'], "content": result})
            yield result, item["repos_name"], item['title']

    def save_article(self, result, repos_name, title):
    	"""写入文章"""
        current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        dir_path = f"{self.data_path}/{repos_name}"
        filepath = dir_path + f"/{title}.md"
        dir_ret = os.path.exists(dir_path)
        if not dir_ret:
            os.makedirs(dir_path)
        exists_ret = os.path.exists(filepath)
        if exists_ret:
            os.remove(filepath)
        try:
            with open(filepath, 'a', encoding="utf-8") as fp:
                fp.writelines(result)
            print(f"[{current_time}]  {title} 写入完成")
        except Exception as e:
            print(f"[{current_time}]  {title} 写入失败")
    
    def main(self):
        self.get_user_info()
        repos_list = self.get_repos_data()
        gen_obj = self.get_article_data(repos_list)
        for item in gen_obj:
            self.save_article(item[0], item[1], item[2])
    

if __name__ == "__main__":
    yq = ExportYueQueDoc()
    yq.main()

将程序文件和配置文件放在同一级目录下,执行py文件即可

同时提供了exe程序,直接双击yuque.exe执行,注意配置文件``config.json` 同级目录和填写信息是否正确,exe下载地址 👉 https://github.com/Ri0nGo/ScriptCode/tree/master/CrawlScript/yuque/Tools

image-20221106234442088

后续

  1. 若后面有时间不知道能不能实现把本地的markdown文件自动上传到语雀中,实现双向同步
  2. Linux下可以配置定时任务,实现定期同步,Windows 也可以做成服务,不过需要改动代码,实现定时爬取。
  • 6
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值