利用Python抓取百度日历数据并写入数据库的实践
在日常开发和数据分析中,获取准确的日期信息,包括工作日、周末、节假日等,对于许多应用场景都至关重要。本文将详细介绍如何使用Python从百度日历接口抓取数据,并将其写入数据库。
一、项目背景
在实际项目中,我们常常需要根据日期来进行业务逻辑的处理。例如,在一个基于时间的任务调度系统中,我们需要知道哪些日期是工作日,哪些是节假日,以便合理安排任务的执行时间。百度日历提供了丰富且准确的日期信息,通过抓取其数据,我们可以满足这类业务需求。
二、技术实现
(一)关键代码结构
整个项目的代码主要包含以下几个关键部分:
- 定义表信息
def getTableInfo():
"""
写入表的表名和列名信息
:return:
"""
# 表名
tablename = ('date_info', '日期信息')
# 列名
fields = [('rq', '日期'), ('nf', '年份'), ('yf', '月份'),
('ny', '年月'), ('xqzwm', '星期中文名'), ('xqszx', '星期数字型'),
('sfjjrdm', '是否节假日代码'), ('sfjjrmc', '是否节假日名称'), ('jr', '节日')
]
return tablename, fields
这段代码定义了用于存储日历数据的表结构,包括表名date_info
及其对应的中文描述日期信息
,以及各列的名称和中文含义。
- 抓取百度日历数据
def catch_url_from_baidu(calcultaion_year, month):
insertdataall = []
header = {
"Content-Type": "application/json;charset=UTF-8"
}
param = {
"query": calcultaion_year + "年" + month + "月",
"resource_id": "39043",
"t": dataTime,
"ie": "utf8",
"oe": "gbk",
"format": "json",
"tn": "wisetpl",
"cb": ""
}
# 抓取位置:百度搜索框搜索日历,上面的日历的接口,可以在页面上进行核对
r = requests.get(url="https://sp0.baidu.com/8aQDcjqpAAV3otqbppnN2DJv/api.php",
headers=header, params=param).text
month_data = json.loads(r)["data"][0]["almanac"]
在catch_url_from_baidu
函数中,我们首先构建了请求头header
和请求参数param
。请求参数中包含了要查询的年份和月份信息,通过query
参数传递给百度接口。然后使用requests
库发送GET请求,获取百度日历接口返回的数据,并将其解析为JSON格式。
- 处理数据并构建插入数据列表
for one in month_data: # 偶数上班,奇数休息
# 非周末 且 无status 为正常工作日,记作:0
if ((one['cnDay'] != '日' and one['cnDay'] != '六') and 'status' not in one):
v = datetime.date(int(one['year']), int(one['month']), int(one['day']))
if ('term' in one):
# 构建包含节日信息的正常工作日数据
insertdataall.append(
[str(v), one['year'], one['month'], one['year'] + one['month'], '星期' + one['cnDay'], '1',
'0', '工作日', one['term']])
else:
# 构建不包含节日信息的正常工作日数据
insertdataall.append(
[str(v), one['year'], one['month'], one['year'] + one['month'], '星期' + one['cnDay'], '1',
'0', '工作日', ''])
# 周末 且 无status 为正常周末休息,记作:1
elif ((one['cnDay'] == '日' or one['cnDay'] == '六') and 'status' not in one):
# 类似上述逻辑,构建正常周末休息的数据
# 周末 且 status=2(补班) 为周末补班,记作:2
elif ((one['cnDay'] == '日' or one['cnDay'] == '六') and ('status' in one and one["status"] == '2')):
# 构建周末补班的数据
# status=1(节假日) 为节假日休息,记作:3
elif ('status' in one and one["status"] == '1'):
# 构建节假日休息的数据
这部分代码通过遍历获取到的日历数据month_data
,根据不同的条件判断每一天是工作日、周末、周末补班还是节假日,并将相应的信息构建成列表形式,存储在insertdataall
中。
- 插入数据到数据库
tablename, fields = getTableInfo()
print(insertdataall)
dao = GwljDao()
try:
dao.connect()
dao.insert3(tablename, fields, insertdataall)
print("插入数据库成功")
finally:
dao.close()
在获取并处理好数据后,我们调用getTableInfo
函数获取表名和列名信息,然后实例化数据库操作对象dao
(这里假设GwljDao
类已经定义好数据库连接和插入操作的方法)。通过try - finally
块确保在插入数据成功后关闭数据库连接。
(二)主程序逻辑
def Calendar():
now_time = datetime.datetime.now()
now = now_time.strftime("%Y")
date_time = now_time.strftime("%m-%d")
# date_time = "01-01"
print(date_time)
# 此处只能算当年之前的,因为国务院是每年12月份才会发布第二年的放假计划,所以此接口对于下一年的统计是错的。
calcultaion_year = now
# 因该接口传入的时间,查询了前一个月,当前月和后一个月的数据,所以只需要2、5、8、11即可全部获取到。比如查询5月份,则会查询4,5,6月分的数据
calculation_month = ["2", "5", "8", "11"]
if date_time == '01-01':
for one_month in calculation_month:
catch_url_from_baidu(calcultaion_year, one_month)
else:
print("该年数据已经获取")
在Calendar
函数中,我们首先获取当前时间,并提取出年份now
和日期date_time
。由于百度日历接口对于下一年的数据统计可能存在问题(国务院每年12月才发布次年放假计划),所以我们只处理当年的数据。同时,根据接口的特性,我们发现通过查询2月、5月、8月和11月的数据,就可以覆盖全年的日历信息。最后,通过判断当前日期是否为1月1日来决定是否执行数据抓取操作,如果是1月1日,则循环调用catch_url_from_baidu
函数获取不同月份的数据。
三、项目总结
通过上述步骤,我们成功实现了从百度日历接口抓取数据,并将其整理后写入数据库。在实际应用中,我们可以根据数据库中存储的日历数据进行各种业务逻辑的开发,如任务调度、数据分析等。需要注意的是,百度的接口可能会发生变化,在使用过程中需要定期检查接口的可用性和数据格式的变化。同时,这种抓取数据的方式应遵循相关法律法规和网站的使用条款,确保数据的合法获取和使用。希望本文能为大家在处理日期相关数据的项目中提供一些有益的参考和思路。