Jupyter中以复制粘贴的形式插入的图片(attachment)导出到md时不显示问题的解决办法(转换为网络图片)

问题描述

本人编写Jupyter Notebook的时候,经常参考其他网站或者书中的图片,因此常常将相应的截图粘贴到Jupyter Notebook 或Jupyter Lab中,但是当需要导出为markdown的时候发现导出后图片无法显示。

例如,将截图直接粘贴到jupyter的markdown单元格中时,直接粘贴的结果如下图所示

运行后显示正确图片

但是,当将Jupyter Notebook导出为markdown后,在markdown文件中无法正确显示

经过查询得知,在Jupyter以粘贴截图的方式插入图片,图片实际是以附件的方式存储在jupyter中。

用vscode打开此ipynb文件,并右键点击Reopen Editor With,选中Text Editor模式,可以看到实际上ipynb是以json格式存储的文本文件(用记事本打开也可以)。

其中此图片对应的cell部分为:

而更换为网络链接后就可以正常显示了,此时对应的cell为

因此,只需要将所有的attachments方式粘贴的图片转换为网络链接,然后再导出到md中就可以正常显示了。

前提:配置Picgo图床服务

本人利用Typora编辑笔记,并结合Picgo设置了图片自动上传机制,选择的是腾讯云cos对象存储服务。

这不是本文的重点,可以参考下面的博客进行设置,本文的方法只要通过Picgo设置了自动上传服务即可,不一定必须是腾讯云。

手把手教你Typora图床配置(PicGo+阿里云OSS/腾讯云COS)_孙不坚1208的博客-CSDN博客

处理程序详解

代码思路如下:

首先以json格式打开文件遍历cell,其中有attachments的就是我们的处理对象cell中source部分存储图片附件的名称,因此一次提取各个附件名称,在attachments中找到对应base64数据将图片数据通过Picgo的默认接口36677上传,返回值为上传后的图片网络链接,替换json文件中图片为在线图片。删除原json文件中attachments部分。将json数据写回文件

"""

将jupyter 的 markdown单元格中以复制粘贴形式插入的图片转换成图床图片

![image.png](attachment:cc48e68c-db89-4481-9f84-9900c4759344.png) ----> ![png](https://***.png)

"""

import os

import re

import json

import fire

import base64

import requests

headers = {'Content-Type':'application/json'}

def get_json_data(filename):

dicts = {}

with open(filename, 'r', encoding = 'utf-8') as f:

ipynb_content = json.load(f)

cells = ipynb_content["cells"]

for cell in cells:

sources = cell['source']

if "attachments" in cell:

attachments = cell['attachments']

for idx, source in enumerate(sources):

attachment = 0

while(True):

attachment = source.find('attachment:', attachment)

if attachment==-1:

break

imageidx = attachment + 11

rbracket = source.find(')', imageidx)

imagename = source[imageidx:rbracket]

print(imagename)

value = attachments[imagename]

for data_type, base64data in value.items(): # 其实应该就一个key,valule

if "image" in data_type: # image/png image/jpeg

# print (key, data_type, base64data[:10])

pic_data = base64.b64decode(base64data)

if "png" in data_type:

with open('temp.png', 'wb')as f:

f.write(pic_data)

if "jpeg" in data_type:

with open('tmp.jpeg', 'wb') as f:

f.write(pic_data)

cur_path = os.path.abspath('./temp.png')

datas = json.dumps({'list': [cur_path]})

response = requests.post('http://127.0.0.1:36677/upload', data=datas, headers=headers)

result = response.json()['result']

# print(result[0])

url = result[0]

print(url)

print(source[attachment:rbracket])

sources[idx] = source.replace(source[attachment:rbracket],url)

# print(sources[idx])

attachment = rbracket + 1

cell.pop('attachments')

# print(cell)

ipynb_content['cells'] = cells

# dicts = ipynb_content

with open(filename, 'w', encoding = 'utf-8') as w:

# print(dicts)

json.dump(ipynb_content, w, indent = 1, ensure_ascii=False)

if __name__ == '__main__':

fire.Fire(get_json_data)

运行示例

运行前首先要开启picgo应用,否则无法使用其上传服务。

本程序使用的是picgo的上传服务,只要picgo中配置好了图床,均可使用

上图所示的ipynb文件中有两个png图片,一个jpeg图片,均为复制粘贴形式插入,均成功转换为在线链接,导出md后均可正常显示。

附:其他方式插入的图片导出问题

如果是利用matplotlib生成的图片导出md时,会以压缩包的形式导出,图片以压缩包内的相对路径形式在md中引用,此时利用typora的一键上传本地图片的功能也可以转换为在线链接。具体点击"格式"——“图像”——“上传所有本地图像”

其他的方式比如标签,无论是绝对路径还是相对路径插入的本地图片,也都可以在导出为md后,利用配置好的typora+picgo上传服务转换为在线链接。

上传本地图片的功能也可以转换为在线链接。具体点击"格式"——“图像”——“上传所有本地图像”

其他的方式比如标签,无论是绝对路径还是相对路径插入的本地图片,也都可以在导出为md后,利用配置好的typora+picgo上传服务转换为在线链接。

Copyright © 2088 樊振东世界杯_世界杯开幕 - tyzksb.com All Rights Reserved.
友情链接