转换本地obsidian markdown路径为图床url

动机和作用

写博客, 本地的markdown. 比如要把本地用obsidian写的笔记上传到博客园或者其它的地方, 以前特别麻烦, 那就是一张一张打开图片, 然后拷贝到剪切板, 然后在博客编辑器粘贴. 下面这个脚本解决了这个问题. 执行方式是script_name markdown文件的path -o 目标路径, -o可以省略, 这样就是输出到终端.
你们可能会说, typora不就已经提供了图床功能么?
但我不能接受如果不联网, 自己的笔记都查看不了了.
代码是在这个基础上改的. 用的是sm.ms图床. 需要先注册, 获得api token.

代码

需要修改绝对路径(搜索quebec), api key. 以及, 如果你不是obsidian, 还需要改一下正则表达式, 和Replace中的逻辑.
TU

#!/usr/bin/env python3
# -*- coding:utf-8 -*-

# 使用sm.ms 实现图床上传脚本

import requests
import json
import sys
import os
import re
import argparse
# 引入PIL库,实现图片缩放
# from PIL import Image


# 图片缩放
def zoom(origin_file, width):
    set_width = width
    im = Image.open(origin_file)
    # 获得图像尺寸:
    w, h = im.size

    # 缩放倍率
    prop = w / set_width
    set_height = h / prop

    # 缩放
    im.thumbnail((set_width, set_height))
    # 返回image对象
    return im

class Replace:
    def __init__(self):
        self.count = 0
        self.db=DB('/Users/quebec/box/image_hosting/image_url_sm_ms.sqlite')
    def __call__(self, mo):
        full_path = "/Users/quebec/notes/vx_attachments/" + mo.group(1)
        ret = self.db.get(full_path)
        if(ret):
            new_path = ret
        else:
            ret = self.upload(full_path)
            # self.count+=1
            if(ret["status"]):
                new_path = ret['data']
                self.db.put(full_path, new_path)
            else:
                raise TypeError(f"error: {ret['data']}")
        # return f"![]({new_path})"
        width = mo.group(4) if mo.group(4) else 600
        return f'<img src="{new_path}" alt="drawing" width="{width}"/>'


    @classmethod
    def upload(cls,path):
        upload_url='https://sm.ms/api/v2/upload'
        files = {'smfile': open(path, 'rb')}
        # 发起请求
        headers = {'Authorization': ''} # 这里填你的api
        r = requests.post(upload_url, files=files, headers=headers)
        if r.status_code == requests.codes.ok:
            # 把字符串装换成字典
            return_data = json.loads(r.text)
            if return_data['code'] == 'success':
                return {'status': True, 'data': return_data['data']['url']}
            else:
                return_data = json.loads(r.text)
                # sys.exit(return_data)
                return {'status': False, 'data': return_data}


def main():
    parser = argparse.ArgumentParser(description='convert local obsidian path to url')
    parser.add_argument('source_path', help='obsidian markdown file')
    parser.add_argument('-o', dest='target_path', required = False, help='target path')
    args = parser.parse_args()

    fh = open(args.source_path, 'rt', encoding='utf8')
    text=fh.read()
    fh.close()
    # text = "![[Pasted image 20211004220118.png|600]] and more"
    repl = Replace()
    new_text = re.sub(r"!?\[\[([^\]]+.(png|jpg|jpeg))(\|(\d+))?\]\]", repl, text, flags=re.IGNORECASE)
    # 检查图片参数是否输入
    if(args.target_path):
        fh_o = open(args.target_path, 'wt', encoding='utf8')
        fh_o.write(new_text)
        fh_o.close()
    else:
        print(new_text)
#%%
# 图片上传

class DB:
    def __init__(self, sqlite_db_path):
        from sqlitedict import SqliteDict
        self.mydict = SqliteDict(sqlite_db_path, autocommit=True)
        self.db_path = sqlite_db_path

    def put(self, key, value):
        self.mydict[key] = value

    def get(self, key):
        return self.mydict.get(key)

    def __del__(self):
        self.mydict.close()


if __name__ == "__main__":
    main()
posted @ 2022-04-20 18:35  Tokubara  阅读(438)  评论(0编辑  收藏  举报