• 本地任意markdown工具和文件中一键插入图像(用一种优雅的方式在本地markdown文件中插入网络图片文件)


    用一种优雅的方式在markdown文件中插入图片文件

    很多人用markdown语法记笔记,比如我,无论是做软件开发的时候,还是做科研笔记,我都喜欢用markdown语法来写,这是因为我习惯用git来存我的文献和笔记,而且我不喜欢使用第三方笔记软件因为命根子在别人手里(备忘录、印象笔记、有道云笔记),再者我还想轻量化且可以跨平台。所以最后就选择了markdown语法。

    在网页中写markdown语法可以用丰富的文本编辑器,可以随意插入图片什么的,但是在本地写就比较蛋疼,很多编辑器不支持截图后直接插入markdown文件中,插入图片就显得比较麻烦,但是看文献做笔记的时候需要截图插入,所以就出现了这个大需求。

    typora相信大家用过,可以很方便地在本地插入网络图像(前提是在typoral中配置对象存储的信息),是一个非常强大的本地md文件编辑工具。非常尴尬的是typoral开始收费了,80RMB,但是只能激活3台电脑,虽然可以反激活,但是不是账号买断制我不觉得不香,我不太喜欢,我想白嫖!

    因为不想花钱买typoral,不想用盗版,又非常想要这个本地md插入网络图像的功能,所以我自己写了一个脚本,下面介绍给大家。

    小软件已经发布了exe文件,可以直接下载下来修改配置文件后使用,非常方便,代码完全开源。地址:

    软件源码:https://gitee.com/qkmc/mini-typora

    软件下载:https://gitee.com/qkmc/mini-typora/releases/tag/0.2

    如果你觉得好用,给我点个赞吧,求求你了!

    1. 脚本介绍

    • 这是一个python脚本,只要运行run.py然后挂在后台即可,通过设定的快捷键,触发截图功能,截完图后脚本会自动把图像上传到七牛云中,然后将图片的md地址直接设置到windows的剪切板中,截完图只需要在md文件中ctrl + v就能插入网络图像了,非常方便。
      -流程: 打开脚本 – 设置快捷键 --触发快捷键 – 截图 – 在需要的地方粘贴
      在这里插入图片描述

    2. 技术手段

    原理其实并不复杂:

    • 首先是截图动作和截图,截图动作使用python的wx模块,wx模块是python的GUI模块包,当我们截图时,屏幕表面的灰色蒙版层还有获取鼠标的坐标都是靠这个模块实现。而截图这个动作则是由PIL中的ImageGrab来实现,通过ImageGrab可以获取屏幕上的图像并存到某个python变量中。
    • 其次是快捷键监听,使用python的keyboard模块,里面可以设置钩子函数、监听事件等,设置完成后,当我们触发某组快捷键时,就会执行相应的程序。
    • 然后是图像上传,当我们截取完图像后,需要自动上传到网络中,我这里使用了七牛云的对象存储,如果你还不知道什么是对象存储,那你就要去七牛云官网看看了,阿里云腾讯云什么的都行吧。
    • 还有两个小玩意儿注意一下,plyer中的notification可以在windows的通知栏里面进行通知,pyperclip模块用于设置和读取windows剪切板里面的内容,相当于执行ctrl+c ctrl+v的功能。

    3. 模块实现

    3.1 截图实现

    • 截图的实现其实蛮简单的,使用wx模块和PIL的ImageGrab模块。(核心代码解释略)
    • 具体实现方案见代码所示。
    import wx
    from PIL import ImageGrab
    
    class ScreenShot(wx.Frame):
        left,right,top,bottom = 0,0,0,0
        img = None
    
        def __init__(self, parent):
            wx.Frame.__init__(self, parent,
                style = wx.MAXIMIZE # 全屏显示
            )
            # 设置背景色
            self.SetBackgroundColour((255,255,255))
            # 设置透明度
            self.SetTransparent(30)
            # 注册事件
            self.Bind(wx.EVT_LEFT_DOWN, self.OnDown, self)
            self.Bind(wx.EVT_LEFT_UP, self.OnUp, self)
            # 显示button
            self.Show(True)
    
        def OnDown(self, event):
            pos = event.GetPosition()
            self.top = pos.y
            self.left = pos.x
            
        def OnUp(self, event):
            pos = event.GetPosition()
            self.bottom = pos.y
            self.right = pos.x
            
            # print(self.left, self.top, self.right, self.bottom)
            self.img = self.catch_area(
                self.left, self.top, self.right, self.bottom)
            # 截图完毕后关闭button
            self.Close(False)
    
        def catch_area(self, left, top, right, bottom):
            return ImageGrab.grab((left, top, right, bottom))
    
    • 1
    • 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

    代码解析:代码的主要功能就是在屏幕上蒙上一层灰灰的层,然后鼠标按下拖拽,松开,监听拿到这两个点的坐标,拿到坐标后通过ImageGrab.grab方法截取到屏幕指定地方的截图。

    • 上面只是把工具定义好了,怎么使用呢?
    from ScreenShot import ScreenShot
    # import ScreenShot
    app = wx.App(False)
    frame = ScreenShot(None)
    app.MainLoop()
    frame.img.show()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    3.2 七牛云上传文件

    • 打开七牛云官网,找到开发者文档,找到对象存储,然后找到python的sdk,然后复制下来改改就行了。先去把自己的对象存储开通弄好,不要嫌麻烦。
    • 我这里的文件上传小模块代码如下:

    参数解释:
    access_key和secret_key在哪里获取?在七牛云对象存储的开发者文档里面有详细介绍
    domain是域名,如果你有自己的域名,可以像我这样配置CNAME,如果你没有域名,可以用七牛云对象存储提供的免费域名,效果一样的。
    bucket_name在七牛云对象存储控制面板里面自己创建就行了

    # -*- coding: utf-8 -*-
    # flake8: noqa
    
    from qiniu import Auth, put_file, etag
    import qiniu.config
    
    #需要填写你的 Access Key 和 Secret Key
    access_key = 'sss'
    secret_key = 'xxx'
    domain = 'http://paper.ruankun.xyz/'
    
    #构建鉴权对象
    q = Auth(access_key, secret_key)
    
    #要上传的空间
    bucket_name = 'iwannagraduation'
    
    #要上传文件的本地路径
    # localfile = './sync/bbb.jpg'
    
    # key 上传的文件名
    def upload(key: str, filepath: str):
        #上key是上传后保存的文件名
        # 要上传文件的本地路径
        localfile = filepath + key
        #生成上传 Token,可以指定过期时间等
        token = q.upload_token(bucket_name, key, 3600)
        ret, info = put_file(token, key, localfile) 
        assert ret['key'] == key
        assert ret['hash'] == etag(localfile)
        return domain + key
    
    
    • 1
    • 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
    • 那么如何使用呢?在需要的地方直接调用就行了:(generate_random_str)为自定义的一个生成随机字符串的方法。
    image_name = generate_random_str() + '.jpg'
    image_path = './image/'
    # 把系统截到的图像放在本地的一个文件夹中
    frame.img.save(image_path + image_name)
    # 此处拿到截图后, 上传至七牛云
    url = upload_qiniu.upload(image_name, image_path)
    # 把图像的url格式化成md中插入图片的格式
    md_url = '![{}]({})'.format(image_name, url)
    print(md_url)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    3.3 windows提示框实现

    • 嘘~~莫说批话
    # 用于弹出提示
    from plyer import notification
    notification.notify(title='阮超越的mini-typora',  \
    message='剪切图片成功,地址:{}' \
    .format(md_url), timeout=5)
    
    • 1
    • 2
    • 3
    • 4
    • 5

    3.4 设置windows剪切板

    import pyperclip
    msg = '我是一个没有用的人'
    pyperclip.copy(msg)
    
    • 1
    • 2
    • 3

    3.5 通过kayboard模块设置快捷键并监听

    import keyboard
    print('Press and release your desired hotkey: ')
    hotkey = keyboard.read_hotkey()
    print('Hotkey selected: ', hotkey)
    keyboard.add_hotkey(hotkey, shot)
    keyboard.wait()
    print("Press ESC to stop.")
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 代码这么写的目的只有一个,那就是每次启动脚本都可以手动设置快捷键,写死得话万一和其它快捷键冲突,还要反复调整,比较麻烦。

    3.6 整个脚本流程

    • 这一部分是整个脚本的运转,过程也不复杂,注意理解就行。
    import random
    # python键盘监听模块
    import keyboard
    # python GUI模块
    import wx
    # 我自己写的七牛云上传文件
    import upload_qiniu
    # 操作windows剪切板
    import pyperclip
    
    # 七牛云, 用于上传图片
    import qiniu
    
    # 用于弹出提示
    from plyer import notification
    
    # 屏幕截图的小脚本
    from ScreenShot import ScreenShot
    
    # 生成随机字符串的函数
    def generate_random_str(randomlength=16):
        random_str =''
        base_str ='ABCDEFGHIGKLMNOPQRSTUVWXYZabcdefghigklmnopqrstuvwxyz0123456789'
        length =len(base_str) -1
        for i in range(randomlength):
            random_str +=base_str[random.randint(0, length)]
        return random_str
    # 截图操作函数
    def shot():
        app = wx.App(False)
        frame = ScreenShot(None)
        app.MainLoop()
        # 将截图保存
        image_name = generate_random_str() + '.jpg'
        image_path = './image/'
        frame.img.save(image_path + image_name)
        # 此处拿到截图后, 上传至七牛云
        url = upload_qiniu.upload(image_name, image_path)
        md_url = '![{}]({})'.format(image_name, url)
        print(md_url)
        pyperclip.copy(md_url)
        # 发出windows提示 上传成功了
        notification.notify(title='阮超越的mini-typora', message='剪切图片成功,地址:{}'.format(md_url), timeout=5)
    
    if __name__ == '__main__':
        print('Press and release your desired hotkey: ')
        hotkey = keyboard.read_hotkey()
        print('Hotkey selected: ', hotkey)
        # shot回调函数
        keyboard.add_hotkey(hotkey, shot)
        keyboard.wait()
        print("Press ESC to stop.")
    
    • 1
    • 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

    4. 代码提供

    https://gitee.com/qkmc/mini-typora

    5. 赏口饭吃

    请添加图片描述

  • 相关阅读:
    Linux—软件管理
    较真儿学源码系列-PowerJob启动流程源码分析
    LeetCode第100题—相同的树
    9.14黄金是否会继续下跌?后市如何布局?
    中国高端水果元宇宙
    记录nvm use node.js版本失败,出现报错: exit status 1: ��û���㹻��Ȩ��ִ�д˲�����
    will be initialized after [-Werror=reorder]
    微信小程序 checkbox 实现双向绑定以及特殊交互处理
    Java手写注解处理器和案例拓展
    Java中的set集合如何理解——精简
  • 原文地址:https://blog.csdn.net/ruankun521/article/details/126731069