7

この文字列には大量の html が含まれており、文字列の href="..." 部分からリンクを抽出しようとしています。href は、次のいずれかの形式になります。

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

正規表現に問題はありませんが、何らかの理由で次のコードを使用すると:

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

   }
  }

誰かが私のコードの何が問題なのか教えてもらえますか? 私はphpでこのようなことをしましたが、Javaではどういうわけか間違ったことをしています...何が起こっているのかは、印刷しようとするたびにhtml文字列全体を印刷することです...

編集:私が扱っている文字列の種類を誰もが知っているように:

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

コードを実行するたびに、文字列全体が出力されます...それが問題です...

そしてjTidyの使用について...私はそれに取り組んでいますが、この場合にも何がうまくいかなかったのかを知ることは興味深いでしょう...

4

7 に答える 7

8
.* 

これは、引用符を含む任意の文字を取る貪欲な操作です。

次のようなものを試してください:

"href=\"([^\"]*)\""
于 2009-11-03T22:42:17.300 に答える
6

投稿したコードには 2 つの問題があります。

まず、.*正規表現の は貪欲です。これにより、最後"に見つかった文字まですべての文字が一致します。これを に変更することで、この一致を非貪欲にすることができます.*?

次に、すべての一致を取得するにMatcher.findは、グループを探すのではなく、反復を続ける必要があります。グループを使用すると、正規表現の括弧で囲まれた各セクションにアクセスできます。ただし、正規表現全体が一致するたびに探しています。

これらをまとめると、必要なことを行う次のコードが得られます。

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

while (m.find()) 
{
    System.out.println(m.group(1));
}
于 2009-11-03T22:48:33.310 に答える
5

正規表現は優れていますが、この特定の目的には適切なツールではありません。通常、これにはスタックベースのパーサーを使用します。jTidyのような Java HTML パーサー API を見てください。

于 2009-11-03T22:45:56.183 に答える
5

組み込みのパーサーを使用します。何かのようなもの:

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

または、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);
        }
    }
}

Reader は StringReader である可能性があります。

于 2009-11-03T23:26:58.723 に答える
4

それを行うためのもう 1 つの簡単で信頼できる方法は、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"));
}
于 2011-12-31T01:53:23.277 に答える
2

html パーサー ライブラリを使用できます。たとえば、 jtidyは html の DOM モデルを提供します。そこからすべての「a」要素を抽出し、それらの「href」属性を読み取ることができます。

于 2009-11-03T22:51:29.090 に答える
1

"href=\"(.*?)\""も動作するはずですが、Kugel の答えの方が速く動作すると思います。

于 2009-11-03T22:46:35.527 に答える