私が取り組んでいる大規模な個人プロジェクトの一環として、インライン日付をさまざまなテキストソースから分離しようとしています。
たとえば、さまざまな形式の文字列(通常は英語の文または文の形式をとる)の大きなリストがあります。
中央設計委員会セッション火曜日10/22午後6時30分
Th 9/19 LAB:シリアルエンコーディング(セクション2.2)
12月15日に、今日参加できない人のために、別のイベントが開催されます。
ワークブック3(最低賃金):水曜日9/18午後11時59分
彼は9月15日に飛行します。
これらの日付は自然なテキストと一直線に並んでいますが、特に自然な言語形式のものはありません(たとえば、「明日から2週間は会議が予定されています」はありません。すべて明示的です)。
この種の処理の経験があまりない人として、始めるのに最適な場所は何でしょうか?私はdateutil.parser
モジュールと parsedatetime ですが、それらは日付を分離したafterのようです。
このため、日付と無関係なテキストを抽出する良い方法はありますか
input: Th 9/19 LAB: Serial encoding (Section 2.2)
output: ['Th 9/19', 'LAB: Serial encoding (Section 2.2)']
または何か似たような?この種の処理は、GmailやApple Mailなどのアプリケーションで行われているようですが、Pythonで実装することは可能ですか?
私はこれに対する解決策も探していましたが、見つけることができなかったので、友人とこれを行うためのツールを作成しました。私は戻ってきて、他の人が役に立つと思った場合に共有すると思いました。
実際に日付情報を含むセグメントを識別できる場合、それらの解析は parsedatetime でかなり簡単になります。ただし、考慮すべき点がいくつかあります。つまり、日付には年がなく、ロケールを選択する必要があるということです。
>>> 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
無関係なテキストがある場合、常に完全に機能するとは限りません。
>>> 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)
正直なところ、これは特定の形式を解析して各文から最も可能性の高いものを選択するのに十分簡単な種類の問題のようです。それを超えて、それはまともな機械学習の問題になります。
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
SUTime および dateparser's 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))]
Dateutil、datefinder、nattyのような他のモジュール(Pythonで動作するようにアヒルの子を取得できませんでした)を試しましたが、この2つは最も有望な結果を与えるようです。
SUTimeの結果はより信頼性が高く、上記のコードスニペットから明らかです。ただし、テキストの解析など、いくつかの基本的なシナリオではSUTimeが失敗します
「9/19まで利用できません」
または
「(9月18日から9月20日までの間は利用できません。).
最初のテキストでは結果が得られず、2番目のテキストでは月と年のみが得られます。ただし、これはsearch_datesメソッドで非常にうまく処理されます。 search_datesメソッドはより積極的であり、入力テキスト内の単語に関連するすべての可能な日付を提供します。
Search_methodsで日付のテキストを厳密に解析する方法をまだ見つけていません。それを行う方法を見つけることができれば、SUTimeに対する最初の選択肢になります。また、見つかった場合はこの回答を更新することも確認します。
こんにちは、私は以下のアプローチが機械学習であるかどうかはわかりませんが、あなたはそれを試すことができます:
区切り文字の空白ですべてのトークンを抽出すると、次のようになります。
['Th','Wednesday','9:34pm','7:34','pm','am','9/18','9/','/18', '19','12']
ルールセットを使用してそれらを処理します。たとえば、平日および/または時間を形成するコンポーネントのバリエーションから成り、それらをマークします。 「%d:%dpm」、「%d am」、「%d /%d」、「%d /%d」などは時間を意味する場合があります。それは組成を持っているかもしれないことに注意してください「12/31」は3グラム(「12」、「/」、「31」)が1つのトークン「12/31」になります。
「9:45 pm」のようなマークされたトークンの周囲にあるトークンを「参照」します。たとえば、(「Th」、「9/19」、「9:45 pm」)は「興味深い」トークンから形成される3グラムであり、意味を決定する可能性のあるルールを適用します。
たとえば、31/12がある場合、31> 12はd/m、またはその逆を意味しますが、12/12がある場合、dはテキストおよび/または外部からのコンテキストビルドでのみ使用できます。
乾杯
dateutil module のparse
メソッドと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)
parsedatetime
libの新しいバージョンは検索機能を提供します。
例
from dateparser.search import search_dates
dates = search_dates('Central design committee session Tuesday 10/22 6:30 pm')