Java:我有一大串html,需要提取href ="..."文本

Leg*_*end 7 html java regex html-parsing

我有这个字符串包含一大块html,我试图从字符串的href ="..."部分提取链接.href可以采用以下形式之一:

<a href="..." />
<a class="..." href="..." />
Run Code Online (Sandbox Code Playgroud)

我没有真正的正则表达式的问题,但出于某种原因我使用以下代码:

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

   }
  }
Run Code Online (Sandbox Code Playgroud)

有人能告诉我我的代码有什么问题吗?我在PHP中做了这些东西,但在Java中,我在某种程度上做错了什么...发生的事情是,每当我尝试打印它时,它会打印整个html字符串...

编辑:这样每个人都知道我正在处理什么样的字符串:

<a class="Wrap" href="item.php?id=43241"><input type="button">
    <span class="chevron"></span>
  </a>
  <div class="menu"></div>
Run Code Online (Sandbox Code Playgroud)

每次我运行代码时,它会打印整个字符串......这就是问题所在......

关于使用jTidy ......我正在使用它,但知道在这种情况下出了什么问题会很有趣......

Kug*_*gel 8

.* 
Run Code Online (Sandbox Code Playgroud)

这是一个贪婪的操作,它将包含任何字符,包括引号.

尝试类似的东西:

"href=\"([^\"]*)\""
Run Code Online (Sandbox Code Playgroud)

  • Xpath也适用于html吗?@Peter我明白了,但这里的工作不是要匹配html节点,而只是找到链接. (2认同)

Phi*_*oss 6

您发布的代码存在两个问题:

首先.*,你的正则表达式是贪婪的.这将使其匹配所有字符,直到"找到可以找到的最后一个字符.你可以通过改变它来使这个匹配变得非贪婪.*?.

其次,要获取所有匹配,您需要继续迭代Matcher.find而不是寻找组.通过组,您可以访问正则表达式的每个带括号的部分.但是,您每次都在查找整个正则表达式.

将这些放在一起为您提供以下代码,它们可以满足您的需求:

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

while (m.find()) 
{
    System.out.println(m.group(1));
}
Run Code Online (Sandbox Code Playgroud)


Bal*_*usC 5

正则表达式很棒但不适合这个特定目的.通常,您希望使用基于堆栈的解析器.看看Java HTML解析器API就像jTidy一样.


cam*_*ckr 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();
    }
Run Code Online (Sandbox Code Playgroud)

或使用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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Reader可以是StringReader。