首页 > 编程语言 >Python抓取汇率并绘制成折线图

Python抓取汇率并绘制成折线图

时间:2022-08-17 21:34:26浏览次数:46  
标签:Python max 抓取 line1 datetime cell 折线图 data row

公司的一个小工作,需要抓取美元、欧元汇率并绘制成折线图。很小的功能,背后却涉及很多Python知识,甚至一些冷门的知识点。知识点总结如下:

1.python抓取网页数据,利用pandas.read_html()进行解析

2.python日期操作,包括获取今天日期,获取上周一日期,上周五日期,今年的第一天等。还有个必须要提的就是将DataFrame里面的字符串写进excel文件时,如何让excel显示为日期格式,分为两步:

①利用pandas.to_datetime()将DataFrame先转化成日期格式,然后用to_excel()写入EXCEL文件

②利用cell.number_format = 'yyyy/m/d'将单元格格式调整成日期格式

这是核心的两步,具体的还要看下面的源代码。

3.openpyxl绘制折线图,其中还包括两个比较冷门的知识点:

①调整数据标签(dLbls)的字体、颜色

②调整趋势线(trendline)的线型、颜色

网上关于这两知识点的案例极少,以至于我费了好长时间才整明白。

话不多说,上代码。

import pandas
import requests
import datetime

from openpyxl import load_workbook
from openpyxl.chart import LineChart, Reference
from openpyxl.chart.label import DataLabelList
from openpyxl.chart.shapes import GraphicalProperties
from openpyxl.chart.text import RichText
from openpyxl.chart.trendline import Trendline
from openpyxl.drawing.line import LineProperties
from openpyxl.drawing.text import Paragraph, ParagraphProperties, CharacterProperties
from openpyxl.styles import Font, Border, Side, Alignment


# 获取上周一
def getLastMonday():
    monday = datetime.date.today()  # 获取今天的日期
    one_day = datetime.timedelta(days=1)  # 获取日期单位增量:一天
    monday -= (7 * one_day)  # 将今天的日期减去7天,得到上周的今天
    # 以下代码,将上周的今天每次减1天,直到monday.weekday()为0为止。monday.weekday()是获取星期几,周一到周日依次是0到6
    while monday.weekday() != 0:
        monday -= one_day
    # 按格式输出字符串,可以理解为将日期格式转化为字符串格式
    return datetime.datetime.strftime(monday, "%Y-%m-%d")


# 获取上周五
def getLastFriday():
    friday = datetime.date.today()
    one_day = datetime.timedelta(days=1)
    friday -= (7 * one_day)
    if friday.weekday() > 4:
        while friday.weekday() != 4:
            friday -= one_day
    else:
        while friday.weekday() != 4:
            friday += one_day
    return datetime.datetime.strftime(friday, "%Y-%m-%d")


# 获取并格式化输出今年第一天
def get_first_day_of_this_year():
    this_year_start = datetime.datetime(datetime.datetime.today().year, 1, 1)
    return datetime.datetime.strftime(this_year_start, "%Y-%m-%d")


# 获取并格式化输出今天
def get_today():
    return datetime.datetime.strftime(datetime.datetime.today(), "%Y-%m-%d")


# post方法访问网页链接,以下是国家外汇局网站获取汇率的链接
url = "http://www.safe.gov.cn/AppStructured/hlw/RMBQuery.do"
headers = {"Content-Type": "text/html;charset=utf-8"}
r = requests.post(url, params={'startDate': getLastMonday(), 'endDate': getLastFriday()}, headers=headers)

#pandas.read_html方法从网页返回结果中拉取表格数据,保存在DataFrame对象中
df = pandas.read_html(r.text)[4].sort_index(ascending=False)
df1 = pandas.to_datetime(df["日期"], format="%Y-%m-%d") #由于df["日期"]是文本格式的,要先转化成日期格式,再写入excel文件时才能正常显示为日期格式
df2 = df["美元"].div(100).round(4) #除以100,并保留4位小数
df_eur = df["欧元"].div(100).round(4)
df3 = pandas.concat([df1, df2], axis=1).T #拼接多个DataFrame对象,并.T将结果转置
df3_1 = pandas.concat([df1, df_eur], axis=1).T
df3.to_excel("数据、图表.xlsx", header=False) #将DataFrame对象写入excel文件

#向excel文件中追加写入数据
filepath = "数据、图表.xlsx"
wb = load_workbook(filepath, data_only=True)
writer = pandas.ExcelWriter(filepath)
writer.book = wb
writer.sheets = {sheets.title: sheets for sheets in writer.book.worksheets}
df3_1.to_excel(writer, sheet_name="Sheet1", startrow=0, startcol=11, header=False) #指定写入的sheet名称,以及从第几行、第几列开始写
writer.save()
writer.close()

ws = wb.active
ws.cell(1, 7).value = "本周平均"
ws.cell(2, 7).value = df2.mean().round(4) #mean()方法用于DataFrame求平均数
ws.cell(1, 18).value = "本周平均"
ws.cell(2, 18).value = df_eur.mean().round(4)
for row in ws['A1:G2']:
    for cell in row:
        if cell.row == 1:
            cell.number_format = 'yyyy/m/d;@' #将单元格调整为日期格式,前提是写入的dataframe也是日期格式,最终excel里面才会正常显示为日期格式
        cell.font = Font(size=9) #调整单元格字体
        cell.border = Border(left=Side(style='thin'), right=Side(style='thin'), top=Side(style='thin'),
                             bottom=Side(style='thin')) #调整单元格边框
        cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) #调整单元格居中,自动换行
#以下代码与上一段趋同,就不详细注释了
for row in ws['L1:R2']:
    for cell in row:
        if cell.row == 1:
            cell.number_format = 'yyyy/m/d;@'
        cell.font = Font(size=9)
        cell.border = Border(left=Side(style='thin'), right=Side(style='thin'), top=Side(style='thin'),
                             bottom=Side(style='thin'))
        cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True)

#以下代码添加折线图
lc = LineChart()
# lc.title = ""
lc.style = 13 #设置表格样式
data = Reference(ws, min_col=1, min_row=2, max_col=6, max_row=2) #设置数据区域
line_data = Reference(ws, min_col=2, min_row=1, max_col=6, max_row=1) #设置标题区域
lc.add_data(data, from_rows=True, titles_from_data=True)
lc.set_categories(line_data)
line1 = lc.series[0]
# line1.graphicalProperties.line.solidFill = 'FF0000' #设置线条颜色
line1.graphicalProperties.line.width = 30000 #设置线条粗细
line1.dLbls = DataLabelList()
line1.dLbls.showVal = True  # 显示数据标签
axis = CharacterProperties(b=True, solidFill="FF0000")  # 与下一句一起设置数据标签字体加粗、红色
line1.dLbls.txPr = RichText(p=[Paragraph(pPr=ParagraphProperties(defRPr=axis), endParaRPr=axis)])
line1.trendline = Trendline(
    spPr=GraphicalProperties(ln=LineProperties(w=20000, prstDash='sysDot', solidFill='5082BE')))  # 显示蓝色点状趋势线
# line1.trendline = Trendline(spPr=GraphicalProperties(ln=LineProperties(solidFill='FF0000')))  # 显示红色趋势线
lc.legend = None  # 隐藏图例

lc1 = LineChart()
# lc1.title = ""
lc1.style = 13
data1 = Reference(ws, min_col=12, min_row=2, max_col=17, max_row=2)
line_data1 = Reference(ws, min_col=13, min_row=1, max_col=17, max_row=1)
lc1.add_data(data1, from_rows=True, titles_from_data=True)
lc1.set_categories(line_data1)
line1_1 = lc1.series[0]
# line1.graphicalProperties.line.solidFill = 'FF0000'
line1_1.graphicalProperties.line.width = 30000
line1_1.dLbls = DataLabelList()
line1_1.dLbls.showVal = True  # 显示数据标签
axis = CharacterProperties(b=True, solidFill="FF0000")  # 与下一句一起设置数据标签字体加粗、红色
line1_1.dLbls.txPr = RichText(p=[Paragraph(pPr=ParagraphProperties(defRPr=axis), endParaRPr=axis)])
# print(line1.dLbls.graphicalProperties)
line1_1.trendline = Trendline(
    spPr=GraphicalProperties(ln=LineProperties(w=20000, prstDash='sysDot', solidFill='5082BE')))  # 显示蓝色点状趋势线
# line1_1.trendline = Trendline(spPr=GraphicalProperties(ln=LineProperties(solidFill='FF0000')))  # 显示红色趋势线
lc1.legend = None  # 隐藏图例

ws.add_chart(lc, "A6")
ws.add_chart(lc1, "L6")

wb.create_sheet("Sheet2", 1)  # 创建一个新的工作表
wb.save("数据、图表.xlsx")

# 用DataFrame.to_excel()和ExcelWriter一起将数据追加到现有的工作簿中
filepath = "数据、图表.xlsx"
writer = pandas.ExcelWriter(filepath)
writer.book = wb
writer.sheets = {sheets.title: sheets for sheets in writer.book.worksheets}
r2 = requests.post(url, params={'startDate': get_first_day_of_this_year(), 'endDate': get_today()}, headers=headers)
df4 = pandas.read_html(r2.text)[4].sort_index(ascending=False)
df5 = pandas.concat(
    [pandas.to_datetime(df4['日期'], format="%Y-%m-%d"), df4['美元'].div(100).round(4), df4['欧元'].div(100).round(4)],
    axis=1)
df5.to_excel(writer, sheet_name="Sheet2", index=False)
writer.save()
writer.close()

# 调整sheet2的格式,调整前要重新load一遍工作簿,以获取最新的工作簿
wb = load_workbook("数据、图表.xlsx", data_only=True)
ws2 = wb["Sheet2"]
for row in ws2[ws2.dimensions]:
    for cell in row:
        if cell.column == 1:
            cell.number_format = 'yyyy/m/d;@'
        cell.font = Font(size=9)
        cell.border = Border(left=Side(style='thin'), right=Side(style='thin'), top=Side(style='thin'),
                             bottom=Side(style='thin'))
        cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True)

lc2 = LineChart()
# lc2.title = "今年外汇走势图"
lc2.style = 1
data = Reference(ws2, min_col=2, min_row=1, max_col=2, max_row=ws2.max_row)
line_data = Reference(ws2, min_col=1, min_row=2, max_col=1, max_row=ws2.max_row)
lc2.add_data(data, titles_from_data=True)
lc2.set_categories(line_data)
line3 = lc2.series[0]
line3.graphicalProperties.line.solidFill = '5082BE'
line3.graphicalProperties.line.width = 20000
line3.trendline = Trendline(
    spPr=GraphicalProperties(ln=LineProperties(w=20000, prstDash='sysDot', solidFill='5082BE')))  # 显示蓝色点状趋势线
lc2.legend = None  # 隐藏图例

lc3 = LineChart()
# lc2.title = "今年外汇走势图"
lc3.style = 1
data2 = Reference(ws2, min_col=3, min_row=1, max_col=3, max_row=ws2.max_row)
line_data2 = Reference(ws2, min_col=1, min_row=2, max_col=1, max_row=ws2.max_row)
lc3.add_data(data2, titles_from_data=True)
lc3.set_categories(line_data2)
line4 = lc3.series[0]
line4.graphicalProperties.line.solidFill = '5082BE'
line4.graphicalProperties.line.width = 20000
line4.trendline = Trendline(
    spPr=GraphicalProperties(ln=LineProperties(w=20000, prstDash='sysDot', solidFill='5082BE')))  # 显示蓝色点状趋势线
lc3.legend = None  # 隐藏图例

ws2.add_chart(lc2, "E2")
ws2.add_chart(lc3, "E20")

wb.save("数据、图表.xlsx")

 

下面是效果图

sheet1:

 

 

 

sheet2:

 

标签:Python,max,抓取,line1,datetime,cell,折线图,data,row
From: https://www.cnblogs.com/dige1993/p/16596815.html

相关文章

  • # Conda虚拟环境中的pip,python 等路径是base环境而非本虚拟环境
    现象一次运行项目发现,原本可以正常运行的项目,突然提示有个包不存在,但是经过piplist发现在我的虚拟环境中是存在这个包的,并且此时我是正常的位于我的虚拟环境中。报错......
  • python复习
    break;continue;passord();chr()格式化:%s;f’str’;format序列:字符串、列表、元组...                    索引切片:sname[start:end:step] ......
  • Python入门系列(一)安装环境
    python是什么python是一门很受欢迎的语言,除了不能生孩子以外,其它都可以做。它擅长的领域是脚本工具和科学数据这一块,比如大数据,数据分析什么的。python安装为了演示和......
  • python 中根据RNA序列输出密码子编码的氨基酸序列
     001、(base)root@PC1:/home/test4#lstest.py(base)root@PC1:/home/test4#cattest.py##测试程序#!/usr/bin/pythonrna="AUGGCCAUG......
  • 学习:python 第三方模块介绍
    第三方模块是由第三方个人或者组织使用python开发,需要先下载安装才能使用的工具包第三方模块来自各行各业使用python的开发人员为了不同行业的不停业务提供了解决方案 ......
  • 学习:python 内置模块datetime
    importtimeimportdatetime#获取当前的日期时间n=datetime.datetime.now()print(n)#获取一个指定时间da=datetime.datetime(2018,2,13,5,23,45)print(da)#日期......
  • 学习:python 内置模块 time
    importtimes1=time.time()#获取一个时间戳:当前时间距离1979年元旦0时的秒数,用户计算程序执行秒数开始前记录一次结束后记录一次相减forxinrange(1,10001):......
  • 学习:python 内置模块random
    importrandom#引入模块#创建的文件名项目的名字不要与引入的模块名重复r1=random.randint(1,6)#生成范围随机数r2=random.uniform(1,6)#生成指定范围随机浮点数r3=......
  • 学习:python 模块
    模块是python最高级别的组织单元将程序代码和数据封装起来以便重复使用模块中包含了实现某一类业务的多个函数和属性说的通俗点模块就是一个实现某种业务的工具包,每一......
  • python 日志写入文件
    importloggingfmt="%(asctime)s%(filename)s[line:%(lineno)d]%(levelname)s:%(message)s"logging.basicConfig(level=logging.DEBUG,format=fmt,......