Extraer parte de una coincidencia de expresiones regulares

130

Quiero una expresión regular para extraer el título de una página HTML. Actualmente tengo esto:

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

¿Existe una expresión regular para extraer solo el contenido de <título> para que no tenga que eliminar las etiquetas?

hoju
fuente
55
wow, no puedo creer todas las respuestas que llaman a analizar toda la página HTML solo para extraer un título simple. ¡Qué exageración!
hoju
44
Título de la pregunta lo dice todo - el ejemplo dado pasa a ser HTML, pero el problema general es ... en general.
Phil

Respuestas:

207

Úselo ( )en regexp y group(1)en python para recuperar la cadena capturada ( re.searchse devolverá Nonesi no encuentra el resultado, así que no la use group()directamente ):

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

if title_search:
    title = title_search.group(1)
Krzysztof Krasoń
fuente
1
Si no está haciendo nada cuando no se encuentra ningún título, ¿por qué sería malo usar group () directamente? (De todos modos, puedes ver la excepción)
tonfa
1
sí, pero la mayoría de gente se olvida de excepciones, y están realmente sorprendidos cuando los ven en tiempo de ejecución :)
Krzysztof Krason
No te olvides de correr import reo de lo contrario obtendrásNameError: name 're' is not defined
Powers
16

Tenga en cuenta que al comenzar Python 3.8, y la introducción de expresiones de asignación (PEP 572) ( :=operador), es posible mejorar un poco la solución de Krzysztof Krasoń capturando el resultado del partido directamente dentro de la condición if como una variable y reutilizándolo en el cuerpo de la condición :

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

Intente usar grupos de captura:

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

¿Puedo recomendar a Beautiful Soup? La sopa es una muy buena lib para analizar todo su documento html.

soup = BeatifulSoup(html_doc)
titleName = soup.title.name
Kharagpur
fuente
Me gustaría agregar que beautifulsoup también analiza html incompleto, y eso es realmente bueno.
hasta el
3

Tratar:

title = re.search('<title>(.*)</title>', html, re.IGNORECASE).group(1)
Cachondo
fuente
Si realmente desea utilizar REGEX para el análisis HTML, no ejecute .group () directamente en la coincidencia, ya que puede devolver Ninguno.
iElectric
Debe usarlo .*?en caso de que haya varios </title>en el documento (poco probable pero nunca se sabe).
tonfa
@ iElectric: puedes probarlo, excepto bloquear si realmente quieres, ¿verdad?
tonfa
3

Las piezas de código proporcionadas no cumplen con lo que Exceptions puedo sugerir.

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

Esto devuelve una cadena vacía por defecto si no se ha encontrado el patrón o la primera coincidencia.

Steve K
fuente
1

Creo que esto debería ser suficiente:

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

... suponiendo que su texto (HTML) esté en una variable llamada "texto".

Esto también supone que no hay otras etiquetas HTML que se puedan incrustar legalmente dentro de una etiqueta de TÍTULO HTML y no hay forma de incrustar legalmente ningún otro carácter <dentro de dicho contenedor / bloque.

Sin embargo ...

No use expresiones regulares para el análisis HTML en Python. ¡Utiliza un analizador HTML! (A menos que vaya a escribir un analizador completo, lo que sería un trabajo adicional cuando varios analizadores HTML, SGML y XML ya están en las bibliotecas estándar.

Si maneja HTML de sopa de etiqueta del "mundo real" (que con frecuencia no se ajusta a ningún validador SGML / XML), utilice el paquete BeautifulSoup . No está en las bibliotecas estándar (todavía), pero se recomienda ampliamente para este propósito.

Otra opción es: lxml ... que está escrito para HTML correctamente estructurado (conforme a los estándares). Pero tiene una opción para recurrir al uso de BeautifulSoup como analizador: ElementSoup .

Jim Dennis
fuente