Как извлечь несколько раз из одной строки в Python? - PullRequest
0 голосов
/ 06 января 2020

Я пытаюсь извлечь время из отдельных строк, где в одной строке будут тексты, отличные от только времени. Например, s = 'Dates : 12/Jul/2019 12/Aug/2019, Loc : MEISHAN BRIDGE, Time : 06:00 17:58'.

Я пытался использовать модуль datefinder, например:

from datetime import datetime as dt
import datefinder as dfn
for m in dfn.find_dates(s):
    print(dt.strftime(m, "%H:%M:%S"))

Что дает мне следующее:

17:58:00

В этом случае время "06:00" пропускается. Теперь, если я попытаюсь без datefinder только с модулем datetime, как это:

dt.strftime(s, "%H:%M")

Он уведомляет меня, что входные данные уже должны быть объектом datetime, а не строкой со следующей ошибкой:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: descriptor 'strftime' requires a 'datetime.date' object but received a 'str'

Поэтому я попытался использовать модуль dateutil для анализа этой строки s в объекте datetime с помощью:

from dateutil.parser import parse
parse(s)

но теперь он теперь говорит что моя строка не в правильном формате (который в большинстве случаев не будет в любом фиксированном формате), показывая мне эту ошибку:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/michael/anaconda3/envs/sec_img/lib/python3.7/site-packages/dateutil/parser/_parser.py", line 1358, in parse
    return DEFAULTPARSER.parse(timestr, **kwargs)
  File "/home/michael/anaconda3/envs/sec_img/lib/python3.7/site-packages/dateutil/parser/_parser.py", line 649, in parse
    raise ValueError("Unknown string format:", timestr)
ValueError: ('Unknown string format:', '12/Jul/2019 12/Aug/2019 MEISHAN BRIDGE 06:00 17:58')

Я думал о получении времени с регулярным выражением, как

import re
p = r"\d{2}\:\d{2}"
times = [i.group() for i in re.finditer(p, s)]
# Gives me ['06:00', '17:58']

Но для этого нужно, чтобы я снова проверил, соответствуют ли эти фрагменты регулярному выражению времени или нет, потому что даже "99:99" может быть правильно сопоставлено с регулярным выражением и неверно указано как время. Можно ли обойтись без регулярных выражений, чтобы получить все время из одной строки?

Обратите внимание, что строка может содержать или не содержать какую-либо дату, но она всегда будет содержать время. Даже если она содержит дату, формат даты может быть любым на земле, а также эта строка может содержать или не содержать другие не относящиеся к делу тексты.

Ответы [ 4 ]

0 голосов
/ 06 января 2020

вы можете использовать словари:

my_dict = {}

for i in s.split(', '):
    m = i.strip().split(' : ', 1)
    my_dict[m[0]] = m[1].split()


my_dict
Out: 
{'Dates': ['12/Jul/2019', '12/Aug/2019'],
 'Loc': ['MEISHAN', 'BRIDGE'],
 'Time': ['06:00', '17:58']}
0 голосов
/ 06 января 2020

Как извлечь несколько раз из одной и той же строки в Python?

Если вам нужно только время, это регулярное выражение должно работать нормально

r"[0-2][0-9]\:[0-5][0-9]"

Если есть возможность быть пробелами во времени как 23 : 59 используйте это

r"[0-2][0-9]\s*\:\s*[0-5][0-9]"
0 голосов
/ 06 января 2020

Я не вижу много вариантов здесь, поэтому я бы go с heuristi c. Я бы запустил следующее для всего набора данных и расширил бы config / regexes, пока он не охватил все / большинство случаев:

import re
import logging
from datetime import datetime as dt

s = 'Dates : 12/Jul/2019 12/08/2019, Loc : MEISHAN BRIDGE, Time : 06:00 17:58:59'


SUPPORTED_DATE_FMTS = {
    re.compile(r"(\d{2}/\w{3}/\d{4})"): "%d/%b/%Y",
    re.compile(r"(\d{2}/\d{2}/\d{4})"): "%d/%m/%Y",
    re.compile(r"(\d{2}/\w{3}\w+/\d{4})"): "%d/%B/%Y",
    # Capture more here
}

SUPPORTED_TIME_FMTS = {
    re.compile(r"((?:[0-1][0-9]|2[0-4]):[0-5][0-9])[^:]"): "%H:%M",
    re.compile(r"((?:[0-1][0-9]|2[0-4]):[0-5][0-9]:[0-5][0-9])"): "%H:%M:%S",
    # Capture more here
}


def extract_supported_dt(config, s):
    """
    Loop thru the given config (keys are regexes, values are date/time format)
    and attempt to gather all valid data.
    """
    valid_data = []
    for regex, fmt in config.items():
        # Extract what you think looks like date
        valid_ish_data = regex.findall(s)
        if not valid_ish_data:
            continue
        print("Checking " + str(valid_ish_data))

        # validate it
        for d in valid_ish_data:
            try:
                valid_data.append(dt.strptime(d, fmt))
            except ValueError:
                pass

    return valid_data


# Handle dates
dates = extract_supported_dt(SUPPORTED_DATE_FMTS, s)
# Handle times
times = extract_supported_dt(SUPPORTED_TIME_FMTS, s)

print("Found dates: ")
for date in dates:
    print("\t" + str(date.date()))

print("Found times: ")
for t in times:
    print("\t" + str(t.time()))

Пример вывода:

Checking ['12/Jul/2019']
Checking ['12/08/2019']
Checking ['06:00']
Checking ['17:58:59']
Found dates:
    2019-07-12
    2019-08-12
Found times:
    06:00:00
    17:58:59

Это пробная версия и ошибочный подход, но я не думаю, что есть альтернатива в вашем случае. Таким образом, моя цель здесь состоит в том, чтобы максимально облегчить расширение поддержки с помощью большего количества форматов даты / времени, а не пытаться найти решение, которое покрывает 100% данных в день-1. Таким образом, чем больше данных вы используете, тем полнее будет ваша конфигурация.

Следует отметить, что вам нужно будет обнаружить строки, которые, как кажется, не имеют дат, и записать их где-нибудь. Позже вам нужно будет вручную пересмотреть и посмотреть, можно ли что-то пропустить.

Теперь, предполагая, что ваши данные генерируются другой системой, рано или поздно вы сможете найти соответствие 100%. , Если ввод данных от человека, то вам, вероятно, никогда не удастся получить 100%! (люди, как правило, делают орфографические ошибки и иногда импортируют случайные вещи ... дата = сегодня :))

0 голосов
/ 06 января 2020

Используйте Regex, но как-то так,

(?=[0-1])[0-1][0-9]\:[0-5][0-9]|(?=2)[2][0-3]\:[0-5][0-9]

Это соответствует

00: 00, 00:59 01:00 01:59 02:00 02 : 59 09:00 10:00 11:59 20:00 21:59 23: 59

Не работает для

99: 99 23:99 01:99

Проверьте здесь, чувак, работает ли он для вас

Проверьте Repl.it

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...