Pregunta

Tengo esta cadena que contiene una gran cantidad de html y estoy intentando extraer el enlace de la parte href="..." de la cadena.El href podría tener una de las siguientes formas:

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

Realmente no tengo ningún problema con las expresiones regulares, pero por alguna razón uso el siguiente código:

        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);

   }
  }

¿Alguien puede decirme qué está mal con mi código?Hice esto en php pero en Java de alguna manera estoy haciendo algo mal...Lo que sucede es que imprime toda la cadena html cada vez que intento imprimirla...

EDITAR:Para que todos sepan con qué tipo de cadena estoy tratando:

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

Cada vez que ejecuto el código, imprime la cadena completa...Ese es el problema...

Y sobre el uso de jTidy...Estoy en ello, pero también sería interesante saber qué salió mal en este caso...

¿Fue útil?

Solución

.* 

Esta es una operación codiciosos que se llevará a cualquier carácter incluyendo las comillas.

Pruebe algo como:

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

Otros consejos

Hay dos problemas con el código que has enviado:

En primer lugar el .* en su expresión regular es codicioso. Esto hará que coincide con todos los caracteres hasta que el último carácter " que se pueden encontrar. Puede tomar este partido sea no expansivo cambiando esto a .*?.

En segundo lugar, para recoger todos los partidos, que necesita para mantener la iteración con Matcher.find en lugar de buscar grupos. Grupos le dan acceso a cada sección entre paréntesis de la expresión regular. Usted sin embargo, busca cada vez que coincide con toda la expresión regular.

Poner estos juntos le da el código siguiente que debe hacer lo que tiene:

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

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

Regex es genial, pero no la herramienta adecuada para este propósito en particular. Normalmente desea utilizar un analizador stackbased para esto. Echar un vistazo a Java HTML API analizador como JTidy .

Utilice un analizador integrado.Algo como:

    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();
    }

O utilice 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);
        }
    }
}

El lector podría ser un StringReader.

Otra forma fácil y fiable de hacerlo es mediante el uso de 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"));
}

puede usar una biblioteca de html analizador. JTidy por ejemplo, le da un modelo DOM del HTML, desde los que se puede extraer todos los "unos" elementos y leer su atributo "href"

"href=\"(.*?)\"" también debería funcionar, pero creo que la respuesta de Kugel funcionará más rápido.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top