Domanda

Ho questa stringa contenente una grossa porzione di codice HTML e sto cercando di estrarre il collegamento dalla porzione href="..." della stringa.L'href potrebbe essere in una delle seguenti forme:

<a href="..." />
<a class="..." href="..." />

Non ho davvero problemi con le espressioni regolari, ma per qualche motivo quando utilizzo il seguente codice:

        String innerHTML = getHTML(); 
  Pattern p = Pattern.compile("href=\"(.*)\"", Pattern.DOTALL);
  Matcher m = p.matcher(innerHTML);
  if (m.find()) {
   // Get all groups for this match
   for (int i=0; i<=m.groupCount(); i++) {
    String groupStr = m.group(i);
    System.out.println(groupStr);

   }
  }

Qualcuno può dirmi cosa c'è che non va nel mio codice?Ho fatto queste cose in php ma in Java in qualche modo sto facendo qualcosa di sbagliato...Quello che succede è che stampa l'intera stringa html ogni volta che provo a stamparla...

MODIFICARE:Solo in modo che tutti sappiano con che tipo di stringa ho a che fare:

<a class="Wrap" href="item.php?id=43241"><input type="button">
    <span class="chevron"></span>
  </a>
  <div class="menu"></div>

Ogni volta che eseguo il codice, stampa l'intera stringa...Questo è il problema...

E riguardo all'utilizzo di jTidy...Ci sto lavorando ma sarebbe interessante sapere cosa è andato storto anche in questo caso...

È stato utile?

Soluzione

.* 

Questa è un'operazione avido che avrà carattere comprese le virgolette.

Prova qualcosa di simile:

"href=\"([^\"]*)\""

Altri suggerimenti

Ci sono due problemi con il codice che hai postato:

In primo luogo il .* nella vostra espressione regolare è avido. Questo farà sì che per abbinare tutti i caratteri fino a quando l'ultimo carattere " che può essere trovato. È possibile effettuare questa partita non sia avido modificando questo .*?.

In secondo luogo, per raccogliere tutte le partite, è necessario mantenere l'iterazione con Matcher.find, piuttosto che alla ricerca di gruppi. Gruppi consentono di accedere ad ogni sezione tra parentesi della regex. È tuttavia, sta cercando ogni volta l'intera espressione regolare corrisponde.

Mettendo insieme questi si dà la seguente codice che dovrebbe fare quello che ti serve:

Pattern p = Pattern.compile("href=\"(.*?)\"", Pattern.DOTALL);
Matcher m = p.matcher(innerHTML);

while (m.find()) 
{
    System.out.println(m.group(1));
}

Regex è grande, ma non è lo strumento giusto per questo scopo particolare. Normalmente si desidera utilizzare un parser stackbased per questo. Date un'occhiata a Java API HTML parser di come jTidy .

Utilizza un parser integrato.Qualcosa di simile a:

    EditorKit kit = new HTMLEditorKit();
    HTMLDocument doc = (HTMLDocument)kit.createDefaultDocument();
    doc.putProperty("IgnoreCharsetDirective", Boolean.TRUE);
    kit.read(reader, doc, 0);

    HTMLDocument.Iterator it = doc.getIterator(HTML.Tag.A);

    while (it.isValid())
    {
        SimpleAttributeSet s = (SimpleAttributeSet)it.getAttributes();
        String href = (String)s.getAttribute(HTML.Attribute.HREF);
        System.out.println( href );
        it.next();
    }

Oppure usa ParserCallback:

import java.io.*;
import java.net.*;
import javax.swing.text.*;
import javax.swing.text.html.parser.*;
import javax.swing.text.html.*;

public class ParserCallbackText extends HTMLEditorKit.ParserCallback
{
    public void handleStartTag(HTML.Tag tag, MutableAttributeSet a, int pos)
    {
        if (tag.equals(HTML.Tag.A))
        {
            String href = (String)a.getAttribute(HTML.Attribute.HREF);
            System.out.println(href);
        }
    }

    public static void main(String[] args)
        throws Exception
    {
        Reader reader = getReader(args[0]);
        ParserCallbackText parser = new ParserCallbackText();
        new ParserDelegator().parse(reader, parser, true);
    }

    static Reader getReader(String uri)
        throws IOException
    {
        // Retrieve from Internet.
        if (uri.startsWith("http:"))
        {
            URLConnection conn = new URL(uri).openConnection();
            return new InputStreamReader(conn.getInputStream());
        }
        // Retrieve from file.
        else
        {
            return new FileReader(uri);
        }
    }
}

Il Reader potrebbe essere uno StringReader.

Un altro modo semplice e affidabile per farlo è quello di utilizzare Jsoup

Document doc = Jsoup.connect("http://example.com/").get();
Elements links = doc.select("a[href]");
for (Element link : links){
  System.out.println(link.attr("abs:href"));
}

è possibile utilizzare una libreria html parser. jtidy ad esempio, si dà un modello DOM del HTML, dal quale è possibile estrarre tutti elementi "a" e leggere la loro attributo "href"

"href=\"(.*?)\"" dovrebbe anche funzionare, ma penso che la risposta di Kugel funzionerà più velocemente.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top