【问题标题】:Regex extracting image links正则表达式提取图像链接
【发布时间】:2015-03-06 11:34:51
【问题描述】:

我有以下正则表达式,可以使用 java.util.regex 从 HTML 文档中提取链接

 <a\s.*?href=([^ >]+).*?<img\s.*?src=([^ ]+)(.*?>.*?<\/a>)

并怀疑它与此标记中的最后一个链接相匹配。

<font size="4">Mail : </font><a href="mailto:c.bantz@pgt-gmbh.com"><u><font size="4" color="#0000ff">s.weber@pgt-gmbh.com</font></u></a><br />
<br />
<font size="4">Internet : </font><a href="http://www.pgt-gmbh.com/"><u><font size="4" color="#0000ff">http://www.pgt-gmbh.com</font></u></a><font size="4"> </font><br />
<br />
<br />
<font size="4"> </font><a class="domino-attachment-link" style="display: inline-block; text-align: center" href="/_dv/_dv/documents_DE.nsf/0/7fadd8be280a2e34c1257dfd00307098/$FILE/Anfrage.pdf" title="Anfrage.pdf"><img src="/_dv/_dv/documents_DE.nsf/0/7fadd8be280a2e34c1257dfd00307098/f_Text/0.5F66?OpenElement&FieldElemFormat=gif" width="32" height="32" alt="Anfrage.pdf" border="0" /> - Anfrage.pdf</a>

但它与链接不匹配,而是执行类似于贪婪搜索的操作,从 mailto: 开始并以最后一个链接结束。相同的表达式适用于http://regex101.com 中的正则表达式测试器。

有什么提示吗?

【问题讨论】:

  • 再次转义反斜杠。
  • 使用 HTML 解析器不是更容易吗?
  • 如果转义是问题所在,java 将无法编译。事实上,即使是 eclipse 也能正确找到正则表达式,但 java 不能。
  • 转义反斜杠不是问题。我刚刚删除了它们以提供可在 RegEx 测试器中测试的解决方案。 @stefanA 你是如何在 Eclipse 中测试它的?

标签: java regex


【解决方案1】:

如果换行符位于文本行的末尾,则不会出现此问题。

现在我有一个解释: &lt;a href="mailto 与正则表达式 &lt;a\s.*?href=([^ &gt;]+) 匹配。以下.*? 将匹配任何字符序列(没有换行符),直到找到&lt;img...。它正是这样做的(在没有换行符的情况下)。

示例(一个有换行符,一个没有换行符):

private static final Pattern P = Pattern.compile("<a\\s.*?href=([^ >]+).*?<img\\s.*?src=([^ ]+)(.*?>.*?<\\/a>)");
private static final String TEXT = "<font size=\"4\">Mail              : </font><a href=\"mailto:c.bantz@pgt-gmbh.com\"><u><font size=\"4\" color=\"#0000ff\">s.weber@pgt-gmbh.com</font></u></a><br />"
    + "<br />"
    + "<font size=\"4\">Internet        : </font><a href=\"http://www.pgt-gmbh.com/\"><u><font size=\"4\" color=\"#0000ff\">http://www.pgt-gmbh.com</font></u></a><font size=\"4\"> </font><br />"
    + "<br />"
    + "<br />"
    + "<font size=\"4\"> </font><a class=\"domino-attachment-link\" style=\"display: inline-block; text-align: center\" href=\"/_dv/_dv/documents_DE.nsf/0/7fadd8be280a2e34c1257dfd00307098/$FILE/Anfrage.pdf\" title=\"Anfrage.pdf\"><img src=\"/_dv/_dv/documents_DE.nsf/0/7fadd8be280a2e34c1257dfd00307098/f_Text/0.5F66?OpenElement&FieldElemFormat=gif\" width=\"32\" height=\"32\" alt=\"Anfrage.pdf\" border=\"0\" /> - Anfrage.pdf</a>";
private static final String NEWLINE_TEXT = "<font size=\"4\">Mail              : </font><a href=\"mailto:c.bantz@pgt-gmbh.com\"><u><font size=\"4\" color=\"#0000ff\">s.weber@pgt-gmbh.com</font></u></a><br />\n"
    + "<br />\n"
    + "<font size=\"4\">Internet        : </font><a href=\"http://www.pgt-gmbh.com/\"><u><font size=\"4\" color=\"#0000ff\">http://www.pgt-gmbh.com</font></u></a><font size=\"4\"> </font><br />\n"
    + "<br />\n"
    + "<br />\n"
    + "<font size=\"4\"> </font><a class=\"domino-attachment-link\" style=\"display: inline-block; text-align: center\" href=\"/_dv/_dv/documents_DE.nsf/0/7fadd8be280a2e34c1257dfd00307098/$FILE/Anfrage.pdf\" title=\"Anfrage.pdf\"><img src=\"/_dv/_dv/documents_DE.nsf/0/7fadd8be280a2e34c1257dfd00307098/f_Text/0.5F66?OpenElement&FieldElemFormat=gif\" width=\"32\" height=\"32\" alt=\"Anfrage.pdf\" border=\"0\" /> - Anfrage.pdf</a>";

public static void main(String[] args) {
    Matcher m = P.matcher(TEXT);
    if (m.find()) {
        System.out.println(m.group());
    }
    m = P.matcher(NEWLINE_TEXT);
    if (m.find()) {
        System.out.println(m.group());
    }
}

输出:

&lt;a href="mailto:c.bantz@pgt-gmbh.com"&gt;... 没有换行符

&lt;a class="domino-attachment-link"... 带换行符

更好的模式

&lt;a\s[^&gt;]*?href=([^&gt;]+)&gt;&lt;img\s.*?src=([^ ]+)(.*?&gt;.*?&lt;\/a&gt;)

HTML 和正则表达式的问题在于,上面的模式只匹配特定的情况,如果某些标记介于 &lt;a...&gt;&lt;img...&gt; 之间,那么它会失败。这当然可以解决,但表达变得越来越难以理解。

所以:如果您想针对多个链接执行此提取问题,则应切换到 HTML 解析器(尽管找到最佳解析器本身就是一门科学)。

【讨论】:

  • 谢谢,这很清楚。我刚刚发现,Pattern.DOTALL 甚至可以匹配,包括换行符。您是否也有提示,我如何更改模式以使其仅包含带有 &lt;img 标记的链接?
  • 我刚刚编辑了我的答案并添加了一个工作模式。但是用正则表达式提取html确实是恶意的。这种模式可能在一种情况下有效,而另一种特殊情况会失败。因此html解析器是最好的选择。
猜你喜欢
  • 2011-05-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-26
  • 2014-03-22
  • 2014-07-15
相关资源
最近更新 更多