Extrahieren des Datums aus einer Zeichenfolge in Python

79

Wie kann ich das Datum aus einer Zeichenfolge wie "Affe 2010-07-10 Liebesbanane" extrahieren? Vielen Dank!

dmpop
quelle
3
Nur ein Hinweis: Es beginnt und endet mit einer Ziffer. Lass mich darüber nachdenken. Obwohl Regex dort dein Freund sein kann.
Hamish Grubijan

Antworten:

79

Wenn das Datum in einer festen Form angegeben ist, können Sie einfach einen regulären Ausdruck verwenden, um das Datum zu extrahieren, und "datetime.datetime.strptime", um das Datum zu analysieren:

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()

Andernfalls können Sie das Datum nicht einfach extrahieren, wenn es in einer beliebigen Form angegeben wird.

Mondhorn
quelle
1
Was ist, wenn es im europäischen Format vorliegt, z. B. 20/01/1980, was "20. Januar 1980" bedeutet? Was ist, wenn Monate / Tage / Jahre außerhalb des angemessenen Bereichs liegen?
Hamish Grubijan
@lunaryorn Bezieht sich "re" in der ersten Anweisung auf die Zeichenfolge, in der wir nach unserem gewünschten Muster suchen?
Vishal
@ vishal.k Es bezieht sich auf das eingebaute reModul, dh , import re.
Mondhorn
Für den Fall, dass jemand anderes den gleichen Fehler gemacht hat: Sie müssen from datetime import datetimestattimport datetime
dankal444
152

Verwenden von 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)

Ungültige Daten führen zu einem ValueError:

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

Es kann Daten in vielen Formaten erkennen:

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

Beachten Sie, dass es eine Vermutung gibt, wenn das Datum nicht eindeutig ist:

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

Die Art und Weise, wie mehrdeutige Daten analysiert werden, ist jedoch anpassbar:

In [21]: dparser.parse("monkey 10/01/1980 love banana",fuzzy=True, dayfirst=True)
Out[21]: datetime.datetime(1980, 1, 10, 0, 0)
unutbu
quelle
3
@Hamish: Wenn es zwei Datumsangaben gibt (wie im Fall von "monkey 10/01/1980 love 7/10/2010 banana"), wird möglicherweise ein ValueError ausgelöst, oder (wie im Fall von "monkey 10/01/1980 love 2010-07-10 banana") wird das zweite Datum möglicherweise falsch interpretiert, indem Stunden, Minuten, Sekunden oder Zeitzonen angegeben werden. fuzzy=Truegibt es Lizenz zu raten.
Unutbu
1
@unutbu str = "Von flufie · 14. Oktober 2010 um 23:22 Uhr · 26 Antworten" Durch die Verwendung von dateutil erhalte ich "ValueError: Stunde muss in 0..23 sein"
saravanan
Was passiert, wenn der Text mehr als ein Datum enthält?
Alvas
1
@alvas: Die parseFunktion kann eine Ausnahme auslösen (auch wenn fuzzy=True) oder mit fuzzy=True, dass sie das erste Datum oder einen Mischmasch zurückgibt, der aus Teilen beider Daten besteht. Also wirklich, parsesollte nur für eine Zeichenfolge aufgerufen werden, die ein Datum enthält.
Unutbu
1
@Kailegh: Ja, es wäre möglich, die Indizes mit fuzzy_with_tokens = True abzuleiten . Wenn Sie mehr Klarheit wünschen, beginnen Sie bitte eine neue Frage.
Unutbu
26

Zum Extrahieren des Datums aus einer Zeichenfolge in Python; Das beste verfügbare Modul ist das Datefinder- Modul.

Sie können es in Ihrem Python-Projekt verwenden, indem Sie die folgenden einfachen Schritte ausführen.

Schritt 1: Installieren Sie das Datefinder-Paket

pip install datefinder

Schritt 2: Verwenden Sie es in Ihrem Projekt

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'

Hinweis: Wenn Sie eine große Anzahl von Übereinstimmungen erwarten; Dann wird die Typumwandlung in eine Liste nicht empfohlen, da dies einen hohen Leistungsaufwand bedeutet.

Finny Abraham
quelle
1
Ich fand, dass datefinderdie mehrdeutige python-dateutilDatumsübereinstimmung besser war, als nur zwei mögliche Daten aus einem zufälligen Medium.com-Blog-Beitrag zurückzugeben, anstatt fünf. Ich
bin
Dies ist ziemlich gut, außer dass es irgendwie nicht funktioniert, wenn es einen Doppelpunkt (:) vor Datumszeichenfolge gibt: 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
Ich bin damit einverstanden, dass der Datumsfinder für mehrdeutigen Text viel besser ist als der Dateparser
Jay Jung,
2

Mit Pygrok können Sie abstrahierte Erweiterungen der Syntax für reguläre Ausdrücke definieren.

Die benutzerdefinierten Muster können im Format in Ihre Regex aufgenommen werden %{PATTERN_NAME}.

Sie können auch eine Beschriftung für dieses Muster erstellen, indem Sie durch einen Doppelpunkt trennen : %s{PATTERN_NAME:matched_string}. Wenn das Muster übereinstimmt, wird der Wert als Teil des resultierenden Wörterbuch zurückgeführt wird (zB result.get('matched_string'))

Zum Beispiel:

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))

Der resultierende Wert ist ein Wörterbuch:

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

Wenn das Datumsmuster nicht in der Eingabezeichenfolge vorhanden ist, lautet der Rückgabewert None. Wenn Ihr Muster hingegen keine Beschriftungen enthält, wird ein leeres Wörterbuch zurückgegeben{}

Verweise:

Aubrey Lavigne
quelle
1

Sie können auch das Dateparser- Modul ausprobieren , das bei freiem Text möglicherweise langsamer als der Datefinder ist, jedoch mehr potenzielle Fälle und Datumsformate sowie eine erhebliche Anzahl von Sprachen abdecken sollte.

Adbar
quelle
-5

Wenn Sie die Position des Datumsobjekts in der Zeichenfolge kennen (z. B. in einer Protokolldatei), können Sie das Datum mit .split () [index] extrahieren, ohne das Format vollständig zu kennen.

Zum Beispiel:

>>> string = 'monkey 2010-07-10 love banana'
>>> date = string.split()[1]
>>> date
'2010-07-10'
dsod
quelle