<cms:contentload>标签的使用

[ 王毅原创,转载注明]

标签说明:
    <cms:contentload> 载入一个 XML 内容资源的 collection ,根据给定的 collector 属性,确定是单个资源还是资源列表。
    也就是说,这个标签可以载入一个xml结构化类型的资源的列表,也可以载入单个的一个xml结构化类型的资源,依靠的仅仅是collector这个属性的值的不同。

标签属性:
  • collector:必选属性
    这个属性用来确定读取结构化内容。collectors是由OpenCms中的配置文件opencms-vfs.xml定义的。原始内容如下:
            <collectors>
                <collector class="org.opencms.file.collectors.CmsPriorityResourceCollector" order="100" />
                <collector class="org.opencms.file.collectors.CmsDefaultResourceCollector" order="110" />
                <collector class="org.opencms.file.collectors.CmsDateResourceCollector" order="120" />
                <collector class="org.opencms.file.collectors.CmsTimeFrameCategoryCollector" order="130" />
                <collector class="org.opencms.file.collectors.CmsCategoryResourceCollector" order="140" />
            </collectors>
这个标签的可选值有以下几种:
  1. singleFile
  2. allInFolder
  3. allInFolderDateReleasedDesc
  4. allInFolderNavPos
  5. allInSubTree
  6. allInSubTreeDateReleasedDesc
  7. allInSubTreeNavPos
  8. allInFolderPriorityDateDesc
  9. allInFolderPriorityTitleDesc
  10. allInSubTreePriorityDateDesc
  11. allInSubTreePriorityTitleDesc
    至于这些值的意思,我觉得看字面意思也能明白,在这里就不做解释了。
    注意的是,这个值可以直接在属性里面指定,也可以在属性里面指定。大家如果注意的话,就会发现在TemplateOne里面,资源有一个属性为“collector”,你可以通过下面这个值:
            ${property.collector}
来得到属性中的值,这样的话,显得更为灵活,当你需要排序的方式发生改变时候,不需要你修改页面的硬代码,直接修改一个资源的属性就可以了。
  • param
    这个属性用来给“collector”提供额外的其他信息,最常见的用法如下:
  1.         <cms:contentload collector ="singleFile" param="${opencms.uri}">  用来在加载当个资源文件的时候要通过param告诉“collector”遍历的是这个uri做指向的资源。
  2.         <cms:contentload collector ="allInFolder"  param="/xmlcontent/article_${number}.html|article|4"> 用来指定加载的是那些资源,是那种结构化类型,加载多少项。
    这里也需要注意以下,这个属性的值,可以直接指定,也可以向上面的 collector属性一样有属性得到,还可以通过普通的页面参数得到,还有一种比较特殊的就是在加载单个文件的时候,可以使用 ${opencms.uri} ${opencms.filename}
  • editable
    这个属性指定了当前xml内容资源是否支持直接编辑的特性。
    可选的值也当然只有“是”和“否”了,也就是“true”和“false”。
    这个属性是可选的,当你什么都不写的时候,有一个“false”作为默认值。
  • preload 
    这个属性定义了是否预先加载xml资源的内容。
    这个属性可选的值有“true”。

【标签体】
    可以是任何的HTML, JSP or JSTL代码。这个代码在返回的集合不止一个结构化内容项的时候被循环执行。

# LBMA(伦敦金银市场协会)官网:https://www.lbma.org.uk/cn/prices-and-data#/ # 黄金: https://prices.lbma.org.uk/json/gold_pm.json?r=854633265 # 白银: https://prices.lbma.org.uk/json/silver.json?r=65231548 # import json from datetime import datetime import matplotlib.dates as mdates import matplotlib.pyplot as plt import pandas as pd import requests # 设置Matplotlib全局参数 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 指定中文字体 plt.rcParams[&#39;axes.unicode_minus&#39;] = False # 解决负号显示问题 text_fontsize = 10 ryear = &#39;2000&#39; rdate = ryear + &#39;0101&#39; # 1.绘制金银价格图,使用twinx()创建,共用x轴但不同y轴的图表 def draw_gold_and_silver_graph(df): # 标注偏移量 xoffset = +pd.Timedelta(weeks=2) # 设置x,y数据 x = df[&#39;date&#39;] y1 = df[&#39;gold&#39;] y2 = df[&#39;silver&#39;] fig, ax1 = plt.subplots(figsize=(10, 6)) fig.set_facecolor(&#39;antiquewhite&#39;) ax1.set_facecolor(&#39;antiquewhite&#39;) # 第一个y轴(左侧黄金) ax1.plot(x, y1, label=&#39;黄金&#39;, color=&#39;darkgoldenrod&#39;) ax1.set_ylabel(&#39;黄金(美元/盎司)&#39;) y1_max_index = y1.idxmax() y1_min_index = y1.idxmin() ax1.text(x[y1_max_index]-xoffset, y1.iloc[y1_max_index], y1.iloc[y1_max_index], ha=&#39;right&#39;, va=&#39;center&#39;, fontsize=10, color=&#39;darkgoldenrod&#39;) ax1.text(x[y1_min_index]+xoffset, y1.iloc[y1_min_index]-20, y1.iloc[y1_min_index], ha=&#39;left&#39;, va=&#39;center&#39;, fontsize=10, color=&#39;darkgoldenrod&#39;) # 创建第二个y轴(右侧白银,共用x轴) ax2 = ax1.twinx() ax2.plot(x, y2, label=&#39;白银&#39;, color=&#39;gray&#39;) ax2.set_ylabel(&#39;白银(美元/盎司)&#39;) y2_max_index = y2.idxmax() y2_min_index = y2.idxmin() ax2.text(x[y2_max_index]+xoffset, y2.iloc[y2_max_index], y2.iloc[y2_max_index], ha=&#39;left&#39;, va=&#39;center&#39;, fontsize=10, color=&#39;gray&#39;) ax2.text(x[y2_min_index], y2.iloc[y2_min_index]-0.5, y2.iloc[y2_min_index], ha=&#39;right&#39;, va=&#39;center&#39;, fontsize=10, color=&#39;gray&#39;) # 添加标题和坐标轴标签 #ax1.tick_params(axis=&#39;y&#39;, labelcolor=&#39;gray&#39;) ax1.set_title(f&#39;{ryear}-2025年黄金、白银走势对比图&#39;) ax1.set_xlabel(&#39;年份&#39;) # 合并图例 lines1, labels1 = ax1.get_legend_handles_labels() lines2, labels2 = ax2.get_legend_handles_labels() ax1.legend(lines1 + lines2, labels1 + labels2, loc=&#39;upper left&#39;) # x轴比例刻度 ax1.xaxis.set_major_locator(mdates.YearLocator(1)) plt.show() # 2.绘制金银比图表 def draw_gold_silver_ratio_graph(df): # 标注偏移量 xoffset = +pd.Timedelta(weeks=2) # 设置x,y数据 x = df[&#39;date&#39;] y = df[&#39;ratio&#39;] y_70 = df[&#39;ratio_70th&#39;] y_30 = df[&#39;ratio_30th&#39;] fig, ax = plt.subplots(figsize=(10, 6)) fig.set_facecolor(&#39;antiquewhite&#39;) ax.set_facecolor(&#39;antiquewhite&#39;) # 金银比图例、最高点、最低点 ax.plot(x, y, label=&#39;金银比&#39;, color=&#39;blue&#39;) max_index = y.idxmax() min_index = y.idxmin() ax.text(x[max_index]+xoffset, y.iloc[max_index], y.iloc[max_index], ha=&#39;left&#39;, va=&#39;center&#39;, fontsize=10, color=&#39;blue&#39;) ax.text(x[min_index]+xoffset, y.iloc[min_index], y.iloc[min_index], ha=&#39;left&#39;, va=&#39;center&#39;, fontsize=10, color=&#39;blue&#39;) # 70分位值 ax.plot(x, y_70, label=&#39;70分位值&#39;, color=&#39;red&#39;) ax.text(x[x.count()-1]+xoffset, y_70.iloc[0], y_70.iloc[0], ha=&#39;left&#39;, va=&#39;center&#39;, fontsize=10, color=&#39;red&#39;) # 30分位值 ax.plot(x, y_30, label=&#39;30分位值&#39;, color=&#39;green&#39;) ax.text(x[x.count()-1]+xoffset, y_30.iloc[0], y_30.iloc[0], ha=&#39;left&#39;, va=&#39;center&#39;, fontsize=10, color=&#39;green&#39;) # 添加标题和x轴标签 ax.set_ylabel(&#39;金银比(黄金价格/白银价格)&#39;) ax.set_title(f&#39;{ryear}-2025年金银比走势图&#39;) ax.set_xlabel(&#39;年份&#39;) # 图例 lines, labels = ax.get_legend_handles_labels() ax.legend(lines, labels, loc=&#39;upper left&#39;) # x轴比例刻度 ax.xaxis.set_major_locator(mdates.YearLocator(1)) plt.show() # 3.绘制金银和金银比总图表,共用x轴,金银使用一个y轴,金银比使用另一个y轴 def draw_gold_silver_and_ratio_graph(df): # 标注偏移量 xoffset = +pd.Timedelta(weeks=2) # 设置x,y数据 x = df[&#39;date&#39;] y1 = df[&#39;gold&#39;] y2 = df[&#39;silver_cv&#39;] _y2 = df[&#39;silver&#39;] y = df[&#39;ratio&#39;] y_70 = df[&#39;ratio_70th&#39;] y_30 = df[&#39;ratio_30th&#39;] # 1.创建坐标轴,设置背景色 fig, ax = plt.subplots(figsize=(10, 6)) fig.set_facecolor(&#39;antiquewhite&#39;) ax.set_facecolor(&#39;antiquewhite&#39;) ax1 = ax ############################################################## # 2.左侧y轴 # 黄金价格 ax1.plot(x, y1, label=&#39;黄金&#39;, color=&#39;darkgoldenrod&#39;) y1_max_index = y1.idxmax() y1_min_index = y1.idxmin() ax1.text(x[y1_max_index]-xoffset, y1.iloc[y1_max_index], y1.iloc[y1_max_index], ha=&#39;right&#39;, va=&#39;center&#39;, fontsize=text_fontsize, color=&#39;darkgoldenrod&#39;) ax1.text(x[y1_min_index]+xoffset, y1.iloc[y1_min_index]-50, y1.iloc[y1_min_index], ha=&#39;center&#39;, va=&#39;center&#39;, fontsize=text_fontsize, color=&#39;darkgoldenrod&#39;) # 白银价格 ax1.plot(x, y2, label=&#39;白银&#39;, color=&#39;gray&#39;) y2_max_index = y2.idxmax() y2_min_index = y2.idxmin() ax1.text(x[y2_max_index]+xoffset, y2.iloc[y2_max_index], _y2.iloc[y2_max_index], ha=&#39;left&#39;, va=&#39;center&#39;, fontsize=text_fontsize, color=&#39;gray&#39;) ax1.text(x[y2_min_index], y2.iloc[y2_min_index]-0.5, _y2.iloc[y2_min_index], ha=&#39;left&#39;, va=&#39;center&#39;, fontsize=text_fontsize, color=&#39;gray&#39;) ############################################################## # 3.创建右侧y轴,共用x轴 ax2 = ax1.twinx() ############################################################## # 4.金银比图例、最高点、最低点 ax2.plot(x, y, label=&#39;金银比&#39;, color=&#39;blue&#39;, linewidth=0.5) max_index = y.idxmax() min_index = y.idxmin() ax2.text(x[max_index]+xoffset, y.iloc[max_index], y.iloc[max_index], ha=&#39;left&#39;, va=&#39;center&#39;, fontsize=text_fontsize, color=&#39;blue&#39;) ax2.text(x[min_index]+xoffset, y.iloc[min_index], y.iloc[min_index], ha=&#39;left&#39;, va=&#39;center&#39;, fontsize=text_fontsize, color=&#39;blue&#39;) # 70分位值 ax2.plot(x, y_70, label=&#39;70分位值&#39;, color=&#39;red&#39;, linewidth=0.5) ax2.text(x[x.count()-1]+xoffset, y_70.iloc[0], y_70.iloc[0], ha=&#39;left&#39;, va=&#39;center&#39;, fontsize=text_fontsize, color=&#39;red&#39;) # 30分位值 ax2.plot(x, y_30, label=&#39;30分位值&#39;, color=&#39;green&#39;, linewidth=0.5) ax2.text(x[x.count()-1]+xoffset, y_30.iloc[0], y_30.iloc[0], ha=&#39;left&#39;, va=&#39;center&#39;, fontsize=text_fontsize, color=&#39;green&#39;) ############################################################## # 5.添加标题和xy轴标签 ax1.set_ylabel(&#39;价格&#39;) ax2.set_ylabel(&#39;金银比(黄金价格/白银价格)&#39;) ax1.set_title(f&#39;{ryear}-2025年黄金、白银及金银比走势对比图&#39;) ax1.set_xlabel(&#39;年份&#39;) ############################################################## # 6.合并图例 lines1, labels1 = ax1.get_legend_handles_labels() lines2, labels2 = ax2.get_legend_handles_labels() ax1.legend(lines1 + lines2, labels1 + labels2, loc=&#39;upper left&#39;) # x轴比例刻度 ax.xaxis.set_major_locator(mdates.YearLocator(1)) plt.show() # # 处理原始json数据,转换成pandas DataFrame # # 伦敦金银 gold.json/silver.json:v对应&#39;USD&#39;, &#39;GBP&#39;, &#39;EUR&#39; 美元/英镑/欧元三种计价 # { # "is_cms_locked": 0, # "d": "2025-09-25", # "v": [3730.75, 2790.6, 3193.52] # } # #添加自己动获取数据 def download_data(url, filename): try: response = requests.get(url) with open(filename, &#39;wb&#39;) as f: f.write(response.content) print(f"已下载: {filename}") except Exception as e: print(f"下载失败: {e}") raise # def process_json(filename, cname): fd = open(filename, &#39;r&#39;) data = json.load(fd) fd.close() # 创建 DataFrame df = pd.json_normalize(data) # 增加列 split_cols = df[&#39;v&#39;].apply(pd.Series) split_cols.columns = [&#39;USD&#39;, &#39;GBP&#39;, &#39;EUR&#39;] # 删除列 axis=1 df.drop([&#39;is_cms_locked&#39;, &#39;v&#39;], axis=1, inplace=True) df = pd.concat([df, split_cols[&#39;USD&#39;]], axis=1) # 修改名称 df = df.rename(columns={&#39;d&#39;:&#39;date&#39;, &#39;USD&#39;:cname}) df[&#39;date&#39;] = pd.to_datetime(df[&#39;date&#39;]) df.set_index(&#39;date&#39;, inplace=True) # 筛选数据 start_date = datetime.strptime(rdate, "%Y%m%d") df = df[(df.index >= start_date)] df.reset_index(inplace=True) return df # 重组连接两张数据表 def recombine_data_from_json(): # 1.处理黄金数据: df_gold = process_json(&#39;gold.json&#39;, &#39;gold&#39;) # 2.处理白银数据: df_silver = process_json(&#39;silver.json&#39;, &#39;silver&#39;) # 3.连接两张表 # on: on​:指定合并的列名(两表列名相同时) # ​left_on/right_on​:左右表列名不同时使用,如:date1,date2 # how​:连接方式 # &#39;inner&#39;:只保留两表都有的日期(默认) # &#39;outer&#39;:保留所有日期,缺失值填NaN # &#39;left&#39;:保留左表所有日期 # &#39;right&#39;:保留右表所有日期 # ​suffixes​:列名冲突时的后缀(默认(&#39;x&#39;, &#39;y&#39;)) df = pd.merge(df_gold, df_silver, on=&#39;date&#39;, how=&#39;inner&#39;, suffixes=(&#39;_df1&#39;, &#39;_df2&#39;)) # 4.以黄金价格作为基准,白银价格按照涨幅等比例转换。 df[&#39;silver_cv&#39;] = round(df[&#39;silver&#39;] * df[&#39;gold&#39;].iloc[0] / df[&#39;silver&#39;].iloc[0], 2) # 5.计算金银比 df[&#39;ratio&#39;] = round(df[&#39;gold&#39;] / df[&#39;silver&#39;], 2) # 6.计算百分比分位值 df[&#39;ratio_70th&#39;] = round(df[&#39;ratio&#39;].quantile(0.7), 2) df[&#39;ratio_30th&#39;] = round(df[&#39;ratio&#39;].quantile(0.3), 2) # 7.写入csv文件 df.to_csv("gsr.csv") print(df) return df #if __name__ == "__main__": # 1.首先进入LMBA官网,使用浏览器下载原始json文件,python代码省略此部分。 # 或者,在cmd窗口执行如下命令: # 黄金:curl "https://prices.lbma.org.uk/json/gold_pm.json?r=854633265" -o gold.json # 白银:curl "https://prices.lbma.org.uk/json/silver.json?r=65231548" -o silver.json # 2.从json中提取数据, # df = recombine_data_from_json() # 3.可生成以下三类图表: # 黄金白银价格走势图 #draw_gold_and_silver_graph(df) # 金银比走势图 #draw_gold_silver_ratio_graph(df) # 组合叠加图 #draw_gold_silver_and_ratio_graph(df) #添加表格输出功能 def print_comparison_table(df): """打印金银比对比表格""" # 创建摘要表格 summary = pd.DataFrame({ &#39;指标&#39;: [&#39;黄金均价(USD)&#39;, &#39;白银均价(USD)&#39;, &#39;金银比均值&#39;, &#39;70分位值&#39;, &#39;30分位值&#39;], &#39;数值&#39;: [ df[&#39;gold&#39;].mean(), df[&#39;silver&#39;].mean(), df[&#39;ratio&#39;].mean(), df[&#39;ratio_70th&#39;].iloc[0], df[&#39;ratio_30th&#39;].iloc[0] ] }) # 格式化输出 print("\n" + "=" * 50) print(f"{ryear}-2025年金银市场对比分析") print("=" * 50) print(summary.to_string(index=False)) # 添加时间序列表格 print("\n近期价格趋势:") print(df[[&#39;date&#39;, &#39;gold&#39;, &#39;silver&#39;, &#39;ratio&#39;]].tail(10).to_string(index=False)) if __name__ == "__main__": # 自动下载数据 gold_url = "https://prices.lbma.org.uk/json/gold_pm.json?r=854633265" silver_url = "https://prices.lbma.org.uk/json/silver.json?r=65231548" download_data(gold_url, "gold.json") download_data(silver_url, "silver.json") # 处理数据 df = recombine_data_from_json() # 输出对比表格 print_comparison_table(df) # 新增表格输出 # 生成图表(可选) draw_gold_silver_and_ratio_graph(df) # LBMA(伦敦金银市场协会)官网:https://www.lbma.org.uk/cn/prices-and-data#/ # 黄金: https://prices.lbma.org.uk/json/gold_pm.json?r=854633265 # 白银: https://prices.lbma.org.uk/json/silver.json?r=65231548 # import json from datetime import datetime import matplotlib.dates as mdates import matplotlib.pyplot as plt import pandas as pd import requests # 设置Matplotlib全局参数 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 指定中文字体 plt.rcParams[&#39;axes.unicode_minus&#39;] = False # 解决负号显示问题 text_fontsize = 10 ryear = &#39;2000&#39; rdate = ryear + &#39;0101&#39; # 1.绘制金银价格图,使用twinx()创建,共用x轴但不同y轴的图表 def draw_gold_and_silver_graph(df): # 标注偏移量 xoffset = +pd.Timedelta(weeks=2) # 设置x,y数据 x = df[&#39;date&#39;] y1 = df[&#39;gold&#39;] y2 = df[&#39;silver&#39;] fig, ax1 = plt.subplots(figsize=(10, 6)) fig.set_facecolor(&#39;antiquewhite&#39;) ax1.set_facecolor(&#39;antiquewhite&#39;) # 第一个y轴(左侧黄金) ax1.plot(x, y1, label=&#39;黄金&#39;, color=&#39;darkgoldenrod&#39;) ax1.set_ylabel(&#39;黄金(美元/盎司)&#39;) y1_max_index = y1.idxmax() y1_min_index = y1.idxmin() ax1.text(x[y1_max_index]-xoffset, y1.iloc[y1_max_index], y1.iloc[y1_max_index], ha=&#39;right&#39;, va=&#39;center&#39;, fontsize=10, color=&#39;darkgoldenrod&#39;) ax1.text(x[y1_min_index]+xoffset, y1.iloc[y1_min_index]-20, y1.iloc[y1_min_index], ha=&#39;left&#39;, va=&#39;center&#39;, fontsize=10, color=&#39;darkgoldenrod&#39;) # 创建第二个y轴(右侧白银,共用x轴) ax2 = ax1.twinx() ax2.plot(x, y2, label=&#39;白银&#39;, color=&#39;gray&#39;) ax2.set_ylabel(&#39;白银(美元/盎司)&#39;) y2_max_index = y2.idxmax() y2_min_index = y2.idxmin() ax2.text(x[y2_max_index]+xoffset, y2.iloc[y2_max_index], y2.iloc[y2_max_index], ha=&#39;left&#39;, va=&#39;center&#39;, fontsize=10, color=&#39;gray&#39;) ax2.text(x[y2_min_index], y2.iloc[y2_min_index]-0.5, y2.iloc[y2_min_index], ha=&#39;right&#39;, va=&#39;center&#39;, fontsize=10, color=&#39;gray&#39;) # 添加标题和坐标轴标签 #ax1.tick_params(axis=&#39;y&#39;, labelcolor=&#39;gray&#39;) ax1.set_title(f&#39;{ryear}-2025年黄金、白银走势对比图&#39;) ax1.set_xlabel(&#39;年份&#39;) # 合并图例 lines1, labels1 = ax1.get_legend_handles_labels() lines2, labels2 = ax2.get_legend_handles_labels() ax1.legend(lines1 + lines2, labels1 + labels2, loc=&#39;upper left&#39;) # x轴比例刻度 ax1.xaxis.set_major_locator(mdates.YearLocator(1)) plt.show() # 2.绘制金银比图表 def draw_gold_silver_ratio_graph(df): # 标注偏移量 xoffset = +pd.Timedelta(weeks=2) # 设置x,y数据 x = df[&#39;date&#39;] y = df[&#39;ratio&#39;] y_70 = df[&#39;ratio_70th&#39;] y_30 = df[&#39;ratio_30th&#39;] fig, ax = plt.subplots(figsize=(10, 6)) fig.set_facecolor(&#39;antiquewhite&#39;) ax.set_facecolor(&#39;antiquewhite&#39;) # 金银比图例、最高点、最低点 ax.plot(x, y, label=&#39;金银比&#39;, color=&#39;blue&#39;) max_index = y.idxmax() min_index = y.idxmin() ax.text(x[max_index]+xoffset, y.iloc[max_index], y.iloc[max_index], ha=&#39;left&#39;, va=&#39;center&#39;, fontsize=10, color=&#39;blue&#39;) ax.text(x[min_index]+xoffset, y.iloc[min_index], y.iloc[min_index], ha=&#39;left&#39;, va=&#39;center&#39;, fontsize=10, color=&#39;blue&#39;) # 70分位值 ax.plot(x, y_70, label=&#39;70分位值&#39;, color=&#39;red&#39;) ax.text(x[x.count()-1]+xoffset, y_70.iloc[0], y_70.iloc[0], ha=&#39;left&#39;, va=&#39;center&#39;, fontsize=10, color=&#39;red&#39;) # 30分位值 ax.plot(x, y_30, label=&#39;30分位值&#39;, color=&#39;green&#39;) ax.text(x[x.count()-1]+xoffset, y_30.iloc[0], y_30.iloc[0], ha=&#39;left&#39;, va=&#39;center&#39;, fontsize=10, color=&#39;green&#39;) # 添加标题和x轴标签 ax.set_ylabel(&#39;金银比(黄金价格/白银价格)&#39;) ax.set_title(f&#39;{ryear}-2025年金银比走势图&#39;) ax.set_xlabel(&#39;年份&#39;) # 图例 lines, labels = ax.get_legend_handles_labels() ax.legend(lines, labels, loc=&#39;upper left&#39;) # x轴比例刻度 ax.xaxis.set_major_locator(mdates.YearLocator(1)) plt.show() # 3.绘制金银和金银比总图表,共用x轴,金银使用一个y轴,金银比使用另一个y轴 def draw_gold_silver_and_ratio_graph(df): # 标注偏移量 xoffset = +pd.Timedelta(weeks=2) # 设置x,y数据 x = df[&#39;date&#39;] y1 = df[&#39;gold&#39;] y2 = df[&#39;silver_cv&#39;] _y2 = df[&#39;silver&#39;] y = df[&#39;ratio&#39;] y_70 = df[&#39;ratio_70th&#39;] y_30 = df[&#39;ratio_30th&#39;] # 1.创建坐标轴,设置背景色 fig, ax = plt.subplots(figsize=(10, 6)) fig.set_facecolor(&#39;antiquewhite&#39;) ax.set_facecolor(&#39;antiquewhite&#39;) ax1 = ax ############################################################## # 2.左侧y轴 # 黄金价格 ax1.plot(x, y1, label=&#39;黄金&#39;, color=&#39;darkgoldenrod&#39;) y1_max_index = y1.idxmax() y1_min_index = y1.idxmin() ax1.text(x[y1_max_index]-xoffset, y1.iloc[y1_max_index], y1.iloc[y1_max_index], ha=&#39;right&#39;, va=&#39;center&#39;, fontsize=text_fontsize, color=&#39;darkgoldenrod&#39;) ax1.text(x[y1_min_index]+xoffset, y1.iloc[y1_min_index]-50, y1.iloc[y1_min_index], ha=&#39;center&#39;, va=&#39;center&#39;, fontsize=text_fontsize, color=&#39;darkgoldenrod&#39;) # 白银价格 ax1.plot(x, y2, label=&#39;白银&#39;, color=&#39;gray&#39;) y2_max_index = y2.idxmax() y2_min_index = y2.idxmin() ax1.text(x[y2_max_index]+xoffset, y2.iloc[y2_max_index], _y2.iloc[y2_max_index], ha=&#39;left&#39;, va=&#39;center&#39;, fontsize=text_fontsize, color=&#39;gray&#39;) ax1.text(x[y2_min_index], y2.iloc[y2_min_index]-0.5, _y2.iloc[y2_min_index], ha=&#39;left&#39;, va=&#39;center&#39;, fontsize=text_fontsize, color=&#39;gray&#39;) ############################################################## # 3.创建右侧y轴,共用x轴 ax2 = ax1.twinx() ############################################################## # 4.金银比图例、最高点、最低点 ax2.plot(x, y, label=&#39;金银比&#39;, color=&#39;blue&#39;, linewidth=0.5) max_index = y.idxmax() min_index = y.idxmin() ax2.text(x[max_index]+xoffset, y.iloc[max_index], y.iloc[max_index], ha=&#39;left&#39;, va=&#39;center&#39;, fontsize=text_fontsize, color=&#39;blue&#39;) ax2.text(x[min_index]+xoffset, y.iloc[min_index], y.iloc[min_index], ha=&#39;left&#39;, va=&#39;center&#39;, fontsize=text_fontsize, color=&#39;blue&#39;) # 70分位值 ax2.plot(x, y_70, label=&#39;70分位值&#39;, color=&#39;red&#39;, linewidth=0.5) ax2.text(x[x.count()-1]+xoffset, y_70.iloc[0], y_70.iloc[0], ha=&#39;left&#39;, va=&#39;center&#39;, fontsize=text_fontsize, color=&#39;red&#39;) # 30分位值 ax2.plot(x, y_30, label=&#39;30分位值&#39;, color=&#39;green&#39;, linewidth=0.5) ax2.text(x[x.count()-1]+xoffset, y_30.iloc[0], y_30.iloc[0], ha=&#39;left&#39;, va=&#39;center&#39;, fontsize=text_fontsize, color=&#39;green&#39;) ############################################################## # 5.添加标题和xy轴标签 ax1.set_ylabel(&#39;价格&#39;) ax2.set_ylabel(&#39;金银比(黄金价格/白银价格)&#39;) ax1.set_title(f&#39;{ryear}-2025年黄金、白银及金银比走势对比图&#39;) ax1.set_xlabel(&#39;年份&#39;) ############################################################## # 6.合并图例 lines1, labels1 = ax1.get_legend_handles_labels() lines2, labels2 = ax2.get_legend_handles_labels() ax1.legend(lines1 + lines2, labels1 + labels2, loc=&#39;upper left&#39;) # x轴比例刻度 ax.xaxis.set_major_locator(mdates.YearLocator(1)) plt.show() # # 处理原始json数据,转换成pandas DataFrame # # 伦敦金银 gold.json/silver.json:v对应&#39;USD&#39;, &#39;GBP&#39;, &#39;EUR&#39; 美元/英镑/欧元三种计价 # { # "is_cms_locked": 0, # "d": "2025-09-25", # "v": [3730.75, 2790.6, 3193.52] # } # #添加自己动获取数据 def download_data(url, filename): try: response = requests.get(url) with open(filename, &#39;wb&#39;) as f: f.write(response.content) print(f"已下载: {filename}") except Exception as e: print(f"下载失败: {e}") raise # def process_json(filename, cname): fd = open(filename, &#39;r&#39;) data = json.load(fd) fd.close() # 创建 DataFrame df = pd.json_normalize(data) # 增加列 split_cols = df[&#39;v&#39;].apply(pd.Series) split_cols.columns = [&#39;USD&#39;, &#39;GBP&#39;, &#39;EUR&#39;] # 删除列 axis=1 df.drop([&#39;is_cms_locked&#39;, &#39;v&#39;], axis=1, inplace=True) df = pd.concat([df, split_cols[&#39;USD&#39;]], axis=1) # 修改名称 df = df.rename(columns={&#39;d&#39;:&#39;date&#39;, &#39;USD&#39;:cname}) df[&#39;date&#39;] = pd.to_datetime(df[&#39;date&#39;]) df.set_index(&#39;date&#39;, inplace=True) # 筛选数据 start_date = datetime.strptime(rdate, "%Y%m%d") df = df[(df.index >= start_date)] df.reset_index(inplace=True) return df # 重组连接两张数据表 def recombine_data_from_json(): # 1.处理黄金数据: df_gold = process_json(&#39;gold.json&#39;, &#39;gold&#39;) # 2.处理白银数据: df_silver = process_json(&#39;silver.json&#39;, &#39;silver&#39;) # 3.连接两张表 # on: on​:指定合并的列名(两表列名相同时) # ​left_on/right_on​:左右表列名不同时使用,如:date1,date2 # how​:连接方式 # &#39;inner&#39;:只保留两表都有的日期(默认) # &#39;outer&#39;:保留所有日期,缺失值填NaN # &#39;left&#39;:保留左表所有日期 # &#39;right&#39;:保留右表所有日期 # ​suffixes​:列名冲突时的后缀(默认(&#39;x&#39;, &#39;y&#39;)) df = pd.merge(df_gold, df_silver, on=&#39;date&#39;, how=&#39;inner&#39;, suffixes=(&#39;_df1&#39;, &#39;_df2&#39;)) # 4.以黄金价格作为基准,白银价格按照涨幅等比例转换。 df[&#39;silver_cv&#39;] = round(df[&#39;silver&#39;] * df[&#39;gold&#39;].iloc[0] / df[&#39;silver&#39;].iloc[0], 2) # 5.计算金银比 df[&#39;ratio&#39;] = round(df[&#39;gold&#39;] / df[&#39;silver&#39;], 2) # 6.计算百分比分位值 df[&#39;ratio_70th&#39;] = round(df[&#39;ratio&#39;].quantile(0.7), 2) df[&#39;ratio_30th&#39;] = round(df[&#39;ratio&#39;].quantile(0.3), 2) # 7.写入csv文件 df.to_csv("gsr.csv") print(df) return df #if __name__ == "__main__": # 1.首先进入LMBA官网,使用浏览器下载原始json文件,python代码省略此部分。 # 或者,在cmd窗口执行如下命令: # 黄金:curl "https://prices.lbma.org.uk/json/gold_pm.json?r=854633265" -o gold.json # 白银:curl "https://prices.lbma.org.uk/json/silver.json?r=65231548" -o silver.json # 2.从json中提取数据, # df = recombine_data_from_json() # 3.可生成以下三类图表: # 黄金白银价格走势图 #draw_gold_and_silver_graph(df) # 金银比走势图 #draw_gold_silver_ratio_graph(df) # 组合叠加图 #draw_gold_silver_and_ratio_graph(df) #添加表格输出功能 def print_comparison_table(df): """打印金银比对比表格""" # 创建摘要表格 summary = pd.DataFrame({ &#39;指标&#39;: [&#39;黄金均价(USD)&#39;, &#39;白银均价(USD)&#39;, &#39;金银比均值&#39;, &#39;70分位值&#39;, &#39;30分位值&#39;], &#39;数值&#39;: [ df[&#39;gold&#39;].mean(), df[&#39;silver&#39;].mean(), df[&#39;ratio&#39;].mean(), df[&#39;ratio_70th&#39;].iloc[0], df[&#39;ratio_30th&#39;].iloc[0] ] }) # 格式化输出 print("\n" + "=" * 50) print(f"{ryear}-2025年金银市场对比分析") print("=" * 50) print(summary.to_string(index=False)) # 添加时间序列表格 print("\n近期价格趋势:") print(df[[&#39;date&#39;, &#39;gold&#39;, &#39;silver&#39;, &#39;ratio&#39;]].tail(10).to_string(index=False)) if __name__ == "__main__": # 自动下载数据 gold_url = "https://prices.lbma.org.uk/json/gold_pm.json?r=854633265" silver_url = "https://prices.lbma.org.uk/json/silver.json?r=65231548" download_data(gold_url, "gold.json") download_data(silver_url, "silver.json") # 处理数据 df = recombine_data_from_json() # 输出对比表格 print_comparison_table(df) # 新增表格输出 # 生成图表(可选) draw_gold_silver_and_ratio_graph(df) 此程序哪里有错误不能输出对比表和走势图之类图标,请帮忙修改成程序给出方案
10-03
# LBMA(伦敦金银市场协会)官网:https://www.lbma.org.uk/cn/prices-and-data#/ # 黄金: https://prices.lbma.org.uk/json/gold_pm.json?r=854633265 # 白银: https://prices.lbma.org.uk/json/silver.json?r=65231548 # import json from datetime import datetime import matplotlib.dates as mdates import matplotlib.pyplot as plt import pandas as pd import requests import matplotlib import os # 设置兼容模式为Windows 8 os.environ["__COMPAT_LAYER"] = "WIN8RTM" matplotlib.use(&#39;TkAgg&#39;) # 设置Matplotlib全局参数 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 指定中文字体 plt.rcParams[&#39;axes.unicode_minus&#39;] = False # 解决负号显示问题 text_fontsize = 10 ryear = &#39;2000&#39; rdate = ryear + &#39;0101&#39; # 1.绘制金银价格图,使用twinx()创建,共用x轴但不同y轴的图表 def draw_gold_and_silver_graph(df): # 标注偏移量 xoffset = +pd.Timedelta(weeks=2) # 设置x,y数据 x = df[&#39;date&#39;] y1 = df[&#39;gold&#39;] y2 = df[&#39;silver&#39;] fig, ax1 = plt.subplots(figsize=(10, 6)) fig.set_facecolor(&#39;antiquewhite&#39;) ax1.set_facecolor(&#39;antiquewhite&#39;) # 第一个y轴(左侧黄金) ax1.plot(x, y1, label=&#39;黄金&#39;, color=&#39;darkgoldenrod&#39;) ax1.set_ylabel(&#39;黄金(美元/盎司)&#39;) y1_max_index = y1.idxmax() y1_min_index = y1.idxmin() ax1.text(x[y1_max_index]-xoffset, y1.iloc[y1_max_index], y1.iloc[y1_max_index], ha=&#39;right&#39;, va=&#39;center&#39;, fontsize=10, color=&#39;darkgoldenrod&#39;) ax1.text(x[y1_min_index]+xoffset, y1.iloc[y1_min_index]-20, y1.iloc[y1_min_index], ha=&#39;left&#39;, va=&#39;center&#39;, fontsize=10, color=&#39;darkgoldenrod&#39;) # 创建第二个y轴(右侧白银,共用x轴) ax2 = ax1.twinx() ax2.plot(x, y2, label=&#39;白银&#39;, color=&#39;gray&#39;) ax2.set_ylabel(&#39;白银(美元/盎司)&#39;) y2_max_index = y2.idxmax() y2_min_index = y2.idxmin() ax2.text(x[y2_max_index]+xoffset, y2.iloc[y2_max_index], y2.iloc[y2_max_index], ha=&#39;left&#39;, va=&#39;center&#39;, fontsize=10, color=&#39;gray&#39;) ax2.text(x[y2_min_index], y2.iloc[y2_min_index]-0.5, y2.iloc[y2_min_index], ha=&#39;right&#39;, va=&#39;center&#39;, fontsize=10, color=&#39;gray&#39;) # 添加标题和坐标轴标签 ax1.tick_params(axis=&#39;y&#39;, labelcolor=&#39;gray&#39;) ax1.set_title(f&#39;{ryear}-2025年黄金、白银走势对比图&#39;) ax1.set_xlabel(&#39;年份&#39;) # 合并图例 lines1, labels1 = ax1.get_legend_handles_labels() lines2, labels2 = ax2.get_legend_handles_labels() ax1.legend(lines1 + lines2, labels1 + labels2, loc=&#39;upper left&#39;) # x轴比例刻度 ax1.xaxis.set_major_locator(mdates.YearLocator(1)) plt.show() # 2.绘制金银比图表 def draw_gold_silver_ratio_graph(df): # 标注偏移量 xoffset = +pd.Timedelta(weeks=2) # 设置x,y数据 x = df[&#39;date&#39;] y = df[&#39;ratio&#39;] y_70 = df[&#39;ratio_70th&#39;] y_30 = df[&#39;ratio_30th&#39;] fig, ax = plt.subplots(figsize=(10, 6)) fig.set_facecolor(&#39;antiquewhite&#39;) ax.set_facecolor(&#39;antiquewhite&#39;) # 金银比图例、最高点、最低点 ax.plot(x, y, label=&#39;金银比&#39;, color=&#39;blue&#39;) max_index = y.idxmax() min_index = y.idxmin() ax.text(x[max_index]+xoffset, y.iloc[max_index], y.iloc[max_index], ha=&#39;left&#39;, va=&#39;center&#39;, fontsize=10, color=&#39;blue&#39;) ax.text(x[min_index]+xoffset, y.iloc[min_index], y.iloc[min_index], ha=&#39;left&#39;, va=&#39;center&#39;, fontsize=10, color=&#39;blue&#39;) # 70分位值 ax.plot(x, y_70, label=&#39;70分位值&#39;, color=&#39;red&#39;) ax.text(x[x.count()-1]+xoffset, y_70.iloc[0], y_70.iloc[0], ha=&#39;left&#39;, va=&#39;center&#39;, fontsize=10, color=&#39;red&#39;) # 30分位值 ax.plot(x, y_30, label=&#39;30分位值&#39;, color=&#39;green&#39;) ax.text(x[x.count()-1]+xoffset, y_30.iloc[0], y_30.iloc[0], ha=&#39;left&#39;, va=&#39;center&#39;, fontsize=10, color=&#39;green&#39;) # 添加标题和x轴标签 ax.set_ylabel(&#39;金银比(黄金价格/白银价格)&#39;) ax.set_title(f&#39;{ryear}-2025年金银比走势图&#39;) ax.set_xlabel(&#39;年份&#39;) # 图例 lines, labels = ax.get_legend_handles_labels() ax.legend(lines, labels, loc=&#39;upper left&#39;) # x轴比例刻度 ax.xaxis.set_major_locator(mdates.YearLocator(1)) plt.show() # 3.绘制金银和金银比总图表,共用x轴,金银使用一个y轴,金银比使用另一个y轴 def draw_gold_silver_and_ratio_graph(df): # 标注偏移量 xoffset = +pd.Timedelta(weeks=2) # 设置x,y数据 x = df[&#39;date&#39;] y1 = df[&#39;gold&#39;] y2 = df[&#39;silver_cv&#39;] _y2 = df[&#39;silver&#39;] y = df[&#39;ratio&#39;] y_70 = df[&#39;ratio_70th&#39;] y_30 = df[&#39;ratio_30th&#39;] # 1.创建坐标轴,设置背景色 fig, ax = plt.subplots(figsize=(10, 6)) fig.set_facecolor(&#39;antiquewhite&#39;) ax.set_facecolor(&#39;antiquewhite&#39;) ax1 = ax ############################################################## # 2.左侧y轴 # 黄金价格 ax1.plot(x, y1, label=&#39;黄金&#39;, color=&#39;darkgoldenrod&#39;) y1_max_index = y1.idxmax() y1_min_index = y1.idxmin() ax1.text(x[y1_max_index]-xoffset, y1.iloc[y1_max_index], y1.iloc[y1_max_index], ha=&#39;right&#39;, va=&#39;center&#39;, fontsize=text_fontsize, color=&#39;darkgoldenrod&#39;) ax1.text(x[y1_min_index]+xoffset, y1.iloc[y1_min_index]-50, y1.iloc[y1_min_index], ha=&#39;center&#39;, va=&#39;center&#39;, fontsize=text_fontsize, color=&#39;darkgoldenrod&#39;) # 白银价格 ax1.plot(x, y2, label=&#39;白银&#39;, color=&#39;gray&#39;) y2_max_index = y2.idxmax() y2_min_index = y2.idxmin() ax1.text(x[y2_max_index]+xoffset, y2.iloc[y2_max_index], _y2.iloc[y2_max_index], ha=&#39;left&#39;, va=&#39;center&#39;, fontsize=text_fontsize, color=&#39;gray&#39;) ax1.text(x[y2_min_index], y2.iloc[y2_min_index]-0.5, _y2.iloc[y2_min_index], ha=&#39;left&#39;, va=&#39;center&#39;, fontsize=text_fontsize, color=&#39;gray&#39;) ############################################################## # 3.创建右侧y轴,共用x轴 ax2 = ax1.twinx() ############################################################## # 4.金银比图例、最高点、最低点 ax2.plot(x, y, label=&#39;金银比&#39;, color=&#39;blue&#39;, linewidth=0.5) max_index = y.idxmax() min_index = y.idxmin() ax2.text(x[max_index]+xoffset, y.iloc[max_index], y.iloc[max_index], ha=&#39;left&#39;, va=&#39;center&#39;, fontsize=text_fontsize, color=&#39;blue&#39;) ax2.text(x[min_index]+xoffset, y.iloc[min_index], y.iloc[min_index], ha=&#39;left&#39;, va=&#39;center&#39;, fontsize=text_fontsize, color=&#39;blue&#39;) # 70分位值 ax2.plot(x, y_70, label=&#39;70分位值&#39;, color=&#39;red&#39;, linewidth=0.5) ax2.text(x[x.count()-1]+xoffset, y_70.iloc[0], y_70.iloc[0], ha=&#39;left&#39;, va=&#39;center&#39;, fontsize=text_fontsize, color=&#39;red&#39;) # 30分位值 ax2.plot(x, y_30, label=&#39;30分位值&#39;, color=&#39;green&#39;, linewidth=0.5) ax2.text(x[x.count()-1]+xoffset, y_30.iloc[0], y_30.iloc[0], ha=&#39;left&#39;, va=&#39;center&#39;, fontsize=text_fontsize, color=&#39;green&#39;) ############################################################## # 5.添加标题和xy轴标签 ax1.set_ylabel(&#39;价格&#39;) ax2.set_ylabel(&#39;金银比(黄金价格/白银价格)&#39;) ax1.set_title(f&#39;{ryear}-2025年黄金、白银及金银比走势对比图&#39;) ax1.set_xlabel(&#39;年份&#39;) ############################################################## # 6.合并图例 lines1, labels1 = ax1.get_legend_handles_labels() lines2, labels2 = ax2.get_legend_handles_labels() ax1.legend(lines1 + lines2, labels1 + labels2, loc=&#39;upper left&#39;) # x轴比例刻度 ax.xaxis.set_major_locator(mdates.YearLocator(1)) plt.show() # # 处理原始json数据,转换成pandas DataFrame # # 伦敦金银 gold.json/silver.json:v对应&#39;USD&#39;, &#39;GBP&#39;, &#39;EUR&#39; 美元/英镑/欧元三种计价 # { # "is_cms_locked": 0, # "d": "2025-09-25", # "v": [3730.75, 2790.6, 3193.52] # } # #添加自己动获取数据 def download_data(url, filename): try: response = requests.get(url) with open(filename, &#39;wb&#39;) as f: f.write(response.content) print(f"已下载: {filename}") except Exception as e: print(f"下载失败: {e}") raise # def process_json(filename, cname): fd = open(filename, &#39;r&#39;) data = json.load(fd) fd.close() # 创建 DataFrame df = pd.json_normalize(data) # 增加列 split_cols = df[&#39;v&#39;].apply(pd.Series) split_cols.columns = [&#39;USD&#39;, &#39;GBP&#39;, &#39;EUR&#39;] # 删除列 axis=1 df.drop([&#39;is_cms_locked&#39;, &#39;v&#39;], axis=1, inplace=True) df = pd.concat([df, split_cols[&#39;USD&#39;]], axis=1) # 修改名称 df = df.rename(columns={&#39;d&#39;:&#39;date&#39;, &#39;USD&#39;:cname}) df[&#39;date&#39;] = pd.to_datetime(df[&#39;date&#39;]) df.set_index(&#39;date&#39;, inplace=True) # 筛选数据 start_date = datetime.strptime(rdate, "%Y%m%d") df = df[(df.index >= start_date)] df.reset_index(inplace=True) return df # 重组连接两张数据表 def recombine_data_from_json(): # 1.处理黄金数据: df_gold = process_json(&#39;gold.json&#39;, &#39;gold&#39;) # 2.处理白银数据: df_silver = process_json(&#39;silver.json&#39;, &#39;silver&#39;) # 3.连接两张表 # on: on​:指定合并的列名(两表列名相同时) # ​left_on/right_on​:左右表列名不同时使用,如:date1,date2 # how​:连接方式 # &#39;inner&#39;:只保留两表都有的日期(默认) # &#39;outer&#39;:保留所有日期,缺失值填NaN # &#39;left&#39;:保留左表所有日期 # &#39;right&#39;:保留右表所有日期 # ​suffixes​:列名冲突时的后缀(默认(&#39;x&#39;, &#39;y&#39;)) df = pd.merge(df_gold, df_silver, on=&#39;date&#39;, how=&#39;inner&#39;, suffixes=(&#39;_df1&#39;, &#39;_df2&#39;)) # 4.以黄金价格作为基准,白银价格按照涨幅等比例转换。 df[&#39;silver_cv&#39;] = round(df[&#39;silver&#39;] * df[&#39;gold&#39;].iloc[0] / df[&#39;silver&#39;].iloc[0], 2) # 5.计算金银比 df[&#39;ratio&#39;] = round(df[&#39;gold&#39;] / df[&#39;silver&#39;], 2) # 6.计算百分比分位值 df[&#39;ratio_70th&#39;] = round(df[&#39;ratio&#39;].quantile(0.7), 2) df[&#39;ratio_30th&#39;] = round(df[&#39;ratio&#39;].quantile(0.3), 2) # 7.写入csv文件 df.to_csv("gsr.csv") print(df) return df #if __name__ == "__main__": # 1.首先进入LMBA官网,使用浏览器下载原始json文件,python代码省略此部分。 # 或者,在cmd窗口执行如下命令: # 黄金:curl "https://prices.lbma.org.uk/json/gold_pm.json?r=854633265" -o gold.json # 白银:curl "https://prices.lbma.org.uk/json/silver.json?r=65231548" -o silver.json # 2.从json中提取数据, # df = recombine_data_from_json() # 3.可生成以下三类图表: # 黄金白银价格走势图 #draw_gold_and_silver_graph(df) # 金银比走势图 #draw_gold_silver_ratio_graph(df) # 组合叠加图 #draw_gold_silver_and_ratio_graph(df) if __name__ == "__main__": # 自动下载数据 gold_url = "https://prices.lbma.org.uk/json/gold_pm.json?r=854633265" silver_url = "https://prices.lbma.org.uk/json/silver.json?r=65231548" download_data(gold_url, "gold.json") download_data(silver_url, "silver.json") # 处理数据 df = recombine_data_from_json() # 添加表格输出功能 def print_comparison_table(df): """打印金银比对比表格""" # 创建摘要表格 summary = pd.DataFrame({ &#39;指标&#39;: [&#39;黄金均价(USD)&#39;, &#39;白银均价(USD)&#39;, &#39;金银比均值&#39;, &#39;70分位值&#39;, &#39;30分位值&#39;], &#39;数值&#39;: [ df[&#39;gold&#39;].mean(), df[&#39;silver&#39;].mean(), df[&#39;ratio&#39;].mean(), df[&#39;ratio_70th&#39;].iloc[0], df[&#39;ratio_30th&#39;].iloc[0] ] }) # 格式化输出 print("\n" + "=" * 50) print(f"{ryear}-2025年金银市场对比分析") print("=" * 50) print(summary.to_string(index=False)) # 添加时间序列表格 print("\n近期价格趋势:") print(df[[&#39;date&#39;, &#39;gold&#39;, &#39;silver&#39;, &#39;ratio&#39;]].tail(10).to_string(index=False)) # 输出对比表格 print_comparison_table(df) # 新增表格输出 # 生成图表(可选) draw_gold_silver_and_ratio_graph(df) # 3.可生成以下三类图表: # 黄金白银价格走势图 draw_gold_and_silver_graph(df) # 金银比走势图 draw_gold_silver_ratio_graph(df) 遇到这个问题,怎么优化程序?无法定位程序输入点pssquerysnapshot于动态链库kernel32.dll"问题
最新发布
10-08
# LBMA(伦敦金银市场协会)官网:https://www.lbma.org.uk/cn/prices-and-data#/ # 黄金: https://prices.lbma.org.uk/json/gold_pm.json?r=854633265 # 白银: https://prices.lbma.org.uk/json/silver.json?r=65231548 # import json from datetime import datetime import matplotlib.dates as mdates import matplotlib.pyplot as plt import pandas as pd # 设置Matplotlib全局参数 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 指定中文字体 plt.rcParams[&#39;axes.unicode_minus&#39;] = False # 解决负号显示问题 text_fontsize = 10 ryear = &#39;2000&#39; rdate = ryear + &#39;0101&#39; # 1.绘制金银价格图,使用twinx()创建,共用x轴但不同y轴的图表 def draw_gold_and_silver_graph(df): # 标注偏移量 xoffset = +pd.Timedelta(weeks=2) # 设置x,y数据 x = df[&#39;date&#39;] y1 = df[&#39;gold&#39;] y2 = df[&#39;silver&#39;] fig, ax1 = plt.subplots(figsize=(10, 6)) fig.set_facecolor(&#39;antiquewhite&#39;) ax1.set_facecolor(&#39;antiquewhite&#39;) # 第一个y轴(左侧黄金) ax1.plot(x, y1, label=&#39;黄金&#39;, color=&#39;darkgoldenrod&#39;) ax1.set_ylabel(&#39;黄金(美元/盎司)&#39;) y1_max_index = y1.idxmax() y1_min_index = y1.idxmin() ax1.text(x[y1_max_index]-xoffset, y1.iloc[y1_max_index], y1.iloc[y1_max_index], ha=&#39;right&#39;, va=&#39;center&#39;, fontsize=10, color=&#39;darkgoldenrod&#39;) ax1.text(x[y1_min_index]+xoffset, y1.iloc[y1_min_index]-20, y1.iloc[y1_min_index], ha=&#39;left&#39;, va=&#39;center&#39;, fontsize=10, color=&#39;darkgoldenrod&#39;) # 创建第二个y轴(右侧白银,共用x轴) ax2 = ax1.twinx() ax2.plot(x, y2, label=&#39;白银&#39;, color=&#39;gray&#39;) ax2.set_ylabel(&#39;白银(美元/盎司)&#39;) y2_max_index = y2.idxmax() y2_min_index = y2.idxmin() ax2.text(x[y2_max_index]+xoffset, y2.iloc[y2_max_index], y2.iloc[y2_max_index], ha=&#39;left&#39;, va=&#39;center&#39;, fontsize=10, color=&#39;gray&#39;) ax2.text(x[y2_min_index], y2.iloc[y2_min_index]-0.5, y2.iloc[y2_min_index], ha=&#39;right&#39;, va=&#39;center&#39;, fontsize=10, color=&#39;gray&#39;) # 添加标题和坐标轴标签 #ax1.tick_params(axis=&#39;y&#39;, labelcolor=&#39;gray&#39;) ax1.set_title(f&#39;{ryear}-2025年黄金、白银走势对比图&#39;) ax1.set_xlabel(&#39;年份&#39;) # 合并图例 lines1, labels1 = ax1.get_legend_handles_labels() lines2, labels2 = ax2.get_legend_handles_labels() ax1.legend(lines1 + lines2, labels1 + labels2, loc=&#39;upper left&#39;) # x轴比例刻度 ax1.xaxis.set_major_locator(mdates.YearLocator(1)) plt.show() # 2.绘制金银比图表 def draw_gold_silver_ratio_graph(df): # 标注偏移量 xoffset = +pd.Timedelta(weeks=2) # 设置x,y数据 x = df[&#39;date&#39;] y = df[&#39;ratio&#39;] y_70 = df[&#39;ratio_70th&#39;] y_30 = df[&#39;ratio_30th&#39;] fig, ax = plt.subplots(figsize=(10, 6)) fig.set_facecolor(&#39;antiquewhite&#39;) ax.set_facecolor(&#39;antiquewhite&#39;) # 金银比图例、最高点、最低点 ax.plot(x, y, label=&#39;金银比&#39;, color=&#39;blue&#39;) max_index = y.idxmax() min_index = y.idxmin() ax.text(x[max_index]+xoffset, y.iloc[max_index], y.iloc[max_index], ha=&#39;left&#39;, va=&#39;center&#39;, fontsize=10, color=&#39;blue&#39;) ax.text(x[min_index]+xoffset, y.iloc[min_index], y.iloc[min_index], ha=&#39;left&#39;, va=&#39;center&#39;, fontsize=10, color=&#39;blue&#39;) # 70分位值 ax.plot(x, y_70, label=&#39;70分位值&#39;, color=&#39;red&#39;) ax.text(x[x.count()-1]+xoffset, y_70.iloc[0], y_70.iloc[0], ha=&#39;left&#39;, va=&#39;center&#39;, fontsize=10, color=&#39;red&#39;) # 30分位值 ax.plot(x, y_30, label=&#39;30分位值&#39;, color=&#39;green&#39;) ax.text(x[x.count()-1]+xoffset, y_30.iloc[0], y_30.iloc[0], ha=&#39;left&#39;, va=&#39;center&#39;, fontsize=10, color=&#39;green&#39;) # 添加标题和x轴标签 ax.set_ylabel(&#39;金银比(黄金价格/白银价格)&#39;) ax.set_title(f&#39;{ryear}-2025年金银比走势图&#39;) ax.set_xlabel(&#39;年份&#39;) # 图例 lines, labels = ax.get_legend_handles_labels() ax.legend(lines, labels, loc=&#39;upper left&#39;) # x轴比例刻度 ax.xaxis.set_major_locator(mdates.YearLocator(1)) plt.show() # 3.绘制金银和金银比总图表,共用x轴,金银使用一个y轴,金银比使用另一个y轴 def draw_gold_silver_and_ratio_graph(df): # 标注偏移量 xoffset = +pd.Timedelta(weeks=2) # 设置x,y数据 x = df[&#39;date&#39;] y1 = df[&#39;gold&#39;] y2 = df[&#39;silver_cv&#39;] _y2 = df[&#39;silver&#39;] y = df[&#39;ratio&#39;] y_70 = df[&#39;ratio_70th&#39;] y_30 = df[&#39;ratio_30th&#39;] # 1.创建坐标轴,设置背景色 fig, ax = plt.subplots(figsize=(10, 6)) fig.set_facecolor(&#39;antiquewhite&#39;) ax.set_facecolor(&#39;antiquewhite&#39;) ax1 = ax ############################################################## # 2.左侧y轴 # 黄金价格 ax1.plot(x, y1, label=&#39;黄金&#39;, color=&#39;darkgoldenrod&#39;) y1_max_index = y1.idxmax() y1_min_index = y1.idxmin() ax1.text(x[y1_max_index]-xoffset, y1.iloc[y1_max_index], y1.iloc[y1_max_index], ha=&#39;right&#39;, va=&#39;center&#39;, fontsize=text_fontsize, color=&#39;darkgoldenrod&#39;) ax1.text(x[y1_min_index]+xoffset, y1.iloc[y1_min_index]-50, y1.iloc[y1_min_index], ha=&#39;center&#39;, va=&#39;center&#39;, fontsize=text_fontsize, color=&#39;darkgoldenrod&#39;) # 白银价格 ax1.plot(x, y2, label=&#39;白银&#39;, color=&#39;gray&#39;) y2_max_index = y2.idxmax() y2_min_index = y2.idxmin() ax1.text(x[y2_max_index]+xoffset, y2.iloc[y2_max_index], _y2.iloc[y2_max_index], ha=&#39;left&#39;, va=&#39;center&#39;, fontsize=text_fontsize, color=&#39;gray&#39;) ax1.text(x[y2_min_index], y2.iloc[y2_min_index]-0.5, _y2.iloc[y2_min_index], ha=&#39;left&#39;, va=&#39;center&#39;, fontsize=text_fontsize, color=&#39;gray&#39;) ############################################################## # 3.创建右侧y轴,共用x轴 ax2 = ax1.twinx() ############################################################## # 4.金银比图例、最高点、最低点 ax2.plot(x, y, label=&#39;金银比&#39;, color=&#39;blue&#39;, linewidth=0.5) max_index = y.idxmax() min_index = y.idxmin() ax2.text(x[max_index]+xoffset, y.iloc[max_index], y.iloc[max_index], ha=&#39;left&#39;, va=&#39;center&#39;, fontsize=text_fontsize, color=&#39;blue&#39;) ax2.text(x[min_index]+xoffset, y.iloc[min_index], y.iloc[min_index], ha=&#39;left&#39;, va=&#39;center&#39;, fontsize=text_fontsize, color=&#39;blue&#39;) # 70分位值 ax2.plot(x, y_70, label=&#39;70分位值&#39;, color=&#39;red&#39;, linewidth=0.5) ax2.text(x[x.count()-1]+xoffset, y_70.iloc[0], y_70.iloc[0], ha=&#39;left&#39;, va=&#39;center&#39;, fontsize=text_fontsize, color=&#39;red&#39;) # 30分位值 ax2.plot(x, y_30, label=&#39;30分位值&#39;, color=&#39;green&#39;, linewidth=0.5) ax2.text(x[x.count()-1]+xoffset, y_30.iloc[0], y_30.iloc[0], ha=&#39;left&#39;, va=&#39;center&#39;, fontsize=text_fontsize, color=&#39;green&#39;) ############################################################## # 5.添加标题和xy轴标签 ax1.set_ylabel(&#39;价格&#39;) ax2.set_ylabel(&#39;金银比(黄金价格/白银价格)&#39;) ax1.set_title(f&#39;{ryear}-2025年黄金、白银及金银比走势对比图&#39;) ax1.set_xlabel(&#39;年份&#39;) ############################################################## # 6.合并图例 lines1, labels1 = ax1.get_legend_handles_labels() lines2, labels2 = ax2.get_legend_handles_labels() ax1.legend(lines1 + lines2, labels1 + labels2, loc=&#39;upper left&#39;) # x轴比例刻度 ax.xaxis.set_major_locator(mdates.YearLocator(1)) plt.show() # # 处理原始json数据,转换成pandas DataFrame # # 伦敦金银 gold.json/silver.json:v对应&#39;USD&#39;, &#39;GBP&#39;, &#39;EUR&#39; 美元/英镑/欧元三种计价 # { # "is_cms_locked": 0, # "d": "2025-09-25", # "v": [3730.75, 2790.6, 3193.52] # } # def process_json(filename, cname): fd = open(filename, &#39;r&#39;) data = json.load(fd) fd.close() # 创建 DataFrame df = pd.json_normalize(data) # 增加列 split_cols = df[&#39;v&#39;].apply(pd.Series) split_cols.columns = [&#39;USD&#39;, &#39;GBP&#39;, &#39;EUR&#39;] # 删除列 axis=1 df.drop([&#39;is_cms_locked&#39;, &#39;v&#39;], axis=1, inplace=True) df = pd.concat([df, split_cols[&#39;USD&#39;]], axis=1) # 修改名称 df = df.rename(columns={&#39;d&#39;:&#39;date&#39;, &#39;USD&#39;:cname}) df[&#39;date&#39;] = pd.to_datetime(df[&#39;date&#39;]) df.set_index(&#39;date&#39;, inplace=True) # 筛选数据 start_date = datetime.strptime(rdate, "%Y%m%d") df = df[(df.index >= start_date)] df.reset_index(inplace=True) return df # 重组连接两张数据表 def recombine_data_from_json(): # 1.处理黄金数据: df_gold = process_json(&#39;gold.json&#39;, &#39;gold&#39;) # 2.处理白银数据: df_silver = process_json(&#39;silver.json&#39;, &#39;silver&#39;) # 3.连接两张表 # on: on​:指定合并的列名(两表列名相同时) # ​left_on/right_on​:左右表列名不同时使用,如:date1,date2 # how​:连接方式 # &#39;inner&#39;:只保留两表都有的日期(默认) # &#39;outer&#39;:保留所有日期,缺失值填NaN # &#39;left&#39;:保留左表所有日期 # &#39;right&#39;:保留右表所有日期 # ​suffixes​:列名冲突时的后缀(默认(&#39;x&#39;, &#39;y&#39;)) df = pd.merge(df_gold, df_silver, on=&#39;date&#39;, how=&#39;inner&#39;, suffixes=(&#39;_df1&#39;, &#39;_df2&#39;)) # 4.以黄金价格作为基准,白银价格按照涨幅等比例转换。 df[&#39;silver_cv&#39;] = round(df[&#39;silver&#39;] * df[&#39;gold&#39;].iloc[0] / df[&#39;silver&#39;].iloc[0], 2) # 5.计算金银比 df[&#39;ratio&#39;] = round(df[&#39;gold&#39;] / df[&#39;silver&#39;], 2) # 6.计算百分比分位值 df[&#39;ratio_70th&#39;] = round(df[&#39;ratio&#39;].quantile(0.7), 2) df[&#39;ratio_30th&#39;] = round(df[&#39;ratio&#39;].quantile(0.3), 2) # 7.写入csv文件 df.to_csv("gsr.csv") print(df) return df if __name__ == "__main__": # 1.首先进入LMBA官网,使用浏览器下载原始json文件,python代码省略此部分。 # 或者,在cmd窗口执行如下命令: # 黄金:curl "https://prices.lbma.org.uk/json/gold_pm.json?r=854633265" -o gold.json # 白银:curl "https://prices.lbma.org.uk/json/silver.json?r=65231548" -o silver.json # 2.从json中提取数据, df = recombine_data_from_json() # 3.可生成以下三类图表: # 黄金白银价格走势图 #draw_gold_and_silver_graph(df) # 金银比走势图 #draw_gold_silver_ratio_graph(df) # 组合叠加图 draw_gold_silver_and_ratio_graph(df) 程序为啥不能输出所需要的对比表格
10-03
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值