天天看点

动手写Python程序将图片嵌入Markdown动手写Python程序将图片嵌入Markdown

动手写Python程序将图片嵌入Markdown

理想很丰满,现实很骨感,根据CSDN博客测试,他的编辑器无法接受太大的Markdown文本,测试500KB的文本已经有了图片显示不全的问题,这里提到的方法大家看看就好o(╥﹏╥)o,或许可以考虑下图片压缩

1 前情提要

写技术文档或者做个简单的笔记用Markdown简直在舒服不过了,但是Markdown的图片插入缺非常让人难受。目前Markdown支持三种图片插入方式:

  1. 插入图片的网络URL
    ![desc](http://example.png)
               
  2. 插入本地相对或绝对路径
    ![desc](c:\example.png)
               
  3. 插入图片数据Base64
    ![desc](data:image/png;base64,iVBORw0KGgo...)
    <!--由于这样做非常不利于观赏性,可以按照下面数据链接的方式改写,注意其中的小括号变为了中括号-->
    
    ![desc][link_name1]
    <!--文件末尾写下面-->
    [link_name1]:data:image/png;base64,iVBORw0KGgo...
               

第一种方式将图片存储在网络上,便于文档的分享,不论Markdown文档到了哪里,只要有网络都可以正常显示图片,但是存在一个巨大的问题,那就是存放图片的服务器的稳定性无法保证,低质量的图床可能没有多久就找不到你上传的图片了。

第二种方式不便于将文档进行网络共享(比如发博客),向他人共享文档需要将图片文件一同共享,有时还会有图片路径的问题。

第三种方式没有上面两种的缺点,但是其Markdown文本会显得很大(因为你在其中存储了能表示图片数据的字符串)

但是总的来说,对于发布博客等不是经常修改却要求图片长期稳定显示,第三种方式无疑非常Good。

2 动手

2.1 思路

  • 从Markdown文件中通过正则找到插入图片的语法,并从中提取出图片路径(当前版本只支持本地图片,对我来说足够了,感兴趣的同学可以使用requests之类的方法从网络上获取图片)
  • 使用

    PIL

    打开找到的图片文件,然后

    base64

    BytesIO

    获取图片的Base64编码
  • 使用链接名替换图片路径,并在文件末尾添加数据链接。

2.2 代码

requirements:

  • python3.x
  • PIL
from PIL import Image
import base64
from io import BytesIO
import re
import sys

def main(filename, encoding='utf-8'):
    filenew = filename[0:-3]+'_new.md'
    data_url = []
    with open(filename,'r',encoding=encoding) as f:
        with open(filenew,'w',encoding=encoding) as fn:
            for line in f:
                img_sents = re.findall(r'!\[[^[\]]*\]\(.+\)$',line.strip())
                if not img_sents:
                    fn.write(line)
                else:
                    for img_sent in img_sents:
                        start_index = img_sent.find('(')
                        end_index = img_sent.rfind(')')
                        img_path = img_sent[start_index+1:end_index]
                        try:
                            img = Image.open(img_path)
                            output_buffer = BytesIO()
                            if img_path.upper().endswith('JPG'):
                                file_format = 'JPEG'
                            elif img_path.upper().endswith('PNG'):
                                file_format = 'PNG'
                            img.save(output_buffer, format=file_format)
                            byte_data = output_buffer.getvalue()
                            base64_str = base64.b64encode(byte_data)
                            img_str = 'data:image/jpeg;base64,' + str(base64_str, encoding='utf-8')
                            data_url.append(img_str)
                            fn.write(line.replace('('+img_path+')','[link%d]'%len(data_url)))
                        except:
                            print("img error!!")
                            print(img_path)
            fn.write('\n\n')
            for i,data in enumerate(data_url):
                fn.write('[link%d]:%s\n'%(i+1,data))

    print('Done!')
    print('Process %d imgs'%len(data_url))
    return

if __name__ == '__main__':
    if len(sys.argv) == 1 or not str(sys.argv[1]).endswith('md'):
        print('wrong arg!!')
        exit()
    if len(sys.argv) == 3:
        if str(sys.argv[2]).lower() not in ['utf-8','gbk']:
            print('wrong arg!!')
        else:
            main(*sys.argv[1:])
    else:
        main(sys.argv[1])
           

2.3 测试

原始文档:

动手写Python程序将图片嵌入Markdown动手写Python程序将图片嵌入Markdown

处理过程:

动手写Python程序将图片嵌入Markdown动手写Python程序将图片嵌入Markdown

处理后文档:

动手写Python程序将图片嵌入Markdown动手写Python程序将图片嵌入Markdown

3 总结

理想很丰满,现实很骨感,根据CSDN博客测试,他的编辑器无法接受太大的Markdown文本,测试500KB的文本已经有了图片显示不全的问题,这里提到的方法大家看看就好o(╥﹏╥)o