【发布时间】:2014-01-02 12:29:13
【问题描述】:
我正在尝试找出一个匹配所有不是元素属性或超链接内容的 URL 的正则表达式。
应该匹配:
1. This is a url http://www.google.com
不应匹配:
1. <a href="http://www.google.com">Google</a>
2. <a href="http://www.google.com">http://www.google.com</a>
3. <img src="http://www.google.com/image.jpg">
4. <div data-url="http://www.google.com"></div>
我目前正在使用这个正则表达式来匹配所有 URL,我想我知道我必须检测什么,但我就是不知道如何使用正则表达式。
\\b(https?|ftp|file)://[-a-zA-Z0-9+&@#/%?=~_|!:,.;]*[-a-zA-Z0-9+&@#/%=~_|]
已编辑
我想要达到的目标如下。我想转换这个字符串。
This is a url http://www.google.com <a href="http://www.google.com" title="Go to Google">Google</a><a href="http://www.google.com">http://www.google.com</a><img src="http://www.google.com/image.jpg"><div data-url="http://www.google.com"></div>
到
This is a url <a href="http://www.google.com">http://www.google.com</a> <a href="http://www.google.com" title="Go to Google">Google</a><a href="http://www.google.com">http://www.google.com</a><img src="http://www.google.com/image.jpg"><div data-url="http://www.google.com"></div>
通过删除标签然后将它们放回去进行预处理并不能解决问题,因为实际上最终会删除现有超链接元素的所有数据属性。当在 href 之外的其他属性中使用其他 URL 时,它也不能解决问题。
到目前为止,我还没有找到任何人建议的解决方案,并且到目前为止我还没有找到使用 HTML 解析器执行此操作的方法。使用正则表达式实际上似乎更可行。
已编辑 2
在根据 Dean 的建议进行尝试之后,我准备排除 HTML 解析器能够实现这一点,因为它无法处理字符串而不使其成为有效的 HTML 文档。这是基于建议示例的代码 + 处理排除案例 2 的修复。
Document doc = Jsoup.parseBodyFragment(htmlText);
final List<TextNode> nodesToChange = new ArrayList<TextNode>();
NodeTraversor nd = new NodeTraversor(new NodeVisitor() {
@Override
public void tail(Node node, int depth) {
if (node instanceof TextNode) {
TextNode textNode = (TextNode) node;
Node parent = node.parent();
if(parent.nodeName().equals("a")){
return;
}
String text = textNode.getWholeText();
List<String> allMatches = new ArrayList<String>();
Matcher m = Pattern.compile("\\b(https?|ftp|file)://[-a-zA-Z0-9+&@#/%?=~_|!:,.;]*[-a-zA-Z0-9+&@#/%=~_|]")
.matcher(text);
while (m.find()) {
allMatches.add(m.group());
}
if(allMatches.size() > 0){
nodesToChange.add(textNode);
}
}
}
@Override
public void head(Node node, int depth) {
}
});
nd.traverse(doc.body());
此代码将 HTML、HEAD 和 BODY 标记添加到结果中。关于这个问题,我能想到的唯一方法是检查字符串中是否存在 HTML、HEAD 和 BODY 标签。如果没有,请在处理后将它们剥离。
我希望其他人有比这个 hack 更好的建议。就处理时间而言,使用 JSOUP 已经非常昂贵,所以我真的不想在不必要的情况下增加更多开销。
【问题讨论】:
-
“但我就是不知道如何使用正则表达式。” 正则表达式从来都不是用来解析 HTML 的。使用 HTML 解析器。 stackoverflow.com/q/1732348/418556
-
正则表达式是一种强大的形式,但它们不太适合从 html 或 XML 中提取数据。您应该在预处理步骤中使用 XML 查询语言(例如 XQuery、XPath 或 XSLT)或 XML API(例如 SAX)。在此预处理步骤中,您可以摆脱所有属性和锚标记。如果您的 html 格式不正确,您将不得不在另一个预处理步骤中使用 HTML 清理器。
-
@AndrewThompson 我实际上也可以使用 HTML 解析器。你将如何处理它。假设我有这个字符串“这是一个 url google.com google.com">Google</a><a href="google.com">http://www.google.com</a><img src="google.com/image.jpg"><divdata-url="google.com"></div>"。每个人都一直建议使用 HTML/XML 解析器,但没有人提出解决这个问题的方法。 XML 解析器不能在这里使用,因为它不是格式良好的 XML。使用 HTML 解析器,我仍然需要找到一种方法来处理它。
-
@user152468 肯定更适合就具体细节提供建议。我在这件事上的“专业知识”是通过其他人获得的,并且在我最初的评论中几乎筋疲力尽。对不起。
-
顺便说一句 - 请不要尝试将代码、HTML 等放入 cmets 中。请改为编辑问题。