ibthon notebook .png数字在nbconvert没有加载最新的chrome / firefox之后

时间:2013-09-06 23:45:38

标签: html matplotlib ipython python-3.3 ipython-notebook

在本地运行$ipython3 notebook --pylab=inline,我使用pylab和python 3.3保存了一个带有小png图形的简单笔记本。

笔记本电脑单元的内容:

from pylab import *

x = linspace(0, 5, 10)
y = x ** 2
figure()
plot(x, y, 'r')
xlabel('x')
ylabel('y')
title('title')
show()

运行单元格导致显示内联png图形。 保存的文件(my_notebook.ipynb)将.png保存为数据uri:

{ ..., "png":"iVBO...ZUmwK\n...", ... }

执行命令后

ipython3 nbconvert --to html my_notebook.html

生成my_notebook.html时,数字为数据uri,如下所示:

<img src="data:image/png;base64,b'iVBO...ZUmwk\n..." >

在最新的chrome或firefox中,在本地打开文件:///.../my_notebook.html时,图像数据uri无法加载/显示,并且chrome控制台报告'无法为img标记加载资源'。

我在加载图像时得到了相同的结果,然后用imshow()显示。 这些数字在笔记本上显得很好。在nbconvert到html之后它们不显示(根本没有)。

(注意图像数据uri中的转义换行符 - 我尝试用实际换行符替换数据字符串中所有转义的换行符,但结果没有变化)

如何让png数字显示在浏览器中本地打开的ipython笔记本的nbconverted-html版本中(“file:///.../my_notebook.html”)?

(我宁愿不用保存每个数字并手动修改转换后的html来引用磁盘上保存的数字。)

修改 版本:

python 3.3.1
ipython==1.0.0
matplotlib==1.2.1
Pillow==2.1.0 (PIL)

1 个答案:

答案 0 :(得分:0)

首先安装BeautifulSoup4

pip install BeautifulSoup4

然后使用以下函数冻结生成的html文件。图像将放在与{html文件相同的目录下的images文件夹中。

import os
import re
import base64
from bs4 import BeautifulSoup as BS
from uuid import uuid4


def dump(path, data):
    root = os.path.dirname(path)
    if not os.path.exists(root):
        os.makedirs(root)
    with open(path, 'wb') as f:
        f.write(data)
    # for windows
    return path.replace('\\', '/')


def freeze_html(path):
    '''pass in absolute path of your html'''
    root = os.path.dirname(path)
    with open(path, 'rb') as f:
        soup = BS(f.read())
    for img in soup.find_all('img'):
        m = re.search(r"data:image/png;base64,b'(.*)'", img['src'])
        if m:
            iname = uuid4()
            ipath = os.path.join(root, 'images', '%s.png' % iname)
            # remove '\n'
            s = m.group(1).replace(r'\n', '')
            img['src'] = os.path.relpath(
                dump(ipath, base64.b64decode(s.encode('ascii'))),
                root
            )
    with open(path, 'wb') as f:
        f.write(soup.encode('utf-8'))

如果您不需要进一步将其转换为tex或pdf,则只需将字符串(\n已删除)写回img['src'](带data:image/png;base64,前缀):

import re
from bs4 import BeautifulSoup as BS


def freeze_html(path):
    '''pass in absolute path of your html'''
    with open(path, 'rb') as f:
        soup = BS(f.read())
    for img in soup.find_all('img'):
        m = re.search(r"data:image/png;base64,b'(.*)'", img['src'])
        if m:
            # remove '\n'
            s = m.group(1).replace(r'\n', '')
            img['src'] = 'data:image/png;base64,' + s
    with open(path, 'wb') as f:
        f.write(soup.encode('utf-8'))

我更喜欢将png保存到单独的文件中,因为它对xelatex更友好。