Реальные кейсы: парсинг логов и очистка текста
Собираем изученное в законченные практические задачи.
Сильная сторона регулярок — превращать неструктурированный текст (логи, выгрузки, разметку) в данные за пару строк.
Парсинг строки лога
Строка веб-сервера содержит IP, метод, путь и код ответа. Разберём её на части именованными группами:
import re
line = '127.0.0.1 - - [14/Jun/2024] "GET /index.html" 200'
pattern = r'(?P<ip>\d+\.\d+\.\d+\.\d+).*"(?P<method>\w+) (?P<path>\S+)" (?P<code>\d+)'
m = re.search(pattern, line)
print(m.group("ip"))
print(m.group("method"))
print(m.group("path"))
print(m.group("code"))
Вывод:
127.0.0.1 GET /index.html 200
Разберём паттерн: \d+\.\d+\.\d+\.\d+ — четыре группы цифр через экранированные точки (IP), .* пропускает середину, затем в кавычках метод (\w+) и путь (\S+), и в конце код ответа. Имена групп делают результат самодокументируемым.
Удаление HTML-тегов
Чтобы выдрать чистый текст из простой разметки, убирают всё в угловых скобках. Ключ — класс [^>]+ вместо жадной .*, чтобы не съесть лишнее:
import re
html = "<p>Привет, <b>мир</b>!</p>"
print(re.sub(r"<[^>]+>", "", html))
Вывод:
Привет, мир!
Паттерн <[^>]+> читается как «открывающая скобка, любые символы кроме закрывающей, закрывающая скобка» — то есть один тег целиком. Класс [^>] не даёт совпадению перескочить через границу тега. (Для настоящего HTML это всё же грубо — об этом в следующем уроке.)
Нормализация текста
Часто текст приходит «грязным»: лишние пробелы, табы, переносы. Приведём его к одной строке с одиночными пробелами:
import re
dirty = " Слишком много \t пробелов\n и переносов "
clean = re.sub(r"\s+", " ", dirty).strip()
print(repr(clean))
Вывод:
'Слишком много пробелов и переносов'
Связка re.sub(r"\s+", " ", text).strip() — рабочая лошадка очистки текста, которую вы будете использовать постоянно.
Извлечение всех чисел с дробями
Ещё типовая задача — собрать все числа, включая дробные, из текста:
import re
text = "Куплено 3 шт по 199.90, доставка 0 руб, итого 599.70"
print(re.findall(r"\d+\.\d+|\d+", text))
Вывод:
['3', '199.90', '0', '599.70']
Альтернация \d+\.\d+|\d+ сначала пробует дробное число, и только если не вышло — целое. Порядок важен: дробный вариант стоит первым, чтобы 199.90 не распалось на 199 и 90.
Итог
- Именованные группы превращают строку лога в понятные поля.
- Для тегов и кавычек используйте «отрицающий» класс (
[^>],[^"]) вместо жадной.*. re.sub(r"\s+", " ", text).strip()— стандартная очистка текста.- В альтернации с числами более длинный вариант (дробное) ставьте первым.