2009-03-24 23 views
14

Per favore qualcuno può dirmi un modo semplice per trovare i tag href e src in un file html usando le espressioni regolari in Java?
E poi, come ottengo l'URL associato al tag?Come utilizzare le espressioni regolari per analizzare HTML in Java?

Grazie per qualsiasi suggerimento.

+0

questione canonica: * [RegEx partita tag aperti ad eccezione di XHTML tag autonomi] (http://stackoverflow.com/questions/1732348/) * –

risposta

53

L'utilizzo di espressioni regolari per estrarre valori da HTML è sempre un errore. La sintassi HTML è molto più complessa che potrebbe apparire per la prima volta ed è molto facile che una pagina rilevi anche un'espressione regolare molto complessa.

Utilizzare invece HTML Parser. Vedi anche What are the pros and cons of the leading Java HTML parsers?

+3

Dipende da cosa stai facendo. Se si sta elaborando un sacco di codice HTML da fonti casuali, un parser HTML potrebbe non funzionare correttamente su alcuni di essi e probabilmente richiederà più memoria ed elaborazione rispetto a una regex. Ad esempio, il crawler Web di Heritrix utilizza regex per l'estrazione dei link su pagine HTML. – Kris

+0

La soluzione dipende dalla domanda ... – ReneS

+1

Prima di rispondere alla domanda originale, quindi suggerire come ottimizzare. Molte persone visitano questa domanda su SO sperando di imparare come analizzare HTML usando espressioni regolari, ma invece trovano qualcosa che non stavano cercando. L'uso delle espressioni regolari è veloce e sporco e non è necessario scaricare una libreria separata perché funzioni. –

3

ho cercato su Regular Expression Library (http://regexlib.com/Search.aspx?k=href e http://regexlib.com/Search.aspx?k=src)

Il migliore che ho trovato è stato

((?<html>(href|src)\s*=\s*")|(?<css>url\())(?<url>.*?)(?(html)"|\)) 

Guarda anche questi link per più espressioni:

http://regexlib.com/REDetails.aspx?regexp_id=2261

http://regexlib.com/REDetails.aspx?regexp_id=758

http://regexlib.com/REDetails.aspx?regexp_id=774

http://regexlib.com/REDetails.aspx?regexp_id=1437

+2

Odio quel sito. Vedo che non si preoccupano ancora di menzionare il sapore a cui è indirizzata una determinata regex. Questa regex (id = 2261) utilizza le acquisizioni e i condizionali denominati, nessuno dei quali è supportato da Java. –

5

Se si vuole imboccare la strada all'analisi di oggetti HTML, che Dave e vi consiglio qui è il codice per analizzare una stringa di dati per i tag di ancoraggio e stampare il loro href.

dal momento che si utilizzano solo i tag di ancoraggio, si dovrebbe andare bene solo con espressioni regolari, ma se si vuole fare di più andare con un parser. Il Mozilla HTML Parser è il migliore in circolazione.

File parserLibraryFile = new File("lib/MozillaHtmlParser/native/bin/MozillaParser" + EnviromentController.getSharedLibraryExtension()); 
       String parserLibrary = parserLibraryFile.getAbsolutePath(); 
       // mozilla.dist.bin directory : 
       final File mozillaDistBinDirectory = new File("lib/MozillaHtmlParser/mozilla.dist.bin."+ EnviromentController.getOperatingSystemName()); 

     MozillaParser.init(parserLibrary,mozillaDistBinDirectory.getAbsolutePath()); 
MozillaParser parser = new MozillaParser(); 
Document domDocument = parser.parse(data); 
NodeList list = domDocument.getElementsByTagName("a"); 

for (int i = 0; i < list.getLength(); i++) { 
    Node n = list.item(i); 
    NamedNodeMap m = n.getAttributes(); 
    if (m != null) { 
     Node attrNode = m.getNamedItem("href"); 
     if (attrNode != null) 
      System.out.println(attrNode.getNodeValue()); 
7

Non usare le espressioni regolari usano NekoHTML o TagSoup che sono un ponte che fornisce un SAX o DOM come nell'approccio XML per la visita di un documento HTML.

20

Le altre risposte sono vere. Java Regex API non è uno strumento adatto per raggiungere il tuo obiettivo. Utilizzare strumenti di alto livello efficienti, sicuri e ben testati menzionati nelle altre risposte.

Se i tuoi questione riguarda piuttosto Regex API che un problema di vita reale (fini ad esempio di apprendimento) - si può fare con il seguente codice:

String html = "foo <a href='link1'>bar</a> baz <a href='link2'>qux</a> foo"; 
Pattern p = Pattern.compile("<a href='(.*?)'>"); 
Matcher m = p.matcher(html); 
while(m.find()) { 
    System.out.println(m.group(0)); 
    System.out.println(m.group(1)); 
} 

e l'uscita è:

<a href='link1'> 
link1 
<a href='link2'> 
link2 

Si prega di notare che qualificatore pigro/riluttante *? deve essere usato per ridurre il raggruppamento al singolo tag. Il gruppo 0 è l'intera partita, il gruppo 1 è la successiva partita del gruppo (la successiva coppia di parentesi).

+0

Grazie. Anche se non è una regex reale "funziona-ovunque" funziona per i dati restituiti dalle tendenze hot di google e mi sono tirato i capelli per analizzarlo per un lungo periodo ... – rjha94

1

Le espressioni regolari possono solo analizzare le lingue regolari, per questo vengono chiamate espressioni regolari. L'HTML non è una lingua normale, quindi non può essere analizzato da espressioni regolari.

I parser HTML, d'altra parte, possono analizzare HTML, è per questo che vengono chiamati parser HTML.

Si consiglia di utilizzare il parser HTML preferito.

1

Contrariamente all'opinione comune, le espressioni regolari sono strumenti utili per estrarre i dati dal testo non strutturato (che è HTML).

Se si sta eseguendo l'estrazione di dati HTML complessi (ad esempio, trovare tutti i paragrafi in una pagina), l'analisi dell'HTML è probabilmente la strada da percorrere. Ma se hai solo bisogno di ottenere degli URL da HREF, allora un'espressione regolare funzionerebbe bene e sarà molto difficile romperla.

provare qualcosa di simile:

/<a[^>]+href=["']?([^'"> ]+)["']?[^>]*>/i 
Problemi correlati