实现站内关键词链接功能
2011-08-07 11:41 浅陌 阅读(952) 评论(3) 收藏 举报我是一个真正的刚入门的菜鸟,最近做了一个站内关键词链接的功能,着实锻炼了一把,下面就写一下我在开发时的想法和功能的实现,因为本人实在是菜的不行,所以代码很多地方肯定是有更加优化的地方,比如前段时间转载的正则表达式的完善,比如排序的方法等等,高手看了可以笑,但不要喷哈,求鼓励!
首先说一下这个功能的需求,其实是从数据库中读取已经设置好的数据,其中包括以下几个数据:
功能主要考虑优先这个关键词替换时的优先级别,比如中医和中医文化,他们的优先级分别是1和2,那么如果在文章中出现中医文化4个字的时候因为中医的优先级别比较高,所以只替换中医,而不替换中医文化,最后就是这样的效果中医文化,然后是替换次数,如果输入的是0则默认给文章中所有符合关键词加上链接,如果输入的是2,则给前两个关键词加入链接,这两个字段是我在实现功能时遇到的最大困难。
我的思路是:
1.先给读取出的数据进行优先级的排序,将优先级比较高的放在前面,优先级低的放在后面,优先级相同的按字符长度,长的放到前面;
2.查找此关键词出现的位置,并判断这个关键词所在的位置是否是再<a></a>和<img>标签内,目前主要针对这两个标签,因为我的正则表达式能力有限,网上找到的资料也没有很中意的,如果关键词在这些标签内被加入链接,那么这两个标签就会被破坏,所以被过滤掉,如果发现是再这两个标签内则记录下标签的启示位置和结束位置,这样就可以过滤掉这个关键词;
3.获取关键词出现在文章中的所有起始位置;
4.将第3步中记录的位置与第二步中的位置进行比较,如果出现位置在标签的范围内,则过滤掉,否则就用替换字符串将关键词替换成链接,当然,还要判断下替换的次数。
这样功能就基本实现了,下面来看下代码:
1 //这个方法就是我们要替换关键词的方法,content传的是文章内容
2 public static string SpliceString(string content)
3 {
4 IList<StandConnection> list = StandConnectionLogic.GetAllStandConnection();//这是我的读取数据库中关键词列表的方法
5 StandConnection tempsc =new StandConnection();//我们为了冒泡排序设置的临时关键词对象
6 //我们首先遍历关键词列表,用冒泡排序法(我知识范围内就会这一个排序)首先判断两个相邻关键词的长度,再判断是否互相包含,最后再判断关键词的优先级,将关键词排序成由高到低
7 for (int i =0; i < list.Count; i++)
8 {
9 for (int j =0; j < list.Count - i -1; j++)
10 {
11 if (list[j].Target.Length > list[j +1].Target.Length)
12 {
13 if (list[j].Target.Contains(list[j +1].Target))
14 {
15 if (list[j].Level > list[j +1].Level)
16 {
17 tempsc = list[j];
18 list[j] = list[j +1];
19 list[j +1] = tempsc;
20 }
21 }
22 }
23 elseif (list[j].Target.Length < list[j +1].Target.Length)
24 {
25 if (list[j +1].Target.Contains(list[j].Target))
26 {
27 if (list[j].Level >= list[j +1].Level)
28 {
29 tempsc = list[j];
30 list[j] = list[j +1];
31 list[j +1] = tempsc;
32 }
33 }
34 }
35 else
36 {
37 if (list[j].Target.Contains(list[j +1].Target))
38 {
39 if (list[j].Level > list[j +1].Level)
40 {
41 tempsc = list[j];
42 list[j] = list[j +1];
43 list[j +1] = tempsc;
44 }
45 }
46 }
47 }
48 }
49 //这里最后再根据优先级排序依次得到最后的排序好的关键词列表
50 for (int i =0; i < list.Count; i++)
51 {
52 for (int j =0; j < list.Count - i -1; j++)
53 {
54 if (list[j].Level > list[j +1].Level)
55 {
56 tempsc = list[j];
57 list[j] = list[j +1];
58 list[j +1] = tempsc;
59 }
60 }
61 }
62 string str = content;
63 //然后我们遍历已经排序好的关键词
64 for (int i =0; i < list.Count; i++)
65 {
66 List<int> foundlist =new List<int>();//这里存放关键词的出现起始位置
67 List<int> htmllist =new List<int>();//这里存放包含了关键词的<a></a>和<img>标签的起始位置和结束位置
68 int count =0;//这是存放关键词出现次数的变量
69 FoundHtml(content, content, 0, ref htmllist);//这个方法实现第二步
70
71 Found(content, list[i].Target, -1, 0, htmllist, ref foundlist, ref count);//这个方法实现第三步
72 if (count >0)
73 {
74 //这里判断一下替换次数是否为0或者替换次数大于出现的次数,如果是true的话那么就替换掉所有出现的符合过则的关键词
75 if (list[i].MaxCount ==0|| list[i].MaxCount > count)
76 {
77 for (int j =0; j < count; j++)
78 {
79 //这里是第一个关键词出现位置,截取出来,截取的是从第0位置到第一个关键词出现的位置,然后加上要替换的字符串
80 if (j ==0)
81 {
82 str = content.Substring(0, foundlist[j]) +"<a href='"+ list[i].Url +"' target='"+ list[i].OpenType +"' title='"+ list[i].Title +"' class='back3'>"+ list[i].Target +"</a>";
83 }
84 //下面的截取就是从上一个关键词的起始位置+起始位置的长度开始,截取长度为本次关键词的起始位置减去上一个关键词的起始位置再减去本次关键词的长度,最后再加上要替换的字符串,注意这里的str是+=
85 else
86 {
87 str += content.Substring(foundlist[j -1] + list[i].Target.Length, foundlist[j] - foundlist[j -1] - list[i].Target.Length) +"<a href='"+ list[i].Url +"' target='"+ list[i].OpenType +"' title='"+ list[i].Title +"' class='back3'>"+ list[i].Target +"</a>";
88 }
89 }
90 str += content.Substring(foundlist[count -1] + list[i].Target.Length);
91 content = str;
92 }
93 else
94 {
95 for (int j =0; j < list[i].MaxCount; j++)
96 {
97 if (j ==0)
98 {
99 str = content.Substring(0, foundlist[j]) +"<a href='"+ list[i].Url +"' target='"+ list[i].OpenType +"' title='"+ list[i].Title +"' class='back3'>"+ list[i].Target +"</a>";
100 }
101 else
102 {
103 str += content.Substring(foundlist[j -1] + list[i].Target.Length, foundlist[j] - foundlist[j -1] - list[i].Target.Length) +"<a href='"+ list[i].Url +"' target='"+ list[i].OpenType +"' title='"+ list[i].Title +"' class='back3'>"+ list[i].Target +"</a>";
104 }
105 }
106 //都替换完后将剩下的字符也加进去,就成了替换好的了
107 str += content.Substring(foundlist[list[i].MaxCount -1] + list[i].Target.Length);
108 //然后更新一下内容,因为替换后的文章内容长度已经改变了
109 content = str;
110 }
111 }
112 }
113 return str;
114 }
115 //这里实现第三步
116 privatestaticvoid Found(string content, string target, int found, int a, List<int> htmllist, ref List<int> foundlist, refint count)
117 {
118 //这里的a是为了获得完整的关键词出现位置,因为IndexOf只能获取第一个符合的位置,所以要把前面已经找到的关键词截取掉,后来想一想这个情况想复杂了,起始只要替换掉关键词再查找就可以了,时间问题没有改过来。
119 if (found ==-1)
120 a =0;
121 else
122 a += found + target.Length;
123 found = content.IndexOf(target);
124 if (found !=-1)
125 {
126 //如果有出现过在标签内的关键词则进行比较,如果出现了则c++,如果c依然为0则可以将这个关键词的位置加入foundlist中了
127 if (htmllist.Count >0)
128 {
129 int c =0;
130 for (int i =0; i < htmllist.Count -1; i +=2)
131 {
132 if ((htmllist[i] < found + a) && (htmllist[i +1] > (found + a)))
133 {
134 c++;
135 }
136 }
137 if (c ==0)
138 {
139 count++;
140 foundlist.Add(found + a);
141 }
142 }
143 else
144 {
145 count++;
146 foundlist.Add(found + a);
147 }
148 //最后将前面查到的关键词截取掉,取后面的部分调用这个方法继续查找位置
149 content = content.Substring(found + target.Length).ToString();
150 Found(content, target, found, a, htmllist, ref foundlist, ref count);
151 }
152 }
153 //这里实现第二步
154 privatestaticvoid FoundHtml(string content, string str, int length, ref List<int> htmllist)
155 {
156 //因为我对正则真的一窍不通,所以只简单的判断了下<a></a>和<img>,strExp2和strExp4是为了获取标签出现位置的正则表达式
157 string strExp =string.Format(@"<a.+?>(?<Text>[^<]*)</a>");
158 string strExp2 =string.Format(@"^<a.+?>(?<Text>[^<]*)</a>");
159 string strExp3 =string.Format(@"<img.+?>");
160 string strExp4 =string.Format(@"^<img.+?>");
161
162 string str2 = str;
163 string str3 = str;
164 Regex re =new Regex(strExp);
165 Regex re2 =new Regex(strExp2);
166
167 Regex re3 =new Regex(strExp3);
168 Regex re4 =new Regex(strExp4);
169 //下面就各位自己看一下吧,主要还是通过各种截取和自调用来获取这些包含关键词的标签的起始位置和结束位置
170 str2 = re.Replace(str2, "", 1);
171 if (str2.Length == str.Length)
172 {
173 str2 = re3.Replace(str2, "", 1);
174 if (!(str2.Length == str.Length))
175 {
176 for (int i =0; i < str3.Length; i++)
177 {
178 if (re4.IsMatch(str3))
179 {
180 htmllist.Add(i + length);
181 htmllist.Add(i + length + str.Length - str2.Length);
182 FoundHtml(content, str2, content.Length - str2.Length, ref htmllist);
183 break;
184 }
185 else
186 {
187 str3 = str3.Substring(1);
188 }
189 }
190 }
191 }
192 else
193 {
194 for (int i =0; i < str3.Length; i++)
195 {
196 if (re2.IsMatch(str3))
197 {
198 htmllist.Add(i + length);
199 htmllist.Add(i + length + str.Length - str2.Length);
200 FoundHtml(content, str2, content.Length - str2.Length, ref htmllist);
201 break;
202 }
203 else
204 {
205 str3 = str3.Substring(1);
206 }
207 }
208 }
209 }
本人技术比较菜,代码整理的不是很好,注释添加的比较仓促,也比较繁琐杂乱,让大家见笑了,其实主要就是分享一下自己的努力成果,觉得各种判断和截取获取位置也废了自己不少的精力,做出来还是很高兴的。