Вилучення дати з рядка в Python


82

Як я можу вилучити дату із рядка типу "мавпа 10.07.2010 люблю банан"? Дякую!


3
Тільки підказка: починається і закінчується цифрою. Дозвольте подумати над цим. Хоча, регулярний вираз може бути там вашим другом.
Hamish Grubijan

Відповіді:


82

Якщо дата вказана у фіксованій формі, ви можете просто використовувати регулярний вираз для вилучення дати та "datetime.datetime.strptime" для синтаксичного аналізу дати:

import re
from datetime import datetime

match = re.search(r'\d{4}-\d{2}-\d{2}', text)
date = datetime.strptime(match.group(), '%Y-%m-%d').date()

В іншому випадку, якщо дату вказано у довільній формі, ви не зможете легко її отримати.


1
Що робити, якщо він у європейському форматі, наприклад 20.01.1980, що означає "20 січня 1980 року"? Що робити, якщо місяці / дні / роки виходять за межі розумного діапазону?
Hamish Grubijan

@lunaryorn У першому твердженні "re" означає "рядок", де ми шукаємо бажаний зразок?
вішал

@ vishal.k Це стосується вбудованого reмодуля, тобто import re.
lunaryorn

На випадок, якщо хтось припустився тієї ж помилки: вам потрібно from datetime import datetimeзамістьimport datetime
dankal444

155

Використання python-dateutil :

In [1]: import dateutil.parser as dparser

In [18]: dparser.parse("monkey 2010-07-10 love banana",fuzzy=True)
Out[18]: datetime.datetime(2010, 7, 10, 0, 0)

Недійсні дати піднімають ValueError:

In [19]: dparser.parse("monkey 2010-07-32 love banana",fuzzy=True)
# ValueError: day is out of range for month

Він може розпізнавати дати у багатьох форматах:

In [20]: dparser.parse("monkey 20/01/1980 love banana",fuzzy=True)
Out[20]: datetime.datetime(1980, 1, 20, 0, 0)

Зверніть увагу, що це робить припущення, якщо дата неоднозначна:

In [23]: dparser.parse("monkey 10/01/1980 love banana",fuzzy=True)
Out[23]: datetime.datetime(1980, 10, 1, 0, 0)

Але спосіб аналізу двозначних дат можна налаштувати:

In [21]: dparser.parse("monkey 10/01/1980 love banana",fuzzy=True, dayfirst=True)
Out[21]: datetime.datetime(1980, 1, 10, 0, 0)

3
@Hamish: Якщо є дві дати (як у випадку з "monkey 10/01/1980 love 7/10/2010 banana"), це може викликати ValueError або (як у випадку "monkey 10/01/1980 love 2010-07-10 banana") може неправильно інтерпретувати другу дату як позначення годин, хвилин, секунд або часового поясу. fuzzy=Trueдає йому ліцензію на вгадування.
unutbu

1
@unutbu str = "Автор flufie  · 14 жовтня 2010 о 23:22  · 26 відповідей" За допомогою dateutil я отримую "ValueError: година повинна бути в 0..23"
saravanan

що станеться, якщо в тексті більше 1 дати?
alvas

1
@alvas: parseФункція може викликати виняток (навіть якщо fuzzy=True) або fuzzy=Trueможе повертати першу дату або міш-маш, що складається з частин обох дат. Отже, насправді parseслід викликати лише рядок, що містить одну дату.
unutbu

1
@Kailegh: Так, можна було б вивести індекси, використовуючи fuzzy_with_tokens = True . Якщо ви хочете отримати додаткові роз’яснення, будь ласка, розпочніть нове запитання.
unutbu

27

Для вилучення дати з рядка в Python; кращий модуль доступний є datefinder модуль.

Ви можете використовувати його у своєму проекті Python, дотримуючись простих кроків, наведених нижче.

Крок 1: Встановіть пакет шукача дат

pip install datefinder

Крок 2: Використовуйте його у своєму проекті

import datefinder

input_string = "monkey 2010-07-10 love banana"
# a generator will be returned by the datefinder module. I'm typecasting it to a list. Please read the note of caution provided at the bottom.
matches = list(datefinder.find_dates(input_string))

if len(matches) > 0:
    # date returned will be a datetime.datetime object. here we are only using the first match.
    date = matches[0]
    print date
else:
    print 'No dates found'

зауважте: якщо ви очікуєте великої кількості матчів; тоді введення тексту в список не буде рекомендованим способом, оскільки воно матиме великі накладні витрати.


1
Я виявив, що datefinderвручення неоднозначного збігу дат було кращим, ніж python-dateutilповернення лише двох можливих дат із випадкового допису в блозі media.com на відміну від п’яти. Не впевнений, як це обробляє різні локалі, проте ...
CpILL

Це досить добре, за винятком того, що якимось чином не працює, коли є двокрапка (:) перед рядком дати: string = "Assessment Date: 17-May-2017 at 13:31" list(datefinder.find_dates(string.lower())) #[] string = "Assessment Date 17-May-2017 at 13:31" list(datefinder.find_dates(string.lower())) #[datetime.datetime(2017, 5, 17, 13, 31)]
Narahari BM

погодьтеся, що датчик є набагато кращим, ніж партер дати для неоднозначного тексту
Джей Юнг,

2

За допомогою Pygrok ви можете визначити абстраговані розширення синтаксису регулярного виразу.

Спеціальні шаблони можуть бути включені у ваш регулярний вираз у форматі %{PATTERN_NAME}.

Крім того, можна створити ярлик для цієї моделі, розділяючи двокрапка: %s{PATTERN_NAME:matched_string}. Якщо шаблон збігається, значення буде повернуто як частина отриманого словника (наприклад,result.get('matched_string') )

Наприклад:

from pygrok import Grok

input_string = 'monkey 2010-07-10 love banana'
date_pattern = '%{YEAR:year}-%{MONTHNUM:month}-%{MONTHDAY:day}'

grok = Grok(date_pattern)
print(grok.match(input_string))

Отримане значення буде словником:

{'month': '07', 'day': '10', 'year': '2010'}

Якщо вікно date_pattern не існує у рядку input_string, повертається значення None. На відміну від цього, якщо ваш шаблон не має міток, він поверне порожній словник{}

Список літератури:


Ця бібліотека, тобто дуже Python 2
Walter

1

Ви також можете спробувати модуль dateparser , який може бути повільнішим за datefinder у вільному тексті, але повинен охоплювати більше потенційних випадків та форматів дат, а також значну кількість мов.


-5

Якщо ви знаєте позицію об’єкта дати у рядку (наприклад, у файлі журналу), ви можете використовувати .split () [index] для вилучення дати, не знаючи повністю формату.

Наприклад:

>>> string = 'monkey 2010-07-10 love banana'
>>> date = string.split()[1]
>>> date
'2010-07-10'
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.