Витягніть частину збігу з регулярними виразками


130

Я хочу, щоб регулярний вираз витягував заголовок зі сторінки HTML. На даний момент у мене це:

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

Чи є регулярний вираз для вилучення лише вмісту <title>, тому мені не доведеться видаляти теги?


5
Уау, я не можу повірити, що всі відповіді, які закликають розібрати всю сторінку HTML, просто витягнути простий заголовок. Що за надмірність!
ходжу

4
Заголовок запитання говорить про все - наведений приклад буває HTML, але загальна проблема ... загальна.
Філ

Відповіді:


208

Використовуйте ( )в 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
Якщо ви нічого не робите, коли не знайдено заголовка, чому б було погано використовувати групу () безпосередньо? (ви можете зловити виняток у будь-якому випадку)
tonfa

1
так, але більшість людей забувають про винятки, і дуже дивуються, коли бачать їх під час виконання :)
Кшиштоф Красонь,

Не забувайте бігати, 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

Я можу порекомендувати вам Красивий суп. Суп - це дуже хороша версія для аналізу всіх ваших html-документів.

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

Я хотів би додати, що beautifulsoup також розбирає неповний html, і це дійсно добре.
endre

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) міститься в змінній, що називається "текст".

Це також передбачає, що немає інших тегів 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.