首页 > 解决方案 > 使用 nbconvert 将笔记本导出为 HTML 并为面板(散景、holoviews、hvplot)嵌入数据

问题描述

我正在尝试将笔记本导出为 HTML,笔记本内部有多个交互式面板。

import panel as pn
import hvplot as hv
import holoviews as hv2
from bokeh.io import output_notebook, push_notebook, show, save, output_file
from bokeh.resources import INLINE

def plot_ts(feature=Spends[0], target=Target[0]):
    fig = df[target].plot.line(title=target)
    fig += df[feature].plot.area(title=feature)
    
    return fig.cols(1)

kw = dict(feature=sorted(list(Spends + Misc)))
panel1 = pn.interact(plot_ts, **kw)
panel1

现在我正在运行以下行:

!jupyter nbconvert --to html index.ipynb --no-input --no-prompt

问题是我的面板变得陈旧(相应的数据未嵌入其中)。
如果我使用以下行一一保存面板,我将获得带有嵌入数据的面板。

panel1.save('test.html', embed=True, resources=INLINE)

我尝试以这种方式保存所有面板,然后使用 Selenium 合并不同的 HTML 文件,但它不起作用。

我尝试将面板附加到彼此

all_panels.append(panel1).append(panel2).append(panel3)
all_panels.save("all_panels.html", embed=True)

生成的 HTML 文件有问题,一些面板可以工作,而另一些则不能。

如果有人对如何使这项工作有任何想法,那将是惊人的。
谢谢

标签: jupyter-notebookbokehpanelholoviewsnbconvert

解决方案


使用 BeautifulSoup,我设法创建了一个 HTML 文件,其中包含保存为独立 html 文件及其嵌入数据的不同面板。
我认为它可能对其他人有用,所以这里是代码:

# Imports
from bs4 import BeautifulSoup, Tag
import glob

# List the filepaths corresponding to panels exported to html using 'panel_object.save("panel_name.html", embed=True)'
panels = glob.glob("/Users/username/Documents/data_exploration/panels/*.html")
panels_soup = []

# Read files and append their soup to a list
for panel in panels:
    with open(panel) as fp:
        panel = BeautifulSoup(fp, 'html.parser')
        panels_soup.append(panel)

# HTML base
soup = BeautifulSoup()
html = soup.new_tag("html")
soup.append(html)

# Append the head tag of one of the panels (it includes the bokeh/holoviews scripts)
soup.html.append(panels_soup[0].find("head"))

# Append an empty body tag
body = soup.new_tag("body")
soup.html.append(body)

# Loop on soups
for panel in panels_soup:
    divs = panel.find_all("div", attrs={"class":"bk-root"})
    data = panel.find_all('script')[-2]
    script = panel.find_all('script')[-1]
    panels_dict.append({"div_1":divs[0], "div_2":divs[-1], "data":data, "script":script})

# Append panels divs to the body of the page
for panel in panels_dict:
    soup.body.insert(1, panel["div_2"])
    soup.body.insert(1, panel["div_1"])

# Append the data at the end of the page
for panel in panels_dict:
    soup.body.insert(len(soup.body.contents), panel["data"])

# Append the scripts at the end of the page  
for panel in panels_dict:
    soup.body.insert(len(soup.body.contents), panel["script"])

# Export HTML file containing all the panels
with open("index.html", "w") as fp:
    fp.write(soup.prettify(formatter="html"))

推荐阅读