- 在日常业务开发中常常会碰到需要从一段文字中提取时间的情况。
- 需要识别的文字段,例如从“技术总是要日积月累的,我是技术空间,欢迎关注我。此文章2022-09-21发布”提取日期。
pip install chardet -i https://pypi.douban.com/simple/
这里自定义需要提取出来后的时间格式:年-月-日 时:分:秒(%Y-%m-%d %H:%M:%S),
即base_date='2020-01-01 00:00:00',可以根据自己的格式修改为自己想要的格式。
定义正则匹配
# 正则中的%s分割
splits = [
{1: [('年', '月', '日', '点', '分', '秒'), ('-', '-', '', ':', ':', ''), ('\/', '\/', '', ':', ':', ''),
('\.', '\.', '', ':', ':', '')]},
{2: [('年', '月', '日', '点', '分'), ('-', '-', '', ':', ''), ('\/', '\/', '', ':', ''), ('\.', '\.', '', ':', '')]},
{3: [('年', '月', '日'), ('-', '-', ''), ('\/', '\/', ''), ('\.', '\.', '')]},
{4: [('年', '月', '日'), ('-', '-', ''), ('\/', '\/', ''), ('\.', '\.', '')]},
{5: [('月', '日', '点', '分', '秒'), ('-', '', ':', ':', ''), ('\/', '', ':', ':', ''), ('\.', '', ':', ':', '')]},
{6: [('月', '日', '点', '分'), ('-', '', ':', ''), ('\/', '', ':', ''), ('\.', '', ':', '')]},
{7: [('月', '日'), ('-', ''), ('\/', ''), ('\.', '')]},
{8: [('点', '分', '秒'), (':', ':', '')]},
{9: [('点', '分'), (':', '')]},
]
# 匹配正则表达式
matchs = {
1: (r'\d{4}%s\d{1,2}%s\d{1,2}%s \d{1,2}%s\d{1,2}%s\d{1,2}%s', '%%Y%s%%m%s%%d%s %%H%s%%M%s%%S%s'),
2: (r'\d{4}%s\d{1,2}%s\d{1,2}%s \d{1,2}%s\d{1,2}%s', '%%Y%s%%m%s%%d%s %%H%s%%M%s'),
3: (r'\d{4}%s\d{1,2}%s\d{1,2}%s', '%%Y%s%%m%s%%d%s'),
4: (r'\d{2}%s\d{1,2}%s\d{1,2}%s', '%%y%s%%m%s%%d%s'),
# 没有年份
5: (r'\d{1,2}%s\d{1,2}%s \d{1,2}%s\d{1,2}%s\d{1,2}%s', '%%m%s%%d%s %%H%s%%M%s%%S%s'),
6: (r'\d{1,2}%s\d{1,2}%s \d{1,2}%s\d{1,2}%s', '%%m%s%%d%s %%H%s%%M%s'),
7: (r'\d{1,2}%s\d{1,2}%s', '%%m%s%%d%s'),
# 没有年月日
8: (r'\d{1,2}%s\d{1,2}%s\d{1,2}%s', '%%H%s%%M%s%%S%s'),
9: (r'\d{1,2}%s\d{1,2}%s', '%%H%s%%M%s'),
}
parten_other = '\d 天前|\d 分钟前|\d 小时前|\d 秒前'
class TimeFinder(object):
def __init__(self, base_date=None):
self.base_date = base_date
self.match_item = []
self.init_args()
self.init_match_item()
def init_args(self):
# 格式化基础时间
if not self.base_date:
self.base_date = datetime.now()
if self.base_date and not isinstance(self.base_date, datetime):
try:
self.base_date = datetime.strptime(self.base_date, '%Y-%m-%d %H:%M:%S')
except Exception as e:
raise Exception('type of base_date must be str of%Y-%m-%d %H:%M:%S or datetime')
def init_match_item(self):
# 构建穷举正则匹配公式 及提取的字符串转datetime格式映射
for item in splits:
for num, value in item.items():
match = matchs[num]
for sp in value:
tmp = []
for m in match:
tmp.append(m % sp)
self.match_item.append(tuple(tmp))
def get_time_other(self, text):
m = re.search('\d ', text)
if not m:
return None
num = int(m.group())
if '天' in text:
return self.base_date - timedelta(days=num)
elif '小时' in text:
return self.base_date - timedelta(hours=num)
elif '分钟' in text:
return self.base_date - timedelta(minutes=num)
elif '秒' in text:
return self.base_date - timedelta(seconds=num)
return None
def find_time(self, text):
# 格式化text为str类型
if isinstance(text, bytes):
encoding = chardet.detect(text)['encoding']
text = text.decode(encoding)
res = []
parten = '|'.join([x[0] for x in self.match_item])
parten = parten '|' parten_other
match_list = re.findall(parten, text)
if not match_list:
return None
for match in match_list:
for item in self.match_item:
try:
date = datetime.strptime(match, item[1].replace('\\', ''))
if date.year == 1900:
date = date.replace(year=self.base_date.year)
if date.month == 1:
date = date.replace(month=self.base_date.month)
if date.day == 1:
date = date.replace(day=self.base_date.day)
res.append(datetime.strftime(date, '%Y-%m-%d %H:%M:%S'))
break
except Exception as e:
date = self.get_time_other(match)
if date:
res.append(datetime.strftime(date, '%Y-%m-%d %H:%M:%S'))
break
if not res:
return None
return res
- 执行入口
def handleDate(time_str):
result = None
# 定义日期格式
timefinder = TimeFinder(base_date='2020-01-01 00:00:00')
parsed_time = timefinder.find_time(time_str.replace("\t", "").replace("\n", ""))
if parsed_time is None:
if time_str.find("年") >= 0:
parsed_time = timefinder.find_time(time_str.replace(" ", "").replace("\t", ""))
if parsed_time is not None:
result = parsed_time[0]
else:
result = parsed_time[0]
return result
if __name__ == '__main__':
test1 = "技术总是要日积月累的,我是技术空间,欢迎关注我。此文章2022-09-21发布"
test2 = "技术总是要日积月累的,我是技术空间,欢迎关注我。此文章2022/09/21发布"
test3 = "技术总是要日积月累的,我是技术空间,欢迎关注我。此文章2022-9-21发布"
test4 = "技术总是要日积月累的,我是技术空间,欢迎关注我。此文章2022-09-21 08:01发布"
test5 = "技术总是要日积月累的,我是技术空间,欢迎关注我。此文章2022-09-21 08:01:01发布"
test6 = "技术总是要日积月累的,我是技术空间,欢迎关注我。此文章2022年9月21日发布"
print(test1 " -> " handleDate(test1))
print(test2 " -> " handleDate(test2))
print(test3 " -> " handleDate(test3))
print(test4 " -> " handleDate(test4))
print(test5 " -> " handleDate(test5))
print(test6 " -> " handleDate(test6))
此方法可以识别大部分文字段落中带有日期字符串的日期,日期必须是数字日期,不可是大写的,“一月”、“二零二二年”之类的识别不了。
关注我,坚持每日积累一个技巧,长期坚持,我们将会不断进步。
#java##python##程序员##git##计算机#
,