На прошлом занятии

  • Регулярные выражения и их синтаксис
  • Модуль стандартной библиотеки re и функции re.search

План этого занятия

  • Сырые строки r''
  • Метод group()
  • Запоминающие группы
  • Ограничение жадности квантификаторов

Если в регулярном выражениии используются специальные значения с \, то лучше использовать синтаксис для «сырых» (raw) строк. Приведем простой пример использования «сырых» строк: предположим, что нужно написать строку, которая бы содержала два подряд идущих символа: \ и n. Мы уже знаем, что если просто написать '\n', то Python превратит это сочетание в символ переноса строки. Однако, если написать r'\n', то Python не будет производить никаких преобразований внутри этой строки.

Проверим, есть ли числа в строке:

if re.search(r'\d', 'Я родился 30 февраля 1930 года'):
    print(True)

Часто нам не просто нужно узнать, находится ли что-то нас интересующее в строке, но и узнать, что именно нашлось. Но функция re.search возвращает не совсем то, чего бы нам хотелось:

>>> s = 'abc'
>>> r = re.search('a', s)
>>> r
<_sre.SRE_Match object; span=(0, 1), match='a'>

Это такой объект, а нам хотелось бы саму найденную строку.

Чтобы получить найденную строку, существует метод group():

first_match = re.search('кот.', 'Кот пришёл к коту и спросил кота: «Бойкот, котелок или скотч?»')
if first_match:
    first_match.group()    # 'кот '
else:
    print('Nothing found.')

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

>>> s = 'корова молоко'
>>> r = re.search('(.+?оро.+?) (.+?оло.+)', s)
>>> r
<_sre.SRE_Match object; span=(0, 12), match='корова молоко'>
>>> r.group(1)
'корова'
>>> r.group(2)
'молоко'

Ограничение жадности

Если мы хотим выделить в шаблоне только часть строки и сделать её запоминающей группой, то у нас возможны случаи двойного толкования шаблона, как в примере выше:

>>> s = 'корова молоко'
>>> r = re.search('(.+?оро.+?) (.+?оло.+)', s)

В строке 'корова молоко' мы хотим выделить всё слово, содержащее оро до пробела после него. Поэтому в шаблоне мы пишем после слова “ограничитель” в виде пробела, подразумевая, что парсер регулярных выражений “дойдёт” до этого пробела и остановится. Но . означает любой символ, в том числе и пробел. Как будет трактоваться такое выражение? Будет ли пробел “захватываться” группой?

По умолчанию квантификаторы (прежде всего, + и *) жадные (greedy). Это значит, что они стремятся “съесть” как можно больше символов, подходящих под шаблон. Если мы ожидаем, что в строке 'Онегин, добрый мой приятель' такой шаблон '^.+ ' (справа от квантификатора ограничитель в виде пробела) захватит только первое слово “Онегин”, то мы ошибаемся:

>>> s = 'Онегин, добрый мой приятель'
>>> r = re.search('^.+ ', s)
>>> print(r.group())
Онегин, добрый мой

Ограничитель действует, но только это не первый, а последний пробел в строке, после “мой” перед “приятель”, а не после “Онегина”, как мы хотели.

Чтобы этот шаблон работал как нужно, необходимо ограничить жадность квантификатора. Это делается с подстановкой после него символа ?. Таким образом, чтобы квантификатор был нежадным, его следует записать так: .+?. Проверим:

>>> s = 'Онегин, добрый мой приятель'
>>> r = re.search('^.+? ', s)
>>> print(r.group())
Онегин,

Домашнее задание

В некоторых статьях Википедии на какую-то определённую тему есть стандартные шаблоны-карточки, в которых в кратком виде изложена основная информация. Например, для людей это дата рождения и смерти, для стран — столица, население и т. п.

Поскольку карточки устроены стандартным образом, с таких страниц можно автоматически собирать информацию. Этим и должна заниматься Ваша программа из очередного дз. Она должна открывать заранее сохранённый html-файл со статьёй из русской википедии на определённую тему с определённой карточкой (в зависимости от варианта) и доставать оттуда кое-какую информацию (тоже в зависимости от варианта). Извлеченную информацию она должна записать в текстовый файл.

Вот типы карточек и нужная информация:

  1. статьи о странах (напр., Россия) — столица;
  2. статьи о городах (напр., Санкт-Петербург) — часовой пояс;
  3. статьи о вузах (напр., Высшая школа экономики) — год основания;
  4. статьи об учёных (напр., Эйнштейн, Альберт) — научная сфера;
  5. статьи о растениях (напр., томат) — семейство;
  6. статьи о животных (напр., хомяки) — отряд;
  7. статьи о языках (напр., арчинский язык) — трёхбуквенный код (ISO 639-3).

Решить задание следует с помощью применения регулярных выражений.

Выполните задание пройдя по ссылке в GitHub Classroom:


Улучшить эту страницу