最近有一个比较奇怪的需求,就是,要删除掉HTML中的某段文本,但是不能删除HTML标签,
如<b>(hello word)</b>中的(hello word)
我们可以很容易通过正则替换掉。但标签变得特别复杂的时候呢,我们改这如何替换
如:<span style="XXXXX">你好,我想要去掉后<i>面的(hello</i><br> <b>word</b>)内容<span>
这个时候,如果直接替换就可能会将中间的一些标签体也替换掉,这不是我们想要的效果,这个时候,我们该怎么办呢?
这篇博客就是要解决关于HTML中某段内容的过滤
在分享内容之前,先说一下,如果各位有好的开源项目或jar可以给博主留言或发送电子邮件whb3299065@126.com
好了我们先说一下思路,如果是着急的童鞋,可以直接跳过这里,在最后,有我们的一个demo
首先,我们去观察一下数据:
<span style="XXXXX">你好,我想要去掉后<i>面的(hello</i><br> <b>word</b>)内容</span>
发现我们的内容前后或是正文中由于有很多标签,字符串干扰,使得我们提取变得复杂化。我的想法就是,通过正则表达式,先将内容匹配出来,然后将标签过滤掉。
步骤:
1. 将要替换的内容进行加工,加工成为一个正则表达式
我的做法是将字符串遍历,在每个字符前后加入:\\s*(<.*?>)?\\s*这样的标记
生成(\s*(<.?>)?\s* h\s(<.?>)?\s* e\s(<.?>)?\s*l\s(<.?>)?\s*l\s(<.?>)?\s*o\s(<.?>)?\s \s*(<.?>)?\s*w\s(<.?>)?\s*o\s(<.?>)?\s*r\s(<.?>)?\s*d\s(<.*?>)?\s* )
这样我们可以通过字符串matches函数,检查html中是包含我们需要替换的数据
2.过滤标签
最开始,我是靠一个一个字符读取,先找到开始位置和结束位置,如果发现是开始位置,就只读取'>'字符后面的内容,如果读取到'<'则不进行读取。这样将读取到的内容添加到一个变量中,
后来,我发现,通过正则表达式可以更完美的实现我们想要的效果,就是将需要的内容作为捕获组,进行捕获,将不需要的位置,不对其捕获,具体就是在上面生成的正则前后加上"(.*?)",以及在其后加上"(.*)",然后就可以通过group进行抓取了
3.避坑指南
这个dome只是我写的一个小程序,如果你仔细推敲会发现有很多漏洞,比如,字符的转义并不完全,等 一个段落中有多个符合要求的内容,还有,我并没有对多行文本匹配进行解决……但是这个工具用在我的项目中已经是足够的。所以,当你要使用时,一定要避免这些问题
另外如果你将这个工具拿去直接使用的话,我想你一定会被你的领导批评的,因为这个函数中想做的事情太多了,正真使用应该将它重构,将函数分解
//移除html指定内容
public static String removeTextForHtmlTest(String html, String text) throws Exception {
String data = "";
String reqText = "";
for (int i = 0; i < text.length(); i++) {
char c = text.charAt(i);
String aTextChar;
switch (c) {
case '(':aTextChar = "\\(";break;
case '.':aTextChar = "\\.";break;
case '*':aTextChar = "\\*";break;
case ')':aTextChar = "\\)";break;
default:aTextChar = "" + c;
}
reqText += aTextChar + "\\s*(<.*?>)?\\s*";
}
reqText = reqText.substring(0, reqText.lastIndexOf("\\s*(<.*?>)?\\s*"));
Pattern pattern = Pattern.compile("(.*?)"+reqText+"(.*)");
try {
Matcher matcher = pattern.matcher(html);
while (matcher.find()) {
for (int i = 1; i < matcher.groupCount()+1; i++) {
if (StringUtils.isNotBlank(matcher.group(i)))
data+=matcher.group(i);
}
}
} catch (IllegalStateException e) {throw new Exception("没有发现对应数据");}
System.out.println(data);
return data;
}
结果:
html:<span style="XXXXX">你好,我想要去掉后<i>面的(hello</i><br> <b>word</b>)内容<span>
text:(hello word)
<span style="XXXXX">你好,我想要去掉后<i>面的</i><br><b></b>内容<span>
当然,这段代码我已经重构过三次了,之所以发出的是没有经过重构的,是因为我太懒了