Извлечь часть совпадения с регулярным выражением


131

Я хочу, чтобы регулярное выражение извлекало заголовок из HTML-страницы. В настоящее время у меня есть это:

title = re.search('<title>.*</title>', html, re.IGNORECASE).group()
if title:
    title = title.replace('<title>', '').replace('</title>', '') 

Есть ли регулярное выражение для извлечения только содержимого <title>, чтобы мне не нужно было удалять теги?


5
вау, я не могу поверить всем ответам, призывающим проанализировать всю HTML-страницу только для того, чтобы извлечь простой заголовок. Какой перебор!
hoju

4
Название Вопрос говорит , что все это - пример , приведенный случается быть HTML, но общая проблема ... вообще.
Фил

Ответы:


209

Используйте ( )в regexp и group(1)в python для получения захваченной строки ( re.searchвернется, Noneесли не найдет результат, поэтому не используйте group()напрямую ):

title_search = re.search('<title>(.*)</title>', html, re.IGNORECASE)

if title_search:
    title = title_search.group(1)

1
Если вы ничего не делаете, когда заголовок не найден, почему было бы плохо использовать group () напрямую? (вы все равно можете поймать исключение)
tonfa

1
да, но большинство людей забывают об исключениях и очень удивляются, когда видят их во время выполнения :)
Krzysztof Krasoń

Не забывай бежать, import reиначе получишьNameError: name 're' is not defined
Пауэрс

16

Обратите внимание, что, начиная Python 3.8с введения выражений присваивания (PEP 572) ( :=оператор), можно немного улучшить решение Кшиштофа Красоня, зафиксировав результат сопоставления непосредственно в условии if в качестве переменной и повторно используя его в теле условия. :

# pattern = '<title>(.*)</title>'
# text = '<title>hello</title>'
if match := re.search(pattern, text, re.IGNORECASE):
  title = match.group(1)
# hello



4

Могу я порекомендовать вам Beautiful Soup. Soup - очень хорошая библиотека для анализа всего вашего html-документа.

soup = BeatifulSoup(html_doc)
titleName = soup.title.name

Хочу добавить, что beautifulsoup также разбирает неполный html, и это действительно приятно.
конец

3

Пытаться:

title = re.search('<title>(.*)</title>', html, re.IGNORECASE).group(1)

Если вы действительно хотите использовать REGEX для разбора HTML, не запускайте .group () непосредственно при совпадении, поскольку он может вернуть None.
iElectric,

Вы должны использовать .*?это, если </title>в документе их несколько (маловероятно, но вы никогда не знаете).
tonfa

@iElectric: вы могли бы попробовать, кроме блока, если действительно хотите, верно?
tonfa

3

Предоставленные фрагменты кода не подходят Exceptions . Могу я предложить

getattr(re.search(r"<title>(.*)</title>", s, re.IGNORECASE), 'groups', lambda:[u""])()[0]

По умолчанию это возвращает пустую строку, если шаблон не был найден, или первое совпадение.


1

Думаю, этого должно хватить:

#!python
import re
pattern = re.compile(r'<title>([^<]*)</title>', re.MULTILINE|re.IGNORECASE)
pattern.search(text)

... предполагая, что ваш текст (HTML) находится в переменной с именем "text".

Это также предполагает, что нет других тегов HTML, которые могут быть легально встроены в тег HTML TITLE, и нет способа легально встроить любой другой символ <в такой контейнер / блок.

Однако ...

Не используйте регулярные выражения для синтаксического анализа HTML в Python. Используйте парсер HTML! (Если вы не собираетесь писать полноценный синтаксический анализатор, что потребует дополнительной работы, когда различные синтаксические анализаторы HTML, SGML и XML уже находятся в стандартных библиотеках.

Если вы обрабатываете «реальный» тег HTML (который часто не соответствует никаким валидаторам SGML / XML), используйте пакет BeautifulSoup . Его нет в стандартных библиотеках (пока), но для этой цели рекомендуется.

Другой вариант: lxml ..., который написан для правильно структурированного (соответствующего стандартам) HTML. Но у него есть возможность вернуться к использованию BeautifulSoup в качестве парсера: ElementSoup .

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.