web-dev-qa-db-fra.com

Le meilleur moyen d’identifier et d’extraire les dates du texte Python?

Dans le cadre d'un projet personnel plus vaste sur lequel je travaille, je tente de séparer les dates en ligne de diverses sources de texte.

Par exemple, j'ai une longue liste de chaînes (qui se présentent généralement sous la forme de phrases ou d'instructions en anglais) qui prennent diverses formes:

Session du comité de conception central mardi 10/22 à 18h30

Th 9/19 LAB: Encodage en série (Section 2.2)

Il y en aura un autre le 15 décembre pour ceux qui sont incapables de le faire aujourd'hui.

Cahier 3 (salaire minimum): dû le mercredi 9/18 23h59

Il volera le 15 septembre.

Bien que ces dates soient alignées sur le texte naturel, aucune d’entre elles n’est en langage spécifique (par exemple, il n’existe pas de "La réunion aura lieu dans deux semaines à compter de demain" - tout est explicite). 

En tant que personne n'ayant pas beaucoup d'expérience avec ce type de traitement, quel serait le meilleur endroit pour commencer? J'ai examiné des éléments tels que le module dateutil.parser et parsedatetime , mais ceux-ci semblent être pour après que vous avez isolé la date.

Pour cette raison, existe-t-il un bon moyen d'extraire la date et le texte étranger? 

input:  Th 9/19 LAB: Serial encoding (Section 2.2)
output: ['Th 9/19', 'LAB: Serial encoding (Section 2.2)']

ou quelque chose de similaire? Il semble que ce type de traitement soit effectué par des applications telles que Gmail et Apple Mail, mais est-il possible de l'implémenter en Python?

25
redct

Je cherchais également une solution à ce problème et je n’en trouvais pas, alors un ami et moi avons créé un outil pour le faire. Je pensais que je reviendrais et partagerais au cas où d'autres trouveraient cela utile.

datefinder - recherche et extrait les dates dans le texte

20
akoumjian

Si vous pouvez identifier les segments contenant réellement les informations de date, leur analyse peut être relativement simple avec parsedatetime . Il y a quelques points à considérer, à savoir que vos dates n'ont pas d'années et que vous devriez choisir un lieu.

>>> import parsedatetime
>>> p = parsedatetime.Calendar()
>>> p.parse("December 15th")
((2013, 12, 15, 0, 13, 30, 4, 319, 0), 1)
>>> p.parse("9/18 11:59 pm")
((2014, 9, 18, 23, 59, 0, 4, 319, 0), 3)
>>> # It chooses 2014 since that's the *next* occurence of 9/18

Cela ne fonctionne pas toujours parfaitement lorsque vous avez du texte étranger.

>>> p.parse("9/19 LAB: Serial encoding")
((2014, 9, 19, 0, 15, 30, 4, 319, 0), 1)
>>> p.parse("9/19 LAB: Serial encoding (Section 2.2)")
((2014, 2, 2, 0, 15, 32, 4, 319, 0), 1)

Honnêtement, cela semble être le genre de problème qui serait assez simple pour analyser des formats particuliers et choisir le plus probable de chaque phrase. Au-delà, ce serait un problème d’apprentissage automatique décent.

7
Kyle Kelley

Je suis surpris qu'il n'y ait aucune mention de la méthode SUTime _ et search_dates

from sutime import SUTime
import os
import json
from dateparser.search import search_dates

str1 = "Let's meet sometime next Thursday" 

# You'll get more information about these jar files from SUTime's github page
jar_files = os.path.join(os.path.dirname(__file__), 'jars')
sutime = SUTime(jars=jar_files, mark_time_ranges=True)

print(json.dumps(sutime.parse(str1), sort_keys=True, indent=4))
"""output: 
[
    {
        "end": 33,
        "start": 20,
        "text": "next Thursday",
        "type": "DATE",
        "value": "2018-10-11"
    }
]
"""

print(search_dates(str1))
#output:
#[('Thursday', datetime.datetime(2018, 9, 27, 0, 0))]

Bien que j'ai essayé d'autres modules tels que dateutil, datefinder et natty (je ne pouvais pas utiliser le caneton pour fonctionner avec python), ces deux-là semblent donner les résultats les plus prometteurs. 

Les résultats de SUTime sont plus fiables et cela ressort clairement de l'extrait de code ci-dessus. Cependant, SUTime échoue dans certains scénarios de base tels que l'analyse d'un texte 

"Je ne serai pas disponible avant le 19/09"

ou 

"Je ne serai pas disponible entre le 18 septembre et le 20 septembre.

Il ne donne aucun résultat pour le premier texte et ne donne que le mois et l'année pour le deuxième texte. Ceci est cependant assez bien géré dans la méthode search_dates. La méthode search_dates est plus agressive et donnera toutes les dates possibles liées aux mots du texte saisi. 

Je n'ai pas encore trouvé le moyen d'analyser le texte strictement pour les dates dans search_methods. Si je pouvais trouver un moyen de le faire, ce serait mon premier choix sur SUTime et je veillerais également à mettre à jour cette réponse si je la trouve. 

Bonjour, je ne suis pas sûr que l'approche ci-dessous soit un apprentissage automatique, mais vous pouvez l'essayer:

  • ajouter un contexte à partir d'un texte extérieur, par exemple l'heure de publication d'un message texte, la publication, maintenant, etc. (votre texte ne dit rien de l'année) 
  • extraire tous les jetons avec un espace-blanc séparateur et devrait obtenir quelque chose comme ceci:

    ['Th','Wednesday','9:34pm','7:34','pm','am','9/18','9/','/18', '19','12']
    
  • traitez-les avec des ensembles de règles, par exemple en subsistant des jours de la semaine et/ou des variations du temps de formation des composants, et marquez-les, par ex. '% d:% dpm', '% d am', '% d /% d', '% d /% d' etc. peut signifier temps. Notez qu'il peut avoir des compositions, par ex. "12/31" est un 3grammes ("12", "/", "31") devrait être un gage "12/31" d'intérêt.

  • "voir" quels sont les jetons marqués comme "21h45", par exemple ('Th ",' 9/19 ',' 21h45 ') est un 3gram formé à partir de jetons" intéressants "et applique des règles le déterminant . 

  • processus pour une analyse plus spécifique, par exemple, si 31/12, 31> 12 signifie d/m, ou vice versa, mais si 12/12 m, d sera disponible uniquement dans un contexte construit à partir de texte et/ou extérieur.

À votre santé

1
hardcode

Vous pouvez utiliser la méthode parse du module dateutil avec l'option fuzzy.

>>> from dateutil.parser import parse
>>> parse("Central design committee session Tuesday 10/22 6:30 pm", fuzzy=True)
datetime.datetime(2018, 10, 22, 18, 30)
>>> parse("There will be another one on December 15th for those who are unable to make it today.", fuzzy=True)
datetime.datetime(2018, 12, 15, 0, 0)
>>> parse("Workbook 3 (Minimum Wage): due Wednesday 9/18 11:59pm", fuzzy=True)
datetime.datetime(2018, 3, 9, 23, 59)
>>> parse("He will be flying in Sept. 15th.", fuzzy=True)
datetime.datetime(2018, 9, 15, 0, 0)
>>> parse("Th 9/19 LAB: Serial encoding (Section 2.2)", fuzzy=True)
datetime.datetime(2002, 9, 19, 0, 0)
1
Samkit Jain
import datefinder
string_with_dates = """
                    entries are due by January 4th, 2017 at 8:00pm
                    created 01/15/2005 by ACME Inc. and associates.
                    """
matches = datefinder.find_dates(string_with_dates)
for match in matches:
    print match
1
Prabin S