哈喽,大家好呀,好久不见!因为最近太忙了,就一直忘了更新文章。不过今天,就大家分享一期小算法(哈哈,就是简单的逻辑规则罢了)
最近在工作期间,需求提出了一个之前没有遇到过的问题,就是有一个需求字段是日期天数,但是原网站给出的是一个时间区间,而且我们都知道,做数据聚合的时候,就会出现各种情况,同样,聚合的数据有各种形式的时间区间,如2017年12月26日至2016年7月6日、2016-04-20至2016-06-30、5个月、22016.10.1-2016.11.16 47天、201908-202106等等情况。那么我们要将这些数据转换成天数,就可以考虑写一个小的训练算法,我们就可以写规则去匹配各种形式的时间区间文本
1.首先,先介绍一下我们要用到的包,这里主要是用到的是pandas,大家都知道,数据处理分析方面pandas是有着强大的优势的。另外就是需要用到cn2an,在这里我是用它来将 ‘五个月’ 类似的格式的月数转数字,方便进行后续操作
import datetime, cn2an
import re
import pandas as pd
def cn_to_an(text):
output = cn2an.cn2an(text, "smart")
return output
2.第二步就是将时间区间文本进行前、后时间点进行分离(这里的规则大家可以按自己需求完善)
def get_date_difference(date_str):
if '至' in date_str:
date_before = date_str.split('至')[-1]
date_after = date_str.split('至')[0]
days = 0
elif '-' in date_str and '天' in date_str and ',' not in date_str and ',' not in date_str:
date_before = ''
date_after = ''
days = date_str.split(' ')[-1].replace('天', '').strip()
elif '-' in date_str and ',' in date_str:
date_before = ''
date_after = ''
days = date_str.split(',')[-1].replace('天', '').strip()
elif '-' in date_str and ',' in date_str:
date_before = ''
date_after = ''
days = date_str.split(',')[-1].replace('天', '').strip()
elif '-' in date_str and '天' not in date_str and ',' not in date_str and ',' not in date_str and '.' not in date_str:
date_before0 = date_str.split('-')[-1]
if len(date_before0) == 8:
date_before = date_str.split('-')[-1][:4] + '.' + date_str.split('-')[-1][4:6] + '.' + date_str.split('-')[-1][6:]
date_after = date_str.split('-')[0][:4] + '.' + date_str.split('-')[0][4:6] + '.' + date_str.split('-')[0][6:]
days = 0
elif len(date_before0) == 6:
date_before = date_str.split('-')[-1][:4] + '.' + date_str.split('-')[-1][4:]
date_after = date_str.split('-')[0][:4] + '.' + date_str.split('-')[0][4:]
days = 0
else:
date_before = ''
date_after = ''
days = '0'
elif '-' in date_str:
date_before = date_str.split('-')[-1]
date_after = date_str.split('-')[0]
days = 0
elif '-' in date_str and '天' in date_str:
date_before = ''
date_after = ''
days = date_str.split(' ')[-1].replace('天', '').strip()
elif '-' in date_str:
date_before = date_str.split('-')[-1]
date_after = date_str.split('-')[0]
days = 0
elif '—' in date_str and '天' in date_str:
date_before = ''
date_after = ''
days = date_str.split(' ')[-1].replace('天', '').strip()
elif '—' in date_str and '工期' in date_str:
date_before = ''
date_after = ''
days = date_str.split(' ')[-1].replace('工期', '').strip()
elif '—' in date_str:
date_before = date_str.split('—')[-1]
date_after = date_str.split('—')[0]
days = 0
elif '~' in date_str and '天' in date_str:
date_before = ''
date_after = ''
days = date_str.split(' ')[-1].replace('天', '').strip()
elif '~' in date_str:
date_before = date_str.split('~')[-1]
date_after = date_str.split('~')[0]
days = 0
elif '——' in date_str and '天' in date_str:
date_before = ''
date_after = ''
days = date_str.split(' ')[-1].replace('天', '').strip()
elif '——' in date_str:
date_before = date_str.split('——')[-1]
date_after = date_str.split('——')[0]
days = 0
elif '天' in date_str and '-' not in date_str and '至' not in date_str:
date_before = ''
date_after = ''
days = date_str.replace('(日历天)', '').replace('日历天', '').replace('天', '').strip()
elif "个月" in date_str:
date_before = ''
date_after = ''
days0 = "" if re.search('(.*)个月', date_str, re.S) == None else re.search('(.*)个月', date_str, re.S).group(1).strip()
days = "" if days0 == '' else str('%.0f' % (cn_to_an(days0)*30))
elif '天' not in date_str and '-' not in date_str and '至' not in date_str:
date_before = ''
date_after = ''
days = date_str.strip()
else:
date_before = ''
date_after = ''
days = date_str.strip()
return date_before, date_after, days
3.第三步就是将各种格式的时间字符串转时间格式(这里的规则大家可以按自己需求去完善)
def to_datetime_str(time_str):
new_time = pd.to_datetime(time_str, yearfirst=True, errors='ignore')
if new_time == time_str:
# 特殊格式的时间,可以再这里添加规则
format_list = ["%Y~%m~%d", "%Y|%m|%d", "%Y~%m~%d %H:%M:%S", "%Y|%m|%d %H:%M:%S", "%Y年%m月%d日"]
format_index = 0
while new_time == time_str:
if format_index == len(format_list):
return {"succ": False, "datetime": None, "datetime_string": "没有匹配当前时间的规则"}
new_time = pd.to_datetime(time_str, format=format_list[format_index], yearfirst=True, errors='ignore')
if new_time != time_str:
return {"succ": True, "datetime": new_time.to_pydatetime(), "datetime_string": str(new_time)}
format_index += 1
else:
return {"succ": True, "datetime": new_time.to_pydatetime(), "datetime_string": str(new_time)}
4.第四步就是获取前后日期的差值天数
def date_difference(date_before, date_after):
date_before = datetime.datetime.strptime(date_before, '%Y-%m-%d %H:%M:%S')
date_after = datetime.datetime.strptime(date_after, '%Y-%m-%d %H:%M:%S')
days = date_after - date_before
return days.days
5.最后,通过函数调用以上方法,实现各种时间区间的天数转换
def get_days(date_text):
a = get_date_difference(date_text)[0]
b = get_date_difference(date_text)[1]
c = get_date_difference(date_text)[2]
# print(a, b, c)
if a == '' or b == '':
days = c.replace('日', '')
else:
date_before = to_datetime_str(b)
date_after = to_datetime_str(a)
if date_after.get('succ') and date_before.get('succ'):
date_before = date_before.get('datetime_string')
date_after = date_after.get('datetime_string')
days = str(date_difference(date_before, date_after)).replace('-', '')
else:
days = '0'
return days
展示结果:
print('********************')
print(get_days('2017年12月26日至2016年7月6日'))
print(get_days('2016-04-20至2016-06-30'))
print(get_days('5个月'))
print(get_days('230 天'))
print(get_days('480(日历天)'))
print(get_days('480 日历天'))
print(get_days('2017.2.20-2018.6.30'))
print(get_days('2017.4-2017.9'))
print(get_days('2017.04-2017.12'))
print(get_days('22016.10.1-2016.11.16 47天'))
print(get_days('2016/10/01-2017/10/01'))
print(get_days('1900-01-01至1900-01-01'))
# '2019.05.29-2020.12.31、'
print(get_days('2019.05.29-2020.12.31'))
# '2019.02.11~2019.08.10、'
print(get_days('2019.02.11~2019.08.10'))
# '2017.7.1——2018.12.31、'
print(get_days('2017.7.1——2018.12.31'))
# '2016.4.20-2016.12.31,251(逗号后面的是天数)、'
print(get_days('2016.4.20-2016.12.31,251天'))
# '2016.12.01-2017.06.06,203(逗号后面的是天数)、'
print(get_days('2016.12.01-2017.06.06,203天'))
# '2014.5—2014.8(按月初算)、'
print(get_days('2014.5—2014.8'))
# '2016.10.9—2017.1.6 工期90'
print(get_days('2016.10.9—2017.1.6 工期90'))
# '5.0(五个月)、'
print(get_days('5个月'))
# 660日
print(get_days('660日'))
# 2014.05.20-2014.11.31
print(get_days('2014.05.20-2014.11.30'))
# 201908-202106
print(get_days('2019.08-2021.06'))
print(get_days('201908-202106'))
print(get_days('20170305-20171005'))
那么本期的分享就结束了,想要学习更多的python爬虫相关技巧和知识的小伙伴们一定要点下关注哟,后期会不定时分享相关干货内容。临近年底,最后祝大家春节快乐,事业兔飞猛进!!!