大家好,明天分享一个通过 Python 主动创立相干图片的教程,而这个相干图片就是《历史上的明天》,那么为啥是历史呢,因为萝卜哥是一个历史迷,从小就喜爱啃历史书,随着年龄的增长,这份激情还是没有减退~

好了闲话不都说,咱们间接上干货

数据获取

首先就是数据哪里来,我试过应用网上的一些收费历史查问接口,然而成果都不现实,这些接口不是太不稳固,就是数据不敌对。最初我还是抉择了一个精简的网站,间接扒网站页面信息即可

http://jintian.160.com/

网站很简略,也没有任何反爬措施,咱们间接抓取数据

def get_data(month, day):    result_dict = dict()    for i in range(1, 3):        url = "http://jintian.160.com/ashx/GreatThing.ashx?act=getgreatthinglist&page=%s&m=%s&d=%s&c=" % (str(i), month, day)        data = requests.get(url)        html = BeautifulSoup(data.json()["data"])        data_li = html.find_all("li")        for li in data_li:            result = deal_some(li.text)            tmp = result.split(" ")            year = tmp[0].split("年")[0]            new_day = tmp[0].split("年")[1]            result_dict[year] = tmp[1]    return result_dict, new_day

这里提供了月和天的变量,就是为了前面咱们做成 web 服务时能够方面的获取任何工夫的历史信息

而后咱们再编写一个函数,把获取到的数据转化成 DataFrame 格局

def gen_df(result_dict):    df = pd.DataFrame.from_dict(result_dict, orient='index', columns=['事件'])    df = df.reset_index().rename(columns={'index': '年份'})    return df

图片制作

对于最终生成的图片,应用的是 PyEcharts 制作,外围代码复用了《能够叫我才哥》公众号号主才哥的相干代码,上面咱们简略解析下相干代码

首先咱们明确图片根底是 Line 类型,没错就是咱们平时用的最多的折线图!

学生成 Y 轴 数据

def gen_y(data):    y_data = []    counter = 0    position = ['left', 'right']    for idx, row in data.iterrows():        msg = '{bbb|%s}\n{aaa|%s}' % (row['年份'], row['事件'])        l_item = opts.LineItem(            name=10,            value=counter,            symbol='emptyCircle',            symbol_size=10,            label_opts=opts.LabelOpts(                is_show=True,                font_size=16,                position=position[counter%2],                formatter=msg,                rich = {                    'aaa': {                        'fontSize': 18,                        'color': 'red',                        'fontWeight':'bold',                        'align':position[(counter+1)%2],                        },                    'bbb': {                        'fontSize': 15,                        'color': '#000',                        'align':position[(counter+1)%2]}}                )        )        y_data.append(l_item)        counter+=1    return y_data

应用系列配置pyecharts.options当中的LineItem类,不过很奇怪的是,这个类居然在 PyEcharts 官网中找不到,还是查看了官网源码才大略理解其作用

class LineItem(BasicOpts):    def __init__(        self,        name: Union[str, Numeric] = None,        value: Union[str, Numeric] = None,        *,        symbol: Optional[str] = "circle",        symbol_size: Numeric = 4,        symbol_rotate: Optional[Numeric] = None,        symbol_keep_aspect: bool = False,        symbol_offset: Optional[Sequence] = None,        label_opts: Union[LabelOpts, dict, None] = None,        itemstyle_opts: Union[ItemStyleOpts, dict, None] = None,        tooltip_opts: Union[TooltipOpts, dict, None] = None,    ):        self.opts: dict = {            "name": name,            "value": value,            "symbol": symbol,            "symbolSize": symbol_size,            "symbolRotate": symbol_rotate,            "symbolKeepAspect": symbol_keep_aspect,            "symbolOffset": symbol_offset,            "label": label_opts,            "itemStyle": itemstyle_opts,            "tooltip": tooltip_opts,        }

大略的意思就是批量的设置 Line 的属性,这里不得不吐槽下 PyEcharts 官网文档,真的该好好保护下啊~(如果我这里了解的不对,欢送指出,咱们一起学习~)

也就是说下面的代码生成了一系列数据,这些数据 X 轴都是 10,Y 轴是从 0 开始,始终到循环的最初一个值递增,同时还通过LabelOpts设置了 msg 信息,也就是咱们最终看到的历史信息

XY 轴数据设置好之后,就是其余的款式调整了

def myLine(y, day):    line = Line(        init_opts=opts.InitOpts(            theme='light',            width='1000px',            height='800px'        )    )    line.add_xaxis(        ['']    )    line.add_yaxis(        '',        y,        linestyle_opts={            'normal': {                'width': 4,  # 设置线宽                'color':'red',                'shadowColor': 'rgba(155, 18, 184, .3)',  # 暗影色彩                'shadowBlur': 10,  # 暗影大小                'shadowOffsetY': 10,  # Y轴方向暗影偏移                'shadowOffsetX': 10,  # x轴方向暗影偏移            }        },        itemstyle_opts={            'normal': {                'color':'red',                'shadowColor': 'rgba(155, 18, 184, .3)',  # 暗影色彩                'shadowBlur': 10,  # 暗影大小                'shadowOffsetY': 10,  # Y轴方向暗影偏移                'shadowOffsetX': 10,  # x轴方向暗影偏移            }        },        tooltip_opts=opts.TooltipOpts(is_show=False)    )    line.set_global_opts(        xaxis_opts=opts.AxisOpts(is_show=False, type_='category'),        yaxis_opts=opts.AxisOpts(is_show=False, type_='value', max_=len(y)),        title_opts=opts.TitleOpts(            title="历史上的明天-%s" % day, pos_left='center', pos_top='2%',            title_textstyle_opts=opts.TextStyleOpts(color='red', font_size=20),            subtitle="公众号:萝卜大杂烩 出品"        ),        toolbox_opts=opts.ToolboxOpts(            is_show=True,            orient="vertical",            feature=opts.ToolBoxFeatureOpts(                save_as_image=opts.ToolBoxFeatureSaveAsImageOpts(type_="jpeg", title="保留为jpeg",                                                                 background_color="white"),                restore=opts.ToolBoxFeatureRestoreOpts(),                data_view=opts.ToolBoxFeatureDataViewOpts(),                data_zoom=opts.ToolBoxFeatureDataZoomOpts(),                magic_type=opts.ToolBoxFeatureDataViewOpts(),                brush=opts.ToolBoxFeatureDataZoomOpts(),            )        ),        graphic_opts=[                    opts.GraphicGroup(                                graphic_item=opts.GraphicItem(id_='1',left="center", top="center", z=-1),                                children=[# tokyo                                        opts.GraphicImage(graphic_item=opts.GraphicItem(id_="logo",                                                                                        left='center',                                                                                        z=-1),                                                          graphic_imagestyle_opts=opts.GraphicImageStyleOpts(                                            image="1.jpg",                                            width=800,                                            height=1000,                                            opacity=0.1,)                                        )                                    ]                                    )                                    ]    )    return line

这里考验的就是 PyEcharts 的熟练程度了,反正萝卜我是不达标的,这样款式如果是我本人,可能要对照官网调整大半天,哈哈哈

好了,图片制作就介绍到这里

部署 Web 服务

因为有个需要就是每天获取图片,而后转发到微信群,那么最不便的办法就是部署成 Web,在公网上拜访即可

对于这种长期的,集体网站,还是举荐应用 Flask,毕竟快就是劣势(这里的快指的是编写快,上手快~)

导入 Flask 和 PyEcharts 相干库

from flask import Flaskfrom jinja2 import Markup, Environment, FileSystemLoaderfrom pyecharts.globals import CurrentConfigimport datetimefrom flask import request# 对于 CurrentConfig,可参考 [根本应用-全局变量]CurrentConfig.GLOBAL_ENV = Environment(loader=FileSystemLoader("./templates"))

而后设置路由函数

def gen_line(month, day):    result_dict, day = get_data(month, day)    df = gen_df(result_dict)    y = gen_y(df)    line = myLine(y, day)    return line@app.route("/")def index():    month = request.args.get("month")    day = request.args.get("day")    if month and day:        c = gen_line(month, day)        return Markup(c.render_embed())    i = datetime.datetime.now()    c = gen_line(i.month, i.day)    return Markup(c.render_embed())

这样就好了,通过 Flask 自带的 Web 容器启动即可

if __name__ == "__main__":    app.run(debug=True, host="0.0.0.0")

好了,明天的分享就到这里,想要体验的同学,能够拜访这个网址

http://47.105.185.84:8080/

看到这里的敌人,如果你感觉称心请务必点个赞 + 在看 反对下。

一键三连,私信获取残缺代码~

本文由mdnice多平台公布