Java:Ich habe eine große HTML-Zeichenfolge und muss den Text „href=“…“ extrahieren

StackOverflow https://stackoverflow.com/questions/1670593

  •  13-09-2019
  •  | 
  •  

Frage

Ich habe diese Zeichenfolge, die einen großen Teil des HTML-Codes enthält, und versuche, den Link aus dem href="..."-Teil der Zeichenfolge zu extrahieren.Der href könnte eine der folgenden Formen haben:

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

Ich habe nicht wirklich ein Problem mit Regex, aber aus irgendeinem Grund, wenn ich den folgenden Code verwende:

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

   }
  }

Kann mir jemand sagen, was mit meinem Code nicht stimmt?Ich habe das in PHP gemacht, aber in Java mache ich irgendwie etwas falsch ...Was passiert, ist, dass der gesamte HTML-String gedruckt wird, wenn ich versuche, ihn zu drucken ...

BEARBEITEN:Nur damit jeder weiß, mit was für einer Saite ich es zu tun habe:

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

Jedes Mal, wenn ich den Code ausführe, wird die gesamte Zeichenfolge gedruckt ...Das ist das Problem...

Und über die Verwendung von jTidy ...Ich bin dabei, aber es wäre interessant zu wissen, was auch in diesem Fall schief gelaufen ist ...

War es hilfreich?

Lösung

.* 

Dies ist eine gierige Operation, die jedes Zeichen einschließlich der Anführungszeichen nehmen.

Versuchen Sie so etwas wie:

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

Andere Tipps

Es gibt zwei Probleme mit dem Code, den Sie geschrieben haben:

Zum einen die .* in Ihrem regulären Ausdruck ist gierig. Dies wird dazu führen, dass alle Zeichen bis zum letzten " Zeichen zu finden, die gefunden werden können. Sie können dieses Spiel machen nicht-gierig durch diese zu .*? ändern.

Zweitens, alle Spiele zu holen, müssen Sie mit Matcher.find halten Iterieren anstatt auf der Suche nach Gruppen. Gruppen geben Sie jeden eingeklammerten Abschnitt des Regex zugreifen. aber Sie werden für jedes Mal suchen der gesamte reguläre Ausdruck.

Setzt man diese zusammen gibt Ihnen die folgenden Code, tun sollten, was Sie brauchen:

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

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

Regex ist groß, aber nicht das richtige Werkzeug für diesen besonderen Zweck. Normalerweise möchten Sie einen stackbased Parser für diesen Einsatz. Hier finden Sie aktuelle Java HTML-Parser-API wie jtidy .

Verwenden Sie einen integrierten Parser.Etwas wie:

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

Oder verwenden Sie den 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);
        }
    }
}

Der Reader könnte ein StringReader sein.

Eine weitere einfache und zuverlässige Art und Weise, es zu tun ist, indem Sie 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"));
}

Sie können eine HTML-Parser-Bibliothek verwenden. jtidy zum Beispiel gibt Ihnen ein DOM-Modell des html, von Weichen Sie alle „a“ Elemente extrahieren und lesen ihre "href" Attribut

"href=\"(.*?)\"" sollte auch funktionieren, aber ich denke, Kugel Antwort schneller arbeiten.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top