2010-04-10 8 views
8

Quando si cerca di estrarre il titolo di una pagina HTML Ho sempre usato la seguente espressione regolare:Python regex look-dietro richiede schema fisso-larghezza

(?<=<title.*>)([\s\S]*)(?=</title>) 

Quale estrarrà tutto tra i tag in un documento e ignorare i tag stessi. Tuttavia, quando si cerca di utilizzare questa regex in Python solleva la seguente eccezione:

Traceback (most recent call last): 
File "test.py", line 21, in <module> 
    pattern = re.compile('(?<=<title.*>)([\s\S]*)(?=</title>)') 
File "C:\Python31\lib\re.py", line 205, in compile 
    return _compile(pattern, flags) 
File "C:\Python31\lib\re.py", line 273, in _compile 
    p = sre_compile.compile(pattern, flags) File 
"C:\Python31\lib\sre_compile.py", line 495, in compile 
    code = _code(p, flags) File "C:\Python31\lib\sre_compile.py", line 480, in _code 
_compile(code, p.data, flags) File "C:\Python31\lib\sre_compile.py", line 115, in _compile 
    raise error("look-behind requires fixed-width pattern") 
sre_constants.error: look-behind requires fixed-width pattern 

Il codice che sto usando è:

pattern = re.compile('(?<=<title.*>)([\s\S]*)(?=</title>)') 
m = pattern.search(f) 

se faccio alcune modifiche minime funziona:

pattern = re.compile('(?<=<title>)([\s\S]*)(?=</title>)') 
m = pattern.search(f) 

Questo, tuttavia, non terrà conto di potenziali titoli html che per qualche motivo hanno attributi o simili.

Qualcuno sa una buona soluzione per questo problema? Qualsiasi consiglio è apprezzato.

+0

C'è qualche ragione deve essere un'asserzione di larghezza zero? Potresti semplicemente usare un gruppo non catturante? –

+3

Sebbene non si debbano utilizzare espressioni regolari per elaborare l'HTML. Perché non usi affatto lo sguardo in giro e non qualcosa come ' ([\ s \ S] *)' e prendi la corrispondenza del primo gruppo? – Gumbo

risposta

1

Se si desidera solo per ottenere il tag title,

html=urllib2.urlopen("http://somewhere").read() 
for item in html.split("</title>"): 
    if "<title>" in item: 
     print item[ item.find("<title>")+7: ] 
10

Eliminare l'idea di analizzare l'HTML con espressioni regolari e utilizzare invece una libreria di analisi HTML effettiva. Dopo una rapida ricerca ho trovato this one. È un modo molto più sicuro per estrarre informazioni da un file HTML.

Ricorda, l'HTML non è un linguaggio normale, quindi le espressioni regolari sono fondamentalmente lo strumento sbagliato per estrarre informazioni da esso.

+6

BeautifulSoup (http://www.crummy.com/software/BeautifulSoup/) è anche una buona opzione. –

5

Here's a famous answer su parsing html con espressioni regolari che fa un ottimo lavoro dicendo "non utilizzare regex per analizzare html".

+4

Sì e no. Non si dovrebbe usare regex per analizzare un intero DOM o complicati raggruppamenti di tag. Tuttavia, l'analisi di un singolo tag non annidato, come l'OP sta tentando di fare, è un uso perfettamente legittimo della regex. – Cerin

2

Che dire qualcosa come:

r = re.compile("(<title.*>)([\s\S]*)(</title>)") 
title = r.search(page).group(2) 
3

L'espressione regolare per estrarre il contenuto di HTML non annidata/tag XML è in realtà molto simple:

r = re.compile('<title[^>]*>(.*?)</title>') 

Tuttavia, per qualcosa di più complesso, è necessario utilizzare un parser DOM corretto come urlli b o BeautifulSoup.