用正则将链接替换成跳转或空链接
用正则将链接替换成跳转或空链接
当你的网站有会员发布信息功能的时候,就会是一件非常头疼的事情,刚开始做的小网站一但被会员在文章中加入大量的链接,这对于网站优化工作是非常不利的,我们通常的做法就是将链接去掉,或将链接替换成空链接,这方面的文章在网上也有很多,但是讲的都不是很详细,今天周六,我就抽时间写一篇详细的教程。
我们要完成这样的工作必须要用正则表达式来完成,所以我们先要导入一个名字空间
using System.Text.RegularExpressions;
第一个问题:将文章中的链接去掉
首先我写了这样一个方法:
public static string StrReplace(string contentsStr, string pattern, string replaceStr)
{
return Regex.Replace(contentsStr, pattern, replaceStr, RegexOptions.IgnoreCase);
}
很多人都知道string有一个Replace方法,确不知道regex也有一个这样的方法,string的replace方法只可以完全替换,而regex的replace则比string的强大的多,可以用正则表达式去匹配一些模糊的数据然后在替换。
我写的这个方法有三个参数,第一个参数contentsStr是你文章的源字符串,第二个pattern是你的正则表达式字符串,第三个replaceStr是你要替换成的字符串。
OK,那么如果我们要把文章中的链接全部替换掉怎么调用这个方法呢,我们首先要写正则表达式,我已经写好了, <a.*?> 这个正则表达式可以把源代码中的a标记整个提取出来,不管里面有什么style还是title或href属性,这个表达式可以匹配这样的字符:
<a href=”aa”>
<a href=”aa” style=”font-size:12px;”>
<a href=”aa” style=”font-size:12px;” title=”aaa”>
那么我们这样调用这个方法就可以了
contentsStr=StrReplace(contentsStr,”<a.*?>”,”");
OK,这样我们就链接的前半边替换掉了,然后我们不要忘了,a标记的返回标记,这个用string的replace就可以替换了。
contentsStr=contentsStr.Replace(“</a>”,”");
至此我们的链接基本就全部清空了。
第二个问题:将链接替换成空链接
我在写文章之前去网上搜索了一下,很多的写法,不过感觉都特别的乱,可以说是乱做一团,正则表达式也是
复杂的要命,其实根本没必要那么费力,我们只需要把上面的方法的调用方法简单的改一下就行了。
contentsStr=StrReplace(contentsStr,”<a.*?>”,”<a href=”#”>”);
怎么样,这样行不行,一定行的,我们做事要多动一动脑子,很简单的一个替换就解决了,干嘛搞得那么复杂
。
不过我这样写这个代码有一个问题,那就是当文章中的链接应用了样式,我这样就全替换掉了,现在的空链接
是应用的默认样式,好,现在就给你解决这个问题。
第三个问题:将链接替换成其它网址或空链接
下面大家先来看一个正则表达式:(?s)<a[s][^>]*hrefs*=s*[""']?(?<url>([^""'>s]*))[""']?[^>]*>(?<title>([^<]+|.*?)?)</as*>
这个正则号称是可以提取页面中所有的链接,包含单引号的或双引号的和没有引号的。
这确实是一个问题,因为现在的html标记写的都不是很标准,网址用单引号和双引号以及不用引号都可以,所以我们的正则表达式也不是特别好写,我在网上搜索了半天也没有找到一个合适的正则,全都是匹配双引号的,遇到没有引号的和单引号的就匹配不出来了。
上面那个正则不是我写的,也是在一个牛人的博客里看到的,不过那不是我想要的,我自己写了一个简单的正则:href=s*[""']?S*[s""']?
用这个正则就可以把页面中a标记的链接全部提取出来了。
为了方便菜鸟学习,我把提取链接的方法也粘出来,代码如下:
/// <summary>
/// 提取页面的超级链接或其它指定字符返回ArrayList
/// </summary>
/// <param name=”StrCode”>源字符串</param>
/// <param name=”strRegex”>正则表达式</param>
/// <returns></returns>
public static ArrayList GetHyperLinks(string StrCode, string strRegex)
{
ArrayList al = new ArrayList();
Regex r = new Regex(strRegex, RegexOptions.IgnoreCase);
MatchCollection m = r.Matches(StrCode);
for (int i = 0; i <= m.Count – 1; i++)
{
bool rep = false;
string strNew = m[i].ToString();
// 过滤重复的URL
foreach (string str in al)
{
if (strNew == str)
{
rep = true;
break;
}
}
if (!rep) al.Add(strNew);
}
al.Sort();
return al;
}
我们建立一个arraylist然后把上面的正则传到这个方法里,返回的就是这个页面中所有a标记中的链接了,哈哈,好,我来调用一下。
ArrayList hrefStr = new ArrayList();
hrefStr =GetHyperLinks(str, @”href=s*[""']?S*[s""']?”);
在这里我要说明另一个问题,如果你不是想替换成空链接,那就用自己网站中页面转接的方法来解决这个问题,比如我TV150的网站,我想用href.tv150.cn这个域名给页面中的链接做跳转。
比如我页面中出现了www.baidu.com 这样的链接,那么我不给他替换成空,我给他替换成http://href.tv150.cn/?url=http://www.baidu.com
这样的话,链接还是可以打开的,但是对于网站优化影响不大,所以这种方法很好,嘿嘿。
哦,对了,在告诉你一个更完美的地方,如果你是本网站的链接那就不要替换,那岂不是更人性化。所以在代码中加入判断
我的代码:if (updateUrl.IndexOf(“tv150.cn”) < 0) 如果是tv150的内部链接,那就不替换了,哈哈,还为自己站内链接做了优化,真是不错啊。
如果你要替换成空,那就直接替换成#好了,一点也不影响其它的属性。
好了,关于网页中链接的问题基本已经全说完了,有问题在下面给我留言,我看到后会挑着我会的回答的。 : )
谢谢大家关注我的文章,本文由宋健明原创,转载请务必注明此版权信息。
2009年12月6日新修订
经过近两天的观察发现以上代码有一个缺陷,当一个内容代码字符串中包含了两个同样的网址,而只有一个杠的区别的时候,如:
http://www.tv150.cn 和 http://www.tv150.cn/ 这两个网址其实是一个,但是以上的那个提取链接方法却并没有把这两个合并,而是当成了两个网址来处理,这样的话,就导致同样一个网址被替换两次,如果是跳转的话,就是两次跳转,所以说是非常不合理的,于是今天我把代码加以改进,代码如下:
/// <summary>
/// 提取页面的超级链接或其它指定字符返回ArrayList
/// </summary>
/// <param name=”StrCode”>源字符串</param>
/// <param name=”strRegex”>正则表达式</param>
/// <returns></returns>
public static ArrayList GetHyperLinks(string StrCode, string strRegex)
{
ArrayList al = new ArrayList();
Regex r = new Regex(strRegex, RegexOptions.IgnoreCase);
MatchCollection m = r.Matches(StrCode);
for (int i = 0; i <= m.Count – 1; i++)
{
bool rep = false;
string strNew = m[i].ToString().Trim();
//如果网址后面有斜杠用此方法替换
if (strNew.Length > 3)
{
string lastStrif = strNew.Substring(strNew.Length – 1, 1);
if (lastStrif == “/”)//判断最后一个字符是否为/
{
strNew = strNew.Substring(0, strNew.Length – 1);
}
else
{
if (lastStrif == “”" || lastStrif == “‘”)
{
strNew = strNew.Substring(0, strNew.Length – 1);
if (strNew.Substring(strNew.Length – 1, 1) == “/”)
{
strNew = strNew.Substring(0, strNew.Length – 1);
}
}
}
}
//替换结束
// 过滤重复的URL
foreach (string str in al)
{
if (strNew == str)
{
rep = true;
break;
}
}
if (!rep) al.Add(strNew);
}
al.Sort();
return al;
}
在方法的中间加上了这么一段代码:
//如果网址后面有斜杠用此方法替换
if (strNew.Length > 3)
{
string lastStrif = strNew.Substring(strNew.Length – 1, 1);
if (lastStrif == “/”)//判断最后一个字符是否为/
{
strNew = strNew.Substring(0, strNew.Length – 1);
}
else
{
if (lastStrif == “”" || lastStrif == “‘”)
{
strNew = strNew.Substring(0, strNew.Length – 1);
if (strNew.Substring(strNew.Length – 1, 1) == “/”)
{
strNew = strNew.Substring(0, strNew.Length – 1);
}
}
}
}
//替换结束
代码解释:用这段代码来判断最后一个字符是不是/ 因为我的正则表达式也是匹配单引号和双引号的,所以如果倒数第一个字符不是的话,还要去判断倒数第二个。
截取判断的前提是提取的内容一定要大于2或3,不然的话会报错,所以加上了if (strNew.Length > 3) 判断。
OK,这样的话,同一个网址就不会被替换两次了,好了就这样,如果再遇到其它问题我会在这篇文章中继续修改代码。