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
上传服务转换为在线链接。