45  SAS内核输出调整

45.1 流程

45.2 获取notebook生成的html文件每个code单元格和output的字典

有些code是没有output的,因此所有代码单元格和输出要一一对应,哪怕是空的。

规律是:<div class="sourceCode cell-code">后面接<div class="cell-output cell-output-stdout"> 和/或 <div class="cell-output cell-output-display"> 或者是两者均无。

# 打开notebook生成的html文件

from myconfig import book_path

from bs4 import BeautifulSoup

html_file = 'sas-ttest.html'
with open(html_file) as f:
    content = f.read()

soup = BeautifulSoup(content, 'html.parser')


# 找到所有的 cell-output cell-output-stdout 元素并删除它们,因其占据在'sourceCode cell-code'的next_sibling的位置,且不是重要的内容。
output_divs = soup.find_all('div', class_='cell-output cell-output-stdout')
for div in output_divs:
    div.extract()
    


# 找到所有的 sourceCode cell-code 元素
source_code_divs = soup.find_all('div', class_='sourceCode cell-code')

# 创建一个字典,用于存储每个 sourceCode cell-code 对应的 cell-output cell-output-display 元素
result_dict = {}

# 遍历每个 sourceCode cell-code 元素
for i, div in enumerate(source_code_divs):
    # 找到当前 sourceCode cell-code 元素后面的第一个 cell-output 元素
    next_output_div = div.find_next_sibling(['div'], class_= 'cell-output cell-output-display')
    
    # 如果找到了 cell-output 元素,则将其文本内容添加到字典中
    if next_output_div:
        # 删除所有output的style元素,,以防止干扰父页面
        style_element = next_output_div.find('style')
        if style_element:
            style_element.extract()
            
        result_dict[i] = next_output_div
    


# 修改第1个output的style,以添加表格的边框线
first_key = next(iter(result_dict.keys()))

result_dict[first_key]['style'] = '''
              table {
                border-collapse: collapse;
              }
        
              td, th {
                border-right: 1px solid grey;
              }
        '''

45.3 对号入座写入quarto notebook (.qmd)生成的html文件

将上述字典的值插入至<div class="sourceCode cell-code">元素的后面。

# 打开quartobook生成的html文件

with open(f"{book_path}/pyln/{html_file}") as f:
    content = f.read()

soup = BeautifulSoup(content)

code_div_list = soup.find_all('div', class_= 'sourceCode cell-code')  


# 在每个code_div后面添加output
for i, code_div in enumerate(code_div_list):
    if result_dict.get(i):
        code_div.insert_after(result_dict[i])


# 将 Beautiful Soup 对象转换为 HTML 字符串
updated_html = soup.prettify()

# 将更新后的 HTML 写回原始的 HTML 文件
with open(f"{book_path}/pyln/{html_file}", "w") as f:
    f.write(updated_html)

45.4 打包成脚本

# sas_output_adjust.py文件的内容

# 打开notebook生成的html文件

from myconfig import book_path
import sys
from bs4 import BeautifulSoup

html_file = sys.argv[1]


with open(html_file) as f:
    content = f.read()

soup = BeautifulSoup(content, 'html.parser')


# 找到所有的 cell-output cell-output-stdout 元素并删除它们,因其占据在'sourceCode cell-code'的next_sibling的位置,且不是重要的内容。
output_divs = soup.find_all('div', class_='cell-output cell-output-stdout')
for div in output_divs:
    div.extract()
    


# 找到所有的 sourceCode cell-code 元素
source_code_divs = soup.find_all('div', class_='sourceCode cell-code')

# 创建一个字典,用于存储每个 sourceCode cell-code 对应的 cell-output cell-output-display 元素
result_dict = {}

# 遍历每个 sourceCode cell-code 元素
for i, div in enumerate(source_code_divs):
    # 找到当前 sourceCode cell-code 元素后面的第一个 cell-output 元素
    next_output_div = div.find_next_sibling(['div'], class_= 'cell-output cell-output-display')
    
    # 如果找到了 cell-output 元素,则将其文本内容添加到字典中
    if next_output_div:
        # 删除所有output的style元素,,以防止干扰父页面
        style_element = next_output_div.find('style')
        if style_element:
            style_element.extract()
            
        result_dict[i] = next_output_div
    


# 修改第1个output的style,以添加表格的边框线 @ 没有实现边框的功能,待排查及改进 @ 实际效果还可以,暂不着急改变。
first_key = next(iter(result_dict.keys()))

result_dict[first_key]['style'] = '''
              table {
                border-collapse: collapse;
              }
        
              td, th {
                border-right: 1px solid grey;
              }
        '''


# 打开quartobook生成的html文件

with open(f"{book_path}/pyln/{html_file}") as f:
    content = f.read()

soup = BeautifulSoup(content, features="lxml")

code_div_list = soup.find_all('div', class_= 'sourceCode cell-code')  


# 在每个code_div后面添加output
for i, code_div in enumerate(code_div_list):
    if result_dict.get(i):
        code_div.insert_after(result_dict[i])


# 将 Beautiful Soup 对象转换为 HTML 字符串
updated_html = soup.prettify()

# 将更新后的 HTML 写回原始的 HTML 文件
with open(f"{book_path}/pyln/{html_file}", "w") as f:
    f.write(updated_html)


print(f"{html_file}完成SAS输出调整。")

45.4.1 执行命令

jupyter文件放在notebooks文件夹,py文件也放在该notebook文件夹

cd notebook
python sas_output_adjust.py sas-chisquaretest.html