【问题标题】:Alternative of orca for creating PDF file with images and figures替代 orca 用于创建带有图像和图形的 PDF 文件
【发布时间】:2019-10-03 12:55:52
【问题描述】:

我正在使用这个脚本来创建 pdf 文件并附加带有统计信息的图像:

import MySQLdb
from plotly import graph_objs as go
import numpy as np
import os
from plotly.subplots import make_subplots
from PyPDF2 import PdfFileMerger
from datetime import datetime, timedelta
import smtplib
from email.message import EmailMessage
import imghdr

# Database connect
db = MySQLdb.connect(host="localhost",
                     user="root",
                     passwd="****",
                     db="ofasorgu_10_168_1_71")

today = datetime.today().strftime('%Y-%m-%d')
one_week = (datetime.today() - timedelta(days=7)).strftime('%Y-%m-%d')
two_week = (datetime.today() - timedelta(days=14)).strftime('%Y-%m-%d')
three_week = (datetime.today() - timedelta(days=21)).strftime('%Y-%m-%d')
four_week = (datetime.today() - timedelta(days=28)).strftime('%Y-%m-%d')

# Functions
def load_post_views(table, today, one_week, two_week, three_week, four_week):

    product_views_dict = dict()

    cursor = db.cursor()
    cursor.execute(
        "SELECT client_id, product_id, referrer, `date`" +
        " FROM " + table + 
        " WHERE `date`>='"+four_week+"'")

    for x in range(0, cursor.rowcount):

        row = cursor.fetchone()
        network = ""
        period = ""
        client_id = row[0]
        product_id = row[1]
        referrer = row[2]
        date = str(row[3])

        email_cursor = db.cursor()
        email_cursor.execute("SELECT address FROM c8ty_connections_email WHERE entry_id=" + str(client_id))
        email = email_cursor.fetchone()

        product_cursor = db.cursor()
        product_cursor.execute("SELECT post_title FROM c8ty_posts WHERE id=" + str(product_id))
        product_name = product_cursor.fetchone()

        # Add client ID key
        if client_id not in product_views_dict:
            product_views_dict[client_id] = dict()

        # Add product ID key to client ID parent key 
        if product_id not in product_views_dict[client_id]:
            product_views_dict[client_id][product_id] = {
                today + " - " + one_week: {
                    "facebook": 0,
                    "twitter": 0,
                    "instagram": 0,
                    "linkedin": 0,
                    "pinterest": 0,
                    "website": 0,
                },
                one_week + " - " + two_week: {
                    "facebook": 0,
                    "twitter": 0,
                    "instagram": 0,
                    "linkedin": 0,
                    "pinterest": 0,
                    "website": 0,
                },
                two_week + " - " + three_week: {
                    "facebook": 0,
                    "twitter": 0,
                    "instagram": 0,
                    "linkedin": 0,
                    "pinterest": 0,
                    "website": 0,
                },
                three_week + " - " + four_week: {
                    "facebook": 0,
                    "twitter": 0,
                    "instagram": 0,
                    "linkedin": 0,
                    "pinterest": 0,
                    "website": 0,
                }
            }

        # Find referrer
        if "facebook" in referrer:
            network = "facebook"
        elif "twitter" in referrer:
            network = "twitter"
        elif "instagram" in referrer:
            network = "instagram"
        elif "linkedin" in referrer:
            network = "linkedin"
        elif "pinterest" in referrer:
            network = "pinterest"
        else:
            network = "website"

        # Check view period
        if date <= today and date > one_week:
            period = today + " - " + one_week
        if date <= one_week and date > two_week:
            period = one_week + " - " + two_week
        if date <= two_week and date > three_week:
            period = two_week + " - " + three_week
        if date <= three_week and date > four_week:
            period = three_week + " - " + four_week

        product_views_dict[client_id][product_id][period][network] += 1 
        product_views_dict[client_id]["email"] = email[0]
        product_views_dict[client_id][product_id]["product"] = product_name[0]

    return product_views_dict

def draw_statistic(data_dict):
    for clinetID, product_info in data_dict.items():

        client_email = product_info["email"]

        for productID, product_data in product_info.items():

            if type(product_data) is dict:

                product_name = product_data['product']
                table_data = [
                    [
                        today      + " - " + one_week,
                        one_week   + " - " + two_week,
                        two_week   + " - " + three_week,
                        three_week + " - " + four_week,
                        today      + " - " + four_week
                    ]
                ]

                total_one = []
                total_two = []
                total_three = []
                total_four = []
                overall_traces = []

                networks_and_positions = [
                    {"network": "website","row": 2,"col": 1},
                    {"network": "linkedin","row": 2,"col": 2},
                    {"network": "facebook","row": 3,"col": 1},
                    {"network": "twitter","row": 3,"col": 2},
                    {"network": "instagram","row": 4,"col": 1},
                    {"network": "pinterest","row": 4,"col": 2}
                ]

                fig = make_subplots(rows=5, cols=2)
                merge_fig = make_subplots(rows=1, cols=1)
                count = 2

                for dictionary in networks_and_positions:

                    network = dictionary['network']
                    row = dictionary['row']
                    col = dictionary['col']

                    total_one.append(product_data[today + " - " + one_week][network])
                    total_two.append(product_data[one_week + " - " + two_week][network])
                    total_three.append(product_data[two_week + " - " + three_week][network])
                    total_four.append(product_data[three_week + " - " + four_week][network])

                    table_data.append([
                        product_data[today + " - " + one_week][network],
                        product_data[one_week + " - " + two_week][network],
                        product_data[two_week + " - " + three_week][network],
                        product_data[three_week + " - " + four_week][network],
                        sum([
                            product_data[today + " - " + one_week][network],
                            product_data[one_week + " - " + two_week][network], 
                            product_data[two_week + " - " + three_week][network], 
                            product_data[three_week + " - " + four_week][network]
                        ])
                    ])

                    xaxis = [
                                today      + " - " + one_week,
                                one_week   + " - " + two_week,
                                two_week   + " - " + three_week,
                                three_week + " - " + four_week,
                            ]

                    yaxis = [
                                product_data[today + " - " + one_week][network],
                                product_data[one_week + " - " + two_week][network],
                                product_data[two_week + " - " + three_week][network],
                                product_data[three_week + " - " + four_week][network]
                            ]

                    chart_name = network.capitalize() + " statistic" 

                    # Create bar chart
                    if (count == 2):
                        social_fig = go.Bar(
                                x=xaxis,
                                y=yaxis,
                                name=chart_name
                            )
                    else:
                        social_fig = go.Bar(
                                x=xaxis,
                                y=yaxis,
                                name=chart_name,
                                yaxis="y"+str(count)
                            ) 

                    # Add chart to fig
                    fig.add_trace(
                            social_fig,
                            row=row,
                            col=col
                        )

                    count += 1

                    trace_name = network.capitalize() + " views"
                    overall_traces.append(
                            go.Scatter(
                                x=xaxis,
                                y=yaxis,
                                name=trace_name
                            )
                        )

                total_column_values_array = [sum(total_one), sum(total_two), sum(total_three), sum(total_four),]

                total_column_values_array.append(
                        sum(total_one)+sum(total_two)+sum(total_three)+sum(total_four)
                    )

                table_data.append(total_column_values_array)

                # Create product table
                fig.add_trace(
                    go.Table(
                        header=dict(values=["Period", "Website", "Facebook", "Twitter", "Instagram", "LinkedIn", "Pinterest", "Total"]),
                        cells=dict(values=table_data)
                    )
                )

                merge_fig.add_traces(overall_traces)

                # Craete folder if doesn't exist
                if not os.path.exists("files"):
                    os.mkdir("files")

                statistic_file = "files/statistic_"+product_name+".pdf"
                overall_file = "files/overall_"+product_name+".pdf"
                out_file = "files/"+product_name+"_statistic.pdf"
                # Create charts file
                fig.update_layout(height=1500, width=1000, title_text="<b>Greetings</b><br />This is statistic from <a href='https://www.cfasuk.co.uk/'>CFAS UK</a> for your product <b>"+product_name+"</b>")
                fig.update_layout(
                        yaxis3=dict(title="Website views", titlefont=dict(color="#636efa")),
                        yaxis4=dict(title="LinkedIn views", titlefont=dict(color="#ef553b")),
                        yaxis5=dict(title="Facebook views", titlefont=dict(color="#00cc96")),
                        yaxis6=dict(title="Twitter views", titlefont=dict(color="#b780f9")),
                        yaxis7=dict(title="Instagram views", titlefont=dict(color="#ffa15a")),
                        yaxis8=dict(title="Pinterest views", titlefont=dict(color="#19d3f3")),
                    )
                fig.write_image(statistic_file)
                # Create overall file
                merge_fig.update_layout(height=700, width=1000, title_text="Overall <b>"+product_name+"</b> statistic")
                merge_fig.write_image(overall_file)
                merge = PdfFileMerger(strict=False)
                # Append charts file to merger
                merge.append(statistic_file)
                # Append overall file to merger
                merge.append(overall_file)
                # Create end statistic file with both charts and overall
                merge.write(out_file)
                merge.close()
                # Delete statistic file
                os.remove(statistic_file)
                # Delete overall file
                os.remove(overall_file)
                # Send email with file
                send_mail(
                    "tomaivanovtomov@gmail.com", 
                    "tomaivanovtomov@gmail.com", 
                    "CFAS UK, "+product_name+" statistic",
                    "This is automated email. Please, do not reply!<br/>"+
                    "If you find some problem with the statistic or the product is not yours, please contact CFAS UK team.<br/>"+
                    "Best regards!",
                    out_file
                )

def send_mail(send_from, send_to, subject, text, file=None):
    with smtplib.SMTP_SSL('smtp.gmail.com', 465) as smtp:

        smtp.login("tomaivanovtomov@gmail.com", "zmjquvphuvigqdai")

        msg = EmailMessage()
        msg['Subject'] = subject
        msg['From'] = send_from
        msg['To'] = send_to
        msg.set_content(text)

        with open(file, "rb") as f:
            file_data = f.read()
            file_name = f.name
            msg.add_attachment(file_data, maintype='application/pdf', subtype='pdf', filename=file_name)

        smtp.send_message(msg)

# Init
product_views_dict = load_post_views("an_product_view", today, one_week, two_week, three_week, four_week)
brochure_views_dict = load_post_views("an_brochure_view", today, one_week, two_week, three_week, four_week)

draw_statistic(product_views_dict)
draw_statistic(brochure_views_dict)

db.close()
exit()

当我在本地服务器上测试它时它工作正常。但我需要将它上传到 Centos 服务器上的共享帐户。在我的托管服务提供商上。在那里我无法安装anaconda,我需要为静态图像安装orca。是否有替代方法来创建图像然后将其添加到 pdf 文件中?先感谢您!

【问题讨论】:

  • 如果您在此处添加代码,请提供minimal reproducible example。在这种情况下,请专注于“最小”。这是太多的代码 - 尽管可能根本不需要它来回答问题。
  • 询问工具和库对于本网站来说是题外话。赏金到期后,我将投票关闭并删除它。
  • 最后一点,我认为在任何语言(包括 python)中连接 SQL 字符串都是一个非常糟糕的主意。它不受欢迎,因为它通常会启用 SQL 注入攻击。 MySQL 应该有参数化的 SQL 语句。
  • 我忘记了程序员可能非常敏感......加上 SQL 是这样制作的,因为脚本不会从外部源中触及。所以不用担心它的脆弱性。
  • @ThomasWeller 这不是关于工具的问题。它关于代码库集成。如何以正确的方式使用 plotly 和好的替代方案(用于使用库中的函数)用于 plotly 使用的内容(作为后端)

标签: python plotly orca


【解决方案1】:

是的(您不需要在代码中使用任何工具后端依赖项),有一个非常简单的替代库示例,如下所示。

您可以为此使用 matplotlib 集成。

您可以如下图所示导入这些模块

from plotly.offline import init_notebook_mode, plot_mpl
import matplotlib.pyplot as plt

你可以像下面这样使用它们:

init_notebook_mode()
fig = plt.figure()
# you can configure you plot here  use below to save it as image

plot_mpl(fig)
plot_mpl(fig, image='png')

或者,如果您仍然想只坚持情节并寻找替代方案,您可以看到下面

您可以使用plotly的离线模块在服务器上生成静态图像并使用它来生成PDF。您可以使用from plotly.offline import plot 导入它。导入后,您可以使用以下绘图功能

fig = go.Figure( data=data, layout=layout )
plot( fig, filename='your-file-name' , image = 'png')

【讨论】:

    【解决方案2】:

    如果您使用 Plotly,您可以安装 kaleido,它将使用它而不是 orca 来生成静态图像。

    如果你只能通过 pip 安装你的包,这很好。

    【讨论】:

      猜你喜欢
      • 2020-07-22
      • 1970-01-01
      • 1970-01-01
      • 2011-05-27
      • 1970-01-01
      • 1970-01-01
      • 2017-03-16
      • 1970-01-01
      相关资源
      最近更新 更多