Extrair parte de uma correspondência de regex


130

Eu quero uma expressão regular para extrair o título de uma página HTML. Atualmente eu tenho isso:

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

Existe uma expressão regular para extrair apenas o conteúdo de <title>, para que eu não precise remover as tags?


5
uau Não acredito em todas as respostas que chamam para analisar a página HTML inteira apenas para extrair um título simples. Que exagero!
hoju 27/08/2009

4
Título da pergunta diz tudo - o exemplo dado acontece a ser HTML, mas o problema geral é ... geral.
Phil

Respostas:


207

Use ( )no regexp e group(1)no python para recuperar a string capturada ( re.searchretornará Nonese não encontrar o resultado, portanto , não use group()diretamente ):

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

if title_search:
    title = title_search.group(1)

1
Se você não está fazendo nada quando nenhum título é encontrado, por que seria ruim usar o group () diretamente? (você pode pegar o de qualquer maneira exceção)
tonfa

1
Sim, mas a maioria das pessoas esquecer-se sobre exceções, e estão realmente surpreso quando vê-los em tempo de execução :)
Krzysztof Krason

Não se esqueça de correr, import reou então você teráNameError: name 're' is not defined
Powers

16

Observe que o início Python 3.8e a introdução de expressões de atribuição (PEP 572) ( :=operador), é possível melhorar um pouco a solução de Krzysztof Krasoń capturando o resultado da partida diretamente dentro da condição if como uma variável e reutilizá-lo no corpo da condição :

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

6

Tente usar grupos de captura:

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


4

Posso recomendar-lhe a sopa bonita. Soup é uma lib muito boa para analisar todo o seu documento html.

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

Gostaria de acrescentar que beautifulsoup também analisa html incompleto, e isso é muito bom.
End-

3

Experimentar:

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

Se você realmente deseja usar o REGEX para análise de HTML, não execute .group () diretamente na correspondência, pois pode retornar Nenhum.
iElectric

Você deve usá- .*?lo caso haja vários </title>no documento (improvável, mas você nunca sabe).
tonfa

@iElectric: você pode experimentá-lo, exceto o bloco, se realmente quiser, certo?
25210 tonfa

3

Os trechos de código fornecidos não lidam com Exceptions Posso sugerir

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

Isso retorna uma sequência vazia por padrão, se o padrão não foi encontrado ou a primeira correspondência.


1

Eu acho que isso deve ser suficiente:

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

... assumindo que seu texto (HTML) esteja em uma variável chamada "texto".

Isso também pressupõe que não há outras tags HTML que possam ser legalmente incorporadas dentro de uma tag HTML TITLE e que não há maneira de incorporar legalmente qualquer outro caractere <dentro desse contêiner / bloco.

No entanto ...

Não use expressões regulares para análise de HTML no Python. Use um analisador de HTML! (A menos que você escreva um analisador completo, o que seria um trabalho extra quando vários analisadores de HTML, SGML e XML já estiverem nas bibliotecas padrão.

Se você manipular o HTML de sopa de tags do "mundo real" (que geralmente não está em conformidade com qualquer validador SGML / XML), use o pacote BeautifulSoup . Ainda não está nas bibliotecas padrão, mas é amplamente recomendado para esse fim.

Outra opção é: lxml ... que é escrito para HTML adequadamente estruturado (conforme os padrões). Mas tem uma opção para usar o BeautifulSoup como um analisador: ElementSoup .

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.