Extraire une partie d'une correspondance regex

131

Je veux une expression régulière pour extraire le titre d'une page HTML. Actuellement, j'ai ceci:

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

Existe-t-il une expression régulière pour extraire uniquement le contenu de <title> pour ne pas avoir à supprimer les balises?

hoju
la source
5
wow je ne peux pas croire toutes les réponses appelant à analyser la page HTML entière juste pour extraire un titre simple. Quelle exagération!
hoju
4
Le titre de la question dit tout - l'exemple donné se trouve être du HTML, mais le problème général est ... général.
Phil

Réponses:

209

Utilisez ( )en regexp et group(1)en python pour récupérer la chaîne capturée ( re.searchretournera Nones'il ne trouve pas le résultat, donc ne l'utilisez pas group()directement ):

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

if title_search:
    title = title_search.group(1)
Krzysztof Krasoń
la source
1
Si vous ne faites rien quand aucun titre n'est trouvé, pourquoi serait-ce une mauvaise chose d'utiliser directement group ()? (vous pouvez quand même attraper l'exception)
tonfa
1
ouais, mais la plupart des gens oublient les exceptions et sont vraiment surpris de les voir à l'exécution :)
Krzysztof Krasoń
N'oubliez pas de courir import resinon vous obtiendrezNameError: name 're' is not defined
Pouvoirs
16

Notez que le démarrage Python 3.8et l'introduction d' expressions d'assignation (PEP 572) ( :=opérateur), il est possible d'améliorer un peu la solution de Krzysztof Krasoń en capturant le résultat de la correspondance directement dans la condition if en tant que variable et de le réutiliser dans le corps de la condition :

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

Essayez d'utiliser des groupes de capture:

title = re.search('<title>(.*)</title>', html, re.IGNORECASE).group(1)
Aaron Maenpaa
la source
5
re.search('<title>(.*)</title>', s, re.IGNORECASE).group(1)
Vinay Sajip
la source
4

Puis-je vous recommander de Beautiful Soup. Soup est une très bonne bibliothèque pour analyser tout votre document html.

soup = BeatifulSoup(html_doc)
titleName = soup.title.name
Kharagpur
la source
Je voudrais ajouter que beautifulsoup analyse également le HTML incomplet, et c'est vraiment bien.
Endre
3

Essayer:

title = re.search('<title>(.*)</title>', html, re.IGNORECASE).group(1)
Excité
la source
Si vous voulez vraiment utiliser REGEX pour l'analyse HTML, n'exécutez pas .group () directement sur match, car il peut renvoyer None.
iElectric
Vous devriez l'utiliser .*?au cas où il y en aurait plusieurs </title>dans le document (peu probable mais on ne sait jamais).
tonfa
@iElectric: vous pouvez le mettre dans un bloc try sauf si vous voulez vraiment, non?
tonfa
3

Les morceaux de code fournis ne sont pas compatibles avec Exceptions Je suggère

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

Cela renvoie une chaîne vide par défaut si le modèle n'a pas été trouvé, ou la première correspondance.

Steve K
la source
1

Je pense que cela devrait suffire:

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

... en supposant que votre texte (HTML) est dans une variable nommée "texte".

Cela suppose également qu'il n'y a pas d'autres balises HTML qui peuvent être légalement incorporées à l'intérieur d'une balise HTML TITLE et aucun moyen d'incorporer légalement un autre caractère <dans un tel conteneur / bloc.

Cependant ...

N'utilisez pas d'expressions régulières pour l'analyse HTML en Python. Utilisez un analyseur HTML! (À moins que vous n'écriviez un analyseur complet, ce qui serait un travail supplémentaire lorsque divers analyseurs HTML, SGML et XML sont déjà dans les bibliothèques standard.

Si votre manipulation de balises HTML "dans le monde réel" (qui est souvent non conforme à tout validateur SGML / XML), utilisez le package BeautifulSoup . Il n'est pas (encore) dans les bibliothèques standard mais est largement recommandé à cet effet.

Une autre option est: lxml ... qui est écrit pour du HTML correctement structuré (conforme aux normes). Mais il a une option pour revenir à l'utilisation de BeautifulSoup comme analyseur: ElementSoup .

Jim Dennis
la source