如何利用Python批量爬取人民币外汇数据并整理储存可视化!

如何利用Python批量爬取人民币外汇数据并整理储存可视化!

一、需求
由于该网站(http://www.safe.gov.cn/safe/rmbhlzjj/index.html)日期选择最长间隔只能90天,因此如果手动点击下载表格,需要多次选择日期,并且将多个表格手动合并后存入数据库。为了解决这些问题,本篇使用爬虫爬取,pandas整理数据后存入数据库。

二、实现
STEP1 爬取第一批数据
打开网站,输入在允许范围内的日期,点击查询,就发送了一个POST请求
在这里插入图片描述

F12打开开发者工具刷新后,可以看到这个请求的url和请求体信息,仿照该请求体,设置发送请求的data参数
在这里插入图片描述
在这里插入图片描述

import requests
payload = {
'startDate':'2020-01-01',
'endDate':'2020-03-30',
'queryYN':'true'
}
res = requests.post('http://www.safe.gov.cn/AppStructured/hlw/RMBQuery.do', data = payload)
1234567

STEP2 解析数据
用查看器查看表格位置(id=“InfoTable”),使用beautifulsoup解析数据
在这里插入图片描述

from bs4 import BeautifulSoup
soup = BeautifulSoup(res.text, 'html.parser')
type(soup.select('#InfoTable')[0])
>>>bs4.element.Tag
1234

pd.read_html()需要传入的io:str or file-like,需要用prettify()方法格式化一下,顺便设置下编码

import pandas as pd
dfs = pd.read_html(soup.select('#InfoTable')[0].prettify('utf-8'), header=0)
df_rates=dfs[0]
df_rates.head()
1234

在这里插入图片描述

STEP3 数据转换
得到的数据是一个二维表,需要存储到数据库,为了以后更好地使用,需要降低维度
使用pd.melt()方法逆透视

df_rates=pd.melt(df_rates,col_level=0,  id_vars=['日期'])
df_rates.columns = ['date', 'currency', 'exchange']
df_rates.head()
123

或者一步步转

se=df_rates.set_index('日期').stack()
se.index.names=['date', 'currency']
df_rates=se.reset_index(name='exchange')
df_rates.head()
1234

在这里插入图片描述

STEP4 存储数据到数据库

import sqlite3
with sqlite3.connect('currency.sqlite') as db:
    df_rates.to_sql('currency_data', con=db, if_exists='replace', index = None)
123

STEP5 整合成自定义方法
上述4个步骤已经完成了一次完整的抓取-处理-存储过程,之后只要改变request请求的日期就能完成长时间距离的数据获取,因此可以将上述步骤整合成可调用的自定义方法,只需要传入时间参数

import requests
import pandas as pd
from bs4 import BeautifulSoup
import sqllite3
def getCurrency(start, end):
	#STEP 1
	payload = {
	'startDate':start,
	'endDate':end,
	'queryYN':'true'
	}
	res = requests.post('http://www.safe.gov.cn/AppStructured/hlw/RMBQuery.do', data = payload)
	
	#STEP2
	soup = BeautifulSoup(res.text, 'html.parser')
	
	dfs = pd.read_html(soup.select('#InfoTable')[0].prettify(), header=0)
	df_rates=dfs[0]
	
	#STEP3
	df_rates=pd.melt(df_rates,col_level=0,  id_vars=['日期'])
	df_rates.columns = ['date', 'currency', 'exchange']

	#STEP4
	with sqlite3.connect('currency.sqlite') as db:
    	df_rates.to_sql('currency_data', con=db, if_exists='append', index = None)
1234567891011121314151617181920212223242526

STEP6 使用循环
上述4个步骤已经完成了一次完整的抓取-处理-存储过程,如果需要抓取365天至今的数据,至少需要math.ceil(365/90)=5次,每次请求体中日期之间都是等距的90天

from datetime import datetime, timedelta
current_time = datetime.now()
for i in range(-1,365-1,90):
    start_date = (current_time - timedelta(days = i + 90)).strftime('%Y-%m-%d')
    end_date   = (current_time - timedelta(days = i +1)).strftime('%Y-%m-%d')
    #print(start_date, end_date)
    getCurrency(start_date, end_date)
1234567

STEP7 取数可视化
上述步骤已经将所需数据存入数据库,可以在python中使用pandas执行SQL语句查询到所需数据进行分析
1.查询“美元“的汇率中间价

with lite.connect('currency.sqlite') as db:
    df = pandas.read_sql("SELECT * FROM currency_data WHERE currency = '美元'", con=db)
12

2.修改数据类型

#df.info()
df['date'] = pandas.to_datetime(df['date'], format= '%Y-%m-%d')
12

3.将日期列转为索引

df=df.set_index('date')
1

4.可视化数据

% pylab inline

#线图

df.plot(kind = 'line')

#30天移动平均线

df['mvg30']  = df['exchange'].rolling(window=30).mean()

#同时展示

df[['exchange', 'mvg30']].plot(kind = 'line')
1234567

如果同时取”美元”和“英镑“,多个系列在同一张图上,需要将项透视成列

with sqlite3.connect('currency.sqlite') as db:
    df = pd.read_sql("SELECT * FROM currency_data WHERE currency IN ('美元', '英镑') ", con=db)

df['date'] = pandas.to_datetime(df['date'], format= '%Y-%m-%d')

#建立数据透视表

df2 = df.pivot_table(index= 'date', columns= 'currency')

#绘图

plt.rcParams['font.sans-serif']=['SimHei']
df2.plot(kind= 'line', rot= 30)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值