如何从python中的字符串中提取月份和年份?
Posted
技术标签:
【中文标题】如何从python中的字符串中提取月份和年份?【英文标题】:How can i extract month and year from a string in python? 【发布时间】:2020-09-18 10:40:02 【问题描述】:输入文本:
text = "Wipro Limited | Hyderabad, IN Dec 2017 – Present
Project Analyst
Infosys | Delhi, IN Apr 2017 – Nov 2017
Software Developer
HCL Technologies | Hyderabad, IN Jun 2016 – Mar 2017
Software Engineer
"
我为此编写了一个代码,但它显示在每个提取的单词的列表中,并且无法执行任何操作。
regex = re.compile('(?P<month>[a-zA-Z]+)\s+(?P<year>\d4)\s+\–\s+(?P<month1>[a-zA-Z]+)\s+(?P<year1>\d4)')
mat = re.findall(regex, text)
mat
查看代码:https://regex101.com/r/mMlgYp/1。 我希望像下面这样的输出来预览日期并做出改变,然后计算总经验: 此处“当前”或“截止日期”应考虑当前月份和年份。
import time
Present = time.strftime("%m-%Y")
Present
# output: '05-2020'
#Desired output
Extracted dates:
[('Dec 2017 - Present'),
('Apr 2017 - Nov 2017'),
('Jun 2016 - Mar 2017')]# and so on ...should display all the search results
First experience: 1.9 years
second experience: 8 months
third experience: 7 months
# and so on ...should display all the search results
Total experience: 3.4 years
请帮我解决这个问题,我是编程语言和 NLP、正则表达式的新手。
【问题讨论】:
【参考方案1】:您可能最终希望在数据框中使用它,因为您将它标记为 pandas(请参阅Andrej's answer),但无论哪种方式,您都可以使用插值从字符串中解析日期:
fr"(?i)((?:months) *\d4) *(?:-|–) *(present|(?:months) *\d4)"
其中months
是所有可能的月份名称和缩写的交替组。
import calendar
import re
from datetime import datetime
from dateutil.relativedelta import relativedelta
text = """Wipro Limited | Hyderabad, IN Dec 2017 – Present
Project Analyst
Infosys | Delhi, IN Apr 2017 – Nov 2017
Software Developer
HCL Technologies | Hyderabad, IN Jun 2016 – Mar 2017
Software Engineer
"""
def parse_date(x, fmts=("%b %Y", "%B %Y")):
for fmt in fmts:
try:
return datetime.strptime(x, fmt)
except ValueError:
pass
months = "|".join(calendar.month_abbr[1:] + calendar.month_name[1:])
pattern = fr"(?i)((?:months) *\d4) *(?:-|–) *(present|(?:months) *\d4)"
total_experience = None
for start, end in re.findall(pattern, text):
if end.lower() == "present":
today = datetime.today()
end = f"calendar.month_abbr[today.month] today.year"
duration = relativedelta(parse_date(end), parse_date(start))
if total_experience:
total_experience += duration
else:
total_experience = duration
print(f"start-end (duration.years years, duration.months months)")
if total_experience:
print(f"total experience: total_experience.years years, total_experience.months months")
else:
print("couldn't parse text")
输出:
Dec 2017-May 2020 (2 years, 5 months)
Apr 2017-Nov 2017 (0 years, 7 months)
Jun 2016-Mar 2017 (0 years, 9 months)
total experience: 3 years, 9 months
【讨论】:
嗨@ggorlen,非常感谢您的快速响应。它非常适合上面的代码,但是当我将简历解析为文本并将这个文本文件传递给上面的代码时,它会抛出一个错误。 ibb.co/w42sQ6m。 (附图片)。错误:AttributeError:“NoneType”对象没有属性“years”。提前致谢。 你能把文字发到s
吗?可能的原因是恢复字符串与此处显示的不同导致正则表达式失败,因此re.findall
未返回任何结果,total_experience
从未设置。
@ggorlen,请查看附件图片。 ibb.co/9p36RHG
请发帖as text。我无法复制和粘贴此内容或查看空格等。尽管如此,很明显添加在原始格式上运行良好的^(.+?) *\| *(.+?) *
不适用于此版本。如果您将其连同与 company
和 location
相关的任何内容一起删除,它应该可以工作。
好的,谢谢。看我的更新。请记住,正则表达式无法解析任意格式的文本,因此编写可以从一堆随机 pdf 中提取日期范围的代码有点困难(不可能?)。它们必须具有相当良好的格式,并且尝试在所有边缘情况下编写可能是一项无休止的任务(两位数年份而不是四位数年份,'05
而不是 2005
,不同的空格和分隔符。 ..).【参考方案2】:
import re
import numpy as np
import pandas as pd
text = '''Wipro Limited | Hyderabad, IN Dec 2017 – Present
Project Analyst
Infosys | Delhi, IN Apr 2017 – Nov 2017
Software Developer
HCL Technologies | Hyderabad, IN Jun 2016 – Mar 2017
Software Engineer
'''
def pretty_format(monthts):
return f'monthts/12:.1f years' if monthts > 11 else f'monthts:.1f months'
data = []
for employer, d1, d2 in re.findall(r'(.*?)\s*\|.*([A-Z][a-z]2 [12]\d3) – (?:([A-Z][a-z]2 [12]\d3)|Present)', text):
data.append('Employer': employer, 'Begin': d1, 'End': d2 or np.nan)
df = pd.DataFrame(data)
df['Begin'] = pd.to_datetime(df['Begin'])
df['End'] = pd.to_datetime(df['End'])
df['Experience'] = ((df['End'].fillna(pd.to_datetime('now')) - df['Begin']) / np.timedelta64(1, 'M')).apply(pretty_format)
print(df)
total = np.sum(df['End'].fillna(pd.to_datetime('now')) - df['Begin']) / np.timedelta64(1, 'M')
print()
print(f'Total experience = pretty_format(total)')
打印:
Employer Begin End Experience
0 Wipro Limited 2017-12-01 NaT 2.5 years
1 Infosys 2017-04-01 2017-11-01 7.0 months
2 HCL Technologies 2016-06-01 2017-03-01 9.0 months
Total experience = 3.8 years
【讨论】:
OP 有 3.4 年,你有 3.8 年,我有 3.9 年。 死 @ggorlen 我认为这是四舍五入的问题,当我在格式中使用.2f
时,我得到3.83 years
。 也死了
哦,等等,我得到了 3 年零 9 个月,这与小数点不同。我觉得一年的小部分很奇怪,所以我会坚持使用月份格式。
嗨@Andrej Kesely,非常感谢您的快速回复。感谢您应用后期阶段所需的数据框。对于上面的代码,它工作得很好,但是当我将简历解析为文本并将文本文件传递到上面的代码中时,它会抛出一个错误。 ibb.co/FwyQRmS。 (附图片)。错误:KeyError: 'Begin' 在处理上述异常的过程中,发生了另一个异常:以上是关于如何从python中的字符串中提取月份和年份?的主要内容,如果未能解决你的问题,请参考以下文章