Extrahieren Sie einen Teil eines Regex-Matches


130

Ich möchte, dass ein regulärer Ausdruck den Titel aus einer HTML-Seite extrahiert. Derzeit habe ich Folgendes:

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

Gibt es einen regulären Ausdruck, um nur den Inhalt von <title> zu extrahieren, damit ich die Tags nicht entfernen muss?


5
Wow, ich kann nicht glauben, dass alle Antworten dazu aufgerufen werden, die gesamte HTML-Seite zu analysieren, nur um einen einfachen Titel zu extrahieren. Was für ein Overkill!
Hoju

4
Frage Titel sagt alles - das gegebene Beispiel geschieht HTML sein, aber das allgemeine Problem ist ... Allgemeinen.
Phil

Antworten:


207

Verwenden Sie ( )in regexp und group(1)in Python, um die erfasste Zeichenfolge abzurufen ( re.searchwird zurückgegeben, Nonewenn das Ergebnis nicht gefunden wird, verwenden Sie sie also nicht group()direkt ):

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

if title_search:
    title = title_search.group(1)

1
Wenn Sie nichts tun, wenn kein Titel gefunden wird, warum ist es dann schlecht, group () direkt zu verwenden? (Sie können die Ausnahme trotzdem fangen)
Tonfa

1
Ja, aber die meisten Leute vergessen Ausnahmen und sind wirklich überrascht, wenn sie sie zur Laufzeit sehen :)
Krzysztof Krasoń

Vergiss nicht zu rennen, import resonst bekommst duNameError: name 're' is not defined
Powers

16

Beachten Sie, dass durch das Starten Python 3.8und die Einführung von Zuweisungsausdrücken (PEP 572) ( :=Operator) die Lösung von Krzysztof Krasoń ein wenig verbessert werden kann, indem das Übereinstimmungsergebnis direkt in der if-Bedingung als Variable erfasst und im Hauptteil der Bedingung wiederverwendet wird ::

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

6

Versuchen Sie es mit Erfassungsgruppen:

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


4

Darf ich Sie zu Beautiful Soup empfehlen. Suppe ist eine sehr gute Bibliothek, um Ihr gesamtes HTML-Dokument zu analysieren.

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

Ich möchte hinzufügen, dass beautifulsoup auch unvollständiges HTML analysiert, und das ist wirklich schön.
Ende

3

Versuchen:

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

Wenn Sie REGEX wirklich für die HTML-Analyse verwenden möchten, führen Sie .group () nicht direkt bei Übereinstimmung aus, da möglicherweise None zurückgegeben wird.
iElectric

Sie sollten dies verwenden .*?, falls </title>das Dokument mehrere enthält (unwahrscheinlich, aber Sie wissen es nie).
Tonfa

@iElectric: Sie könnten es versuchen, außer Block, wenn Sie wirklich wollen, oder?
Tonfa

3

Die bereitgestellten Codeteile entsprechen nicht Exceptions den von mir vorgeschlagenen

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

Dies gibt standardmäßig eine leere Zeichenfolge zurück, wenn das Muster nicht gefunden wurde oder die erste Übereinstimmung vorliegt.


1

Ich würde denken, das sollte ausreichen:

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

... vorausgesetzt, Ihr Text (HTML) befindet sich in einer Variablen namens "Text".

Dies setzt auch voraus, dass es keine anderen HTML-Tags gibt, die legal in ein HTML-TITLE-Tag eingebettet werden können, und dass kein anderes <-Zeichen legal in einen solchen Container / Block eingebettet werden kann.

Jedoch ...

Verwenden Sie keine regulären Ausdrücke für die HTML-Analyse in Python. Verwenden Sie einen HTML-Parser! (Es sei denn, Sie schreiben einen vollständigen Parser. Dies wäre eine zusätzliche Arbeit, wenn verschiedene HTML-, SGML- und XML-Parser bereits in den Standardbibliotheken enthalten sind.

Verwenden Sie das BeautifulSoup- Paket, wenn Sie mit "real world" -Tagsuppen- HTML umgehen (das häufig nicht mit einem SGML / XML-Validator übereinstimmt) . Es ist (noch) nicht in den Standardbibliotheken enthalten, wird jedoch zu diesem Zweck allgemein empfohlen.

Eine weitere Option ist: lxml ..., das für ordnungsgemäß strukturiertes (standardkonformes) HTML geschrieben wurde. Es besteht jedoch die Möglichkeit, auf die Verwendung von BeautifulSoup als Parser zurückzugreifen: ElementSoup .

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.