在pyecharts中将html导出为png使用phantomjs的方式

文章目录

    • 1. 安装phantomjs
    • 2. 官方使用方法:
    • 3. 如果只是自己测试到这就算完成了,下面为部署到生产环境时遇到的一些问题
        • 1. 我需要将生成的图片发送到企业微信中,但是生成的文件过大,企业微信最大允许发送2M的图片
        • 2. 线上是在容器中部署的服务,当执行生成图片时报错:
        • 3. 在本地发送图片没问题,到了容器中phantomjs将html转换成图片时乱码,缺少文字库
        • 4. 过了个国庆节回来发现代码没有任何变动但是不能用了,生成的html可以打开,但是转换成图片就报错:"ReferenceError: Can't find variable: echarts\n\n undefined:1\nnull\n"
        • 5. 生成的图片的背景是一堆的灰色方格,想要修改图片的背景颜色怎么办呢?

1. 安装phantomjs

  1. pip install snapshot-phantomjs
  2. 下载phantomjs安装包,参见:https://phantomjs.org/download.html,不同系统下载不同的包
  3. 将下载下来的包解压后的bin目录下的二进制文件放到你的$PATH中,查看$PATH的方式: echo $PATH,这里我是放到了/usr/local/bin下
    cp phantomjs-2.1.1-linux-x86_64/bin/phantomjs /usr/local/bin/phantomjs && chmod +x /usr/local/bin/phantomjs

2. 官方使用方法:

下面是官方的例子,我进行了一些小小的修改,允许执行宽和高,背景颜色,以及js的路径
from pyecharts import options as opts
from pyecharts.charts import Bar
from pyecharts.render import make_snapshot

from snapshot_phantomjs import snapshot

def bar_chart() -> Bar:
    c = (
        Bar(init_opts=opts.InitOpts(width=width, height=height, bg_color="white", js_host=file_path))
        .add_xaxis(["衬衫", "毛衣", "领带", "裤子", "风衣", "高跟鞋", "袜子"])
        .add_yaxis("商家A", [114, 55, 27, 101, 125, 27, 105])
        .add_yaxis("商家B", [57, 134, 137, 129, 145, 60, 49])
        .reversal_axis()
        .set_series_opts(label_opts=opts.LabelOpts(position="right"))
        .set_global_opts(title_opts=opts.TitleOpts(title="Bar-测试渲染图片"))
    )
    return c

make_snapshot(snapshot, bar_chart().render(), "bar.png")

3. 如果只是自己测试到这就算完成了,下面为部署到生产环境时遇到的一些问题

1. 我需要将生成的图片发送到企业微信中,但是生成的文件过大,企业微信最大允许发送2M的图片
  1. 先安装图像处理库pip3 install pillow
  2. 对图片进行压缩代码:
from PIL import Image
import os


def get_size(file):
    # 获取文件大小:KB
    size = os.path.getsize(file)
    return size / 1024


def get_outfile(infile, outfile):
    if outfile:
       return outfile
    dir, suffix = os.path.splitext(infile)
    outfile = '{}-out{}'.format(dir, suffix)
    return outfile


def compress_image(infile, outfile='', mb=150, step=10, quality=80):
    """不改变图片尺寸压缩到指定大小
    :param infile: 压缩源文件
    :param outfile: 压缩文件保存地址
    :param mb: 压缩目标,KB
    :param step: 每次调整的压缩比率
    :param quality: 初始压缩比率
    :return: 压缩文件地址,压缩文件大小
    """
    o_size = get_size(infile)
    if o_size <= mb:
        return infile
    while o_size > mb:
        im = Image.open(infile)
        im.save(outfile, quality=quality)
        if quality - step < 0:
            break
        quality -= step
        o_size = get_size(outfile)
    return outfile, get_size(outfile)
2. 线上是在容器中部署的服务,当执行生成图片时报错:
Auto configuration failed
140149858578048:error:25066067:DSO support routines:DLFCN_LOAD:could not load the shared library:dso_dlfcn.c:185:filename(libssl_conf.so): libssl_conf.so: cannot open shared object file: No such file or directory
140149858578048:error:25070067:DSO support routines:DSO_load:could not load the shared library:dso_lib.c:244:
140149858578048:error:0E07506E:configuration file routines:MODULE_LOAD_DSO:error loading dso:conf_mod.c:285:module=ssl_conf, path=ssl_conf
140149858578048:error:0E076071:configuration file routines:MODULE_RUN:unknown module name:conf_mod.c:222:module=ssl_conf
  • 解决方案:
    • export OPENSSL_CONF=/dev/null
    • 重新执行就可以生成图片了
3. 在本地发送图片没问题,到了容器中phantomjs将html转换成图片时乱码,缺少文字库
  • 解决方案:
    • 在centos中执行:
      yum install -y bitmap-fonts bitmap-fonts-cjk

    • 在ubuntu中执行:
      sudo apt-get install -y xfonts-wqy

4. 过了个国庆节回来发现代码没有任何变动但是不能用了,生成的html可以打开,但是转换成图片就报错:“ReferenceError: Can’t find variable: echarts\n\n undefined:1\nnull\n”
  • 排错:
    • 搜索有人说是需要代码的执行路径中不能包含中文,但是我本身的执行路径是没有中文的,
    • 打开html文件发现echarts的引用是通过src引用的远程地址,猜测是否是远端拉不下来,但是在本地和服务器都是可以打开的,这个也被否定了
    • 一度陷入僵局,谷歌并没有什么有用的信息
    • 突然想起以前翻源码的时候在opts.InitOpts里面可以填写js_host的地址,那么我把js下载下来是否可行呢,试了下还真可以,问题就解决了,但是为啥使用远程引用的不可以有点不太理解
  • 解决方案:
    • 1.先把远程引用的js下载到本地,和执行的文件放在同一目录下
      wget https://assets.pyecharts.org/assets/echarts.min.js
    • 2.修改配置信息生成js引用地址的时候使用本地的js
file_path = "{}/".format(os.path.dirname(os.path.abspath(__file__)))
Bar(init_opts=opts.InitOpts(width=width, height=height, bg_color="white", js_host=file_path)))

这里主要看你哪里用的init_opts这个参数,没有的话可以在实例化图像实例的时候加上这个参数
- 3.重新执行图片就生成出来了

5. 生成的图片的背景是一堆的灰色方格,想要修改图片的背景颜色怎么办呢?
  • 在生成html的时候就要进行修改,指定背景颜色,同样是
    Bar(init_opts=opts.InitOpts(width=width, height=height, bg_color="white", js_host=file_path)))
    里面的bg_color就是背景颜色,我这里指定的是白色

至此问题全部解决,Bingo.

你可能感兴趣的:(python,python,pyechart,解决方案)