asp html解析,自己写的,通过测试。

    最近写一个采集程序,然后就想到了通用分析网页再采集数据的方法,通过几天的摸索终于写出来了,与博客园的各位分享。

    欢迎测试,欢迎指正,欢迎评论。

  1 <%  

  2 ' asp html解析

  3 ' 
  4 ' by 吴烈 xWorker.cn
  5 ' 保留所有权利。不得用于商业用途,只能作为个人学习参考。
  6 ' 
  7 '===========================================================================================
  8 '===========================================================================================
  9 '===============                        处理函数                     ==============================
 10 
 11 '--------------------------------------------
 12 ' 清除注释
 13 function clearAnnotate(str)
 14     dim re
 15     set re = New RegExp
 16     re.Global = True
 17     re.IgnoreCase = True
 18     re.Pattern = "\<!--.*-->"
 19     clearAnnotate = re.Replace(str,""
 20 end function
 21 
 22 '--------------------------------------------
 23 ' 字符串转换成单字数组
 24 
 25 function string2CharArray(str)
 26     markDoubleChar = false ' 用来标识处理双字节
 27     nIndex = 0 ' 有效字符编号   
 28     n = 0 ' 双字节数目
 29     for i = 1 to len(str)
 30         chrA = mid(str, i, 1)
 31         if Asc(chrA) < 0 or Asc(chrA) > 255 then
 32             ' 写入双字节
 33             redim preserve sChar(nIndex + 1)
 34             sChar(nIndex) = Mid(str, i, 1)
 35             
 36             ' 写入双字节标识
 37             redim preserve tChar(nIndex + 1)
 38             tChar(nIndex) = 2
 39             
 40             ' 增长索引号
 41             nIndex = nIndex + 1
 42             
 43             '标识中文
 44             n = n + 1
 45         else
 46             ' 写入单字节
 47             redim preserve sChar(nIndex + 1)
 48             sChar(nIndex) = Mid(str, i, 1)
 49             
 50             ' 写入单字节标识
 51             redim preserve tChar(nIndex + 1)
 52             tChar(nIndex) = 1
 53             
 54             ' 增长索引号
 55             nIndex = nIndex + 1
 56         end if
 57     next
 58     
 59     '==========================================================================================================
 60     ' 调试输出
 61     if bDEBUG then
 62     ' 输出调试
 63     response.write "sChar个数:" & ubound(sChar) & "<br />"
 64     response.write "中文个数:" & n & "<br />"
 65         for i = 0 to (ubound(sChar) - 1' 参见注意1
 66             response.write "tChar(" & i & ")       字节数: " & tChar(i) & "    |   字符: " & sChar(i) & "    |   Acsii编码十进制: " & Asc(sChar(i)) & "<br />" & vbCrlf
 67         next
 68     end if
 69     
 70 end function
 71 
 72 '--------------------------------------------
 73 ' 解析html, 生成多个有关系的数组
 74 function htmlParse()
 75     m =0
 76     do
 77         ch = GetCurrentChar()
 78         '开始判断
 79         if ch = "<" then
 80             ch = getNextChar()
 81             ascCh = Asc(ch)
 82             if (ascCh >= Asc("A")) and (ascCh <= Asc("z")) then
 83                 ' 这样才是开始标签  <div
 84                 if newNode() <> 0 then '记录开始点, 这是"<"的位置
 85                     ' 出错了
 86                 end if
 87             end if
 88         elseif ch = "/" then
 89             ch = getNextChar()
 90             ascCh = Asc(ch)
 91             if (ascCh >= Asc("A")) and (ascCh <= Asc("z")) then
 92                 ' 这样才是结束标签  /div>
 93                 ' 注意: 不能排除text/css
 94                 if closeNode() <> 0 then '记录开始点, 这是"/"的位置
 95                     ' 出错了
 96                 end if
 97             end if
 98         else
 99             ' 在创建和关闭过程中自动获取标签内部文字
100         end if
101         m = m + 1
102     loop while moveNext()
103     
104     
105     
106     '==================================================================================================
107     ' 调试输出
108     if bDEBUG then
109     ' 输出调试    
110     response.write "循环" & m & "次<br />" & vbCrLf
111     end if
112     '==========================================================================================
113     ' 调试输出
114     if not bDEBUG then
115     response.write "<br />" & vbCrLf & "tagInfo Array:" & "<br />" & vbCrLf & "<br />" & vbCrLf
116         for i = 0 to (ubound(tagInfo) - 1)
117             
118             response.write i & ": tagInfo(" & i  & ") 自动编号: " & tagInfo(i)(0& " 标签名称: " & tagInfo(i)(1& " 标签类型: "& tagInfo(i)(2& " 层次号: "& tagInfo(i)(3& " 标签文字1: "& tagInfo(i)(4& " 标签文字2: " & tagInfo(i)(5& "<br />" & vbCrLf
119         next
120     end if
121  
122 end function
123 
124 '--------------------------------------------
125 '获取当前单字
126 function getCurrentChar()
127     getCurrentChar = sChar(index)
128 end function
129 
130 '--------------------------------------------
131 '获取下一个单字
132 function getNextChar()
133     n = index + 1
134     getNextChar = sChar(n)
135 end function
136 
137 '--------------------------------------------
138 '获取单字
139 function getChar(nIndex)
140     getChar = sChar(nIndex)
141 end function
142 
143 '--------------------------------------------
144 ' 移动标识
145 function moveNext()
146     if index < nCharCount then
147         index = index + 1
148         moveNext = true
149     else
150         moveNext = false
151     end if
152 end function
153 
154 '--------------------------------------------
155 ' 移动标识到 nIndex
156 function moveTo(nIndex)
157     if nIndex < nCharCount then
158         index = nIndex
159         moveTo = true
160     else
161         moveTo = false
162     end if
163 end function
164 
165 '--------------------------------------------
166 ' 是否是尾部
167 function isEOF()
168     if index < nCharCount then
169         isEOF = true
170     else
171         isEOF = false
172     end if
173 end function
174 
175 '--------------------------------------------
176 ' 时候是双字节
177 function isDoubleChar()
178     if tChar(index) = 2 then
179         isDoubleChar = true
180     else
181         isDoubleChar = false
182     end if
183     
184     '===================================================================================================
185     ' 调试输出
186     sDEBUG = true
187     if sDEBUG then
188     ' 输出调试    
189     response.write "tChar(" & index & ") 字节数:" & tChar(index) & "<br />" & vbCrLf
190     end if
191 end function
192 
193 '--------------------------------------------
194 ' 新建一个节点,并返回详细信息
195 function newNode()
196     ' 新建标签
197     newTagReturn = newTag()
198     if 0 <> newTagReturn then
199         newNode = newTagReturn
200         ' 第一步出错,
201     end if   
202 end function
203 
204 '--------------------------------------------
205 ' 关闭一个节点,并返回详细信息
206 function closeNode()
207     ' 新建标签
208     closeTagReturn = closeTag()
209     if 0 <> closeTagReturn then
210         closeNode = closeTagReturn
211         ' 第一步出错,不是结束标签
212     end if
213 end function
214 
215 '--------------------------------------------
216 ' 新建一个标签,并返回详细信息
217 function newTag()
218     ' 1 检查是否存在标签
219     ' 2 存储标签,并且移动标识到标签前部的末端 <td width="311" height="80" background="../images/title/330400.gif">
220     ' 3 标识当前父标签
221     ' 获取标签名称
222     tagName = getTagNameL()
223     tagNameLen = Len(tagName)
224     if isInTagNameArrayA(tagName) then ' 需配对的标签
225         ' 移动标识到标签左边末端
226         moveToTagLeftSide()
227         
228         ' 写入tagInfo
229         redim preserve tagInfo(tagInfoIndex + 1)
230         tagInfo(tagInfoIndex) = Array(tagInfoIndex, tagName, "A", nodeUin, getTagTextL(), "")
231         ' 0   自动编号
232         ' 1   标签名称
233         ' 2   标签类型 A 或者 B
234         ' 3   层次号
235         ' 4   标签文字1
236         ' 5   标签文字2
237         tagInfoIndex = tagInfoIndex + 1
238         
239         ' 写入 tempList 临时队列,一边配对 
240         redim preserve tempList(tempListIndex + 1)
241         tempList(tempListIndex) = Array(tagInfoIndex - 1, tagName)
242         '   标签编号
243         '   标签名称
244         tempListIndex = tempListIndex + 1
245         
246         ' 层结构加1
247         nodeUin = nodeUin + 1
248     elseif isInTagNameArrayB(tagName) then ' 不需配对的标签
249         ' 移动标识到标签左边末端
250         moveToTagLeftSide()
251         
252         ' 写入tagInfo
253         redim preserve tagInfo(tagInfoIndex + 1)
254         tagInfo(tagInfoIndex) = Array(tagInfoIndex, tagName, "B", nodeUin, """")
255         '0   自动编号
256         '1   标签名称
257         '2   标签类型 A 或者 B
258         '3   层次号
259         '4   标签文字1
260         '5   标签文字2
261         tagInfoIndex = tagInfoIndex + 1
262         
263         ' 层结构不变
264     else
265         ' 标签名不存在
266         response.Write "标签名: " & tagName & " 不存在 <br />" & vbCrLf
267     end if
268     
269     ' 返回
270     newTag = 0
271     
272     
273     '==========================================================================================
274     ' 调试输出
275     if bDEBUG then
276         response.write index  & " : " & tagName & " len: " & Len(tagName) & "<br />" & vbCrLf
277         i = tagInfoIndex - 1
278         response.write " tagInfo(" & i  & ") 自动编号: " & tagInfo(i)(0& " 标签名称: " & tagInfo(i)(1& " 标签类型: "& tagInfo(i)(2& " 父节点编号: "& tagInfo(i)(3& " 标签文字1: "& tagInfo(i)(4& " 标签文字2: " & tagInfo(i)(5& "<br />" & vbCrLf
279     end if
280 end function
281 
282 '--------------------------------------------
283 ' 关闭一个标签,并返回详细信息
284 function closeTag()
285     ' 1 检查是否存在标签
286     ' 2 存储标签,并且移动标识到标签前部的末端 <td width="311" height="80" background="../images/title/330400.gif">
287     ' 3 标识当前父标签
288 
289     ' 没有A标签
290     if nodeUin = 0 then
291         closeTag = 2
292         exit function
293     end if
294     ' 标签名称
295     tagNameR = getTagNameR()
296     ' 排除text/css的情况,再次确认是否是结束标签
297     if not (isInTagNameArrayA(tagNameR) or isInTagNameArrayB(tagNameR)) then
298         closeTag = 1
299         exit function
300     end if
301     ' 获得标签内部右边的文字
302     tagTextR = getTagTextR()
303     ' 移动标识到末端 当前/ 移动到 >  /div>
304     moveTo(index + Len(tagNameR) + 1)
305     ' 获取标签id
306     tagId = 0
307     for i = (ubound(tempList) - 1to 0 step -1
308         if tempList(i)(1= tagNameR then
309             tagId = tempList(i)(0)
310             ' 更改 tempList 记录
311             tempList(i)(1= "NullTagName"
312             ' 减小层结构数
313             nodeUin = nodeUin - 1
314             exit for
315         end if
316     next
317     
318     ' 比对左边文本,并写入
319     if tagInfo(tagId)(4<> tagTextR then
320        tagInfo(tagId)(5= tagTextR
321     else
322        tagInfo(tagId)(5= ""
323     end if
324     
325     
326 end function
327 
328 '--------------------------------------------
329 ' 获取一个标签名称(左边)
330 ' 标识位置: <
331 function getTagNameL()
332     n = 0
333     tTagName = ""
334     do while (isEOF() and n < 9)
335         ch = getChar(index + n + 1)
336         if ch = Chr(32or  ch = Chr(62then
337             for i = 1 to n
338                 tTagName = tTagName & sChar(index + i)
339             next
340             exit do
341         end if
342         n = n + 1
343     loop
344     getTagNameL = tTagName
345 end function
346 
347 '--------------------------------------------
348 ' 获取一个标签名称(右边)
349 ' 标识位置: /
350 function getTagNameR()
351     n = 0
352     tTagName = ""
353     do while (isEOF() and n < 9)
354         ch = getChar(index + n + 1)
355         if ch = Chr(62then
356             for i = 1 to n
357                 tTagName = tTagName & sChar(index + i)
358             next
359             exit do
360         end if
361         n = n + 1
362     loop
363     getTagNameR = tTagName
364 end function
365 
366 '--------------------------------------------
367 ' 移动标识到标签左边末端 
368 ' 当前标识: >
369 function moveToTagLeftSide()
370     n = 0
371     do while isEOF()
372         ch = getChar(index + n + 1)
373         if ch = ">" then
374             moveTo(index + n + 1)
375             moveToTagLeftSide = true
376             exit function
377         end if
378         n = n + 1
379     loop
380     '
381     moveToTagLeftSide = false
382 end function
383 
384 '--------------------------------------------
385 ' 是否是A标签(有配对的标签)
386 function isInTagNameArrayA(sTagName)
387     for each tagName in tagNameArrayA
388         if tagName = sTagName then
389             ' 找到就返回
390             isInTagNameArrayA = true
391             exit function
392         end if
393     next
394     ' 表示没有找到
395     isInTagNameArrayA = false
396 end function
397 
398 '--------------------------------------------
399 ' 是否是B标签(不需配对的标签)
400 function isInTagNameArrayB(sTagName)
401     for each tagName in tagNameArrayB
402         if tagName = sTagName then
403             ' 找到就返回
404             isInTagNameArrayB = true
405             exit function
406         end if
407     next
408     ' 表示没有找到
409     isInTagNameArrayB = false
410 end function
411 
412 '--------------------------------------------
413 ' 获得标签内部左边的文本
414 function getTagTextL()
415     ' 此时标识已经是末端了
416     n = 0
417     tTagText = ""
418     do while isEOF()
419         ch = getChar(index + n + 1)
420         if ch = Chr(60then
421             for i = 1 to n
422                 tTagText = tTagText & sChar(index + i)
423             next
424             exit do
425         end if
426         n = n + 1
427     loop
428     getTagTextL = tTagText
429 end function
430 
431 '--------------------------------------------
432 ' 获得标签内部右边的文本
433 function getTagTextR()
434     ' 此时标识已经是末端了
435     n = 0
436     tTagText = ""
437     do while isEOF()
438         ch = getChar(index - n - 1)
439         if ch = ">" then
440             for i = n to 2 step -1
441                 tTagText = tTagText & sChar(index - i)
442             next
443             exit do
444         end if
445         n = n + 1
446     loop
447     getTagTextR = tTagText
448 end function
449 
450 '--------------------------------------------
451 ' 是否是B标签()
452 function isInTagrayB(sTagName)
453 
454 end function
455 
456 '--------------------------------------------
457 ' 是否是B标签()
458 function isInTgNmeArrayB(sTagName)
459 
460 end function
461 
462 '--------------------------------------------
463 ' 是否是B标签()
464 function isInTagameArayB(sTagName)
465 
466 end function
467 
468 '--------------------------------------------
469 ' 使用FSO读取文件内容的函数
470 function FSOFileRead(filename) 
471     dim objFSO, objCountFile, FiletempData 
472     set objFSO = Server.CreateObject("Scripting.FileSystemObject"
473     set objCountFile = objFSO.OpenTextFile(Server.MapPath(filename), 1true
474     FSOFileRead = objCountFile.ReadAll 
475     objCountFile.Close 
476     set objCountFile = nothing 
477     set objFSO = nothing 
478 end function 
479 
480 
481 
482 
483 '===========================================================================================
484 '===========================================================================================
485 '=========================                          执行体                       ===============================
486 ' 一些设置
487 bDEBUG = false
488 
489 ' 注意这个文件
490 htmlStr = FSOFileRead("test.html")
491 
492 'htmlStr = "<meta http-equiv=""Content-Type"" content=""text/html; charset=gb2312""><html xmlns=""http://www.w3.org/1999/xhtml""><html><head><meta http-equiv=""Content-Type"" content=""text/html; charset=gb2312""><title>朱自成的个人简历-路桥技术/隧道工程·工民建·土建工程师 | 12年工作经验 | 大专 | 路桥 嘉兴人才招聘网</title><meta NAME=""keywords"" content=""嘉兴人才网,嘉兴人才招聘网,嘉兴人才市场,嘉兴招聘网,嘉兴人才网,嘉兴人才招聘网-打造嘉兴最好的人才招聘网站  口碑铸就人气!,http://www.0573hr.com.cn""><meta name=""description"" content=""嘉兴人才网,嘉兴人才招聘网,嘉兴人才市场,嘉兴招聘网,嘉兴人才网,嘉兴人才招聘网-打造嘉兴最好的人才招聘网站  口碑铸就人气!,http://www.0573hr.com.cn"" ><link href=""images/grjl.css"" rel=""stylesheet"" type=""text/css""></head><body><table width=""991"" border=""0"" cellspacing=""0"" cellpadding=""0""><tr><td width=""311"" height=""80"" valign=""bottom"" background=""../images/title/330400.gif""><table width=""275""  border=""0"" align=""right"" cellpadding=""0"" cellspacing=""0""><tr><td width=""266"" height=""35"" class=w>求职<b>嘉兴人才招聘网</b>--打造嘉兴最好的人才招聘网站</td></tr></table></td></tr></table><div>name</div></body></html>"
493 
494 '<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
495 '<html xmlns="http://www.w3.org/1999/xhtml">
496 '   <html>
497 '       <head>
498 '           <meta http-equiv="Content-Type" content="text/html; charset=gb2312">
499 '           <title>朱自成的个人简历-路桥技术/隧道工程·工民建·土建工程师 | 12年工作经验 | 大专 | 路桥 嘉兴人才招聘网</title>
500 '           <meta NAME="keywords" content="嘉兴人才网,嘉兴人才招聘网,嘉兴人才市场,嘉兴招聘网,嘉兴人才网,嘉兴人才招聘网-打造嘉兴最好的人才招聘网站  口碑铸就人气!,http://www.0573hr.com.cn">
501 '           <meta name="description" content="嘉兴人才网,嘉兴人才招聘网,嘉兴人才市场,嘉兴招聘网,嘉兴人才网,嘉兴人才招聘网-打造嘉兴最好的人才招聘网站  口碑铸就人气!,http://www.0573hr.com.cn" >
502 '           <link href="images/grjl.css" rel="stylesheet" type="text/css">
503 '       </head>
504 '       <body>
505 '           <table width="991" border="0" cellspacing="0" cellpadding="0">
506 '               <tr>
507 '                   <td width="311" height="80" valign="bottom" background="../images/title/330400.gif">
508 '                       <table width="275"  border="0" align="right" cellpadding="0" cellspacing="0">
509 '                           <tr>
510 '                               <td width="266" height="35" class=w>
511 '                                   求职
512 '                                   <b>
513 '                                       嘉兴人才招聘网
514 '                                   </b>
515 '                                   --打造嘉兴最好的人才招聘网站
516 '                               </td>
517 '                           </tr>
518 '                       </table>
519 '                   </td>
520 '               </tr>
521 '           </table>
522 '           <div>
523 '               name
524 '           </div>
525 '       </body>
526 '   </html>
527 
528 ' 1 网页字符串预处理
529 ' --------------------------------------------------------------------------------------------------
530 
531 ' 1.0   按行读取,清楚左边空格,再合并
532 tCharArray  = split(htmlStr, vbCrLf)
533 htmlStr = ""
534 for j = 0 to Ubound(tCharArray)
535     htmlStr = htmlStr + Trim(tCharArray(j))
536 next
537 ' 全部转换成小写
538 htmlStr = LCase(htmlStr)
539 ' 1.1   清除注释
540 htmlStr = clearAnnotate(htmlStr)
541 
542 response.write "经过处理后的htmlStr文字个数: " & Len(htmlStr) & "<br />" & vbCrLf
543 
544 ' 1.2   将字符串裁剪成单个字符,注意非英文的,并且记录是否是英文
545 dim sChar() ' 字符串单字数组
546 dim tChar() ' 记录单字是否为多字节
547 string2CharArray(htmlStr) ' 注意1: 这样最后下标的数组是空的
548 
549 
550 ' 2 生成html标签树
551 ' --------------------------------------------------------------------------------------------------
552 index = 0 ' 当前单字下标标识
553 nCharCount = ubound(sChar) - 1 ' 字符数 (实际  + 1)
554 nCurrentFatherTag = 0 ' 当前父标签下标,用来处理 <A>文本段1<B>文本段2</B>文本段3</A> 这样的情况
555 lastTagType = "A"
556 '有配对的标签
557 tagNameArrayA = Array("html""body""head""title""p""center""pre""div""nobr""wbr""strong""b""em""i""tt""u""h1""h2""h3""h4""""h5""h6""font""basefont""big""small""strike""code""kbd""samp""var""cite""blockquote""dfn""address""sub""sup""ol""ul""li""menu""dir""dl""dt""dd""table""caption""tr""td""th""form""textarea""input""select""option""a""frameset""iframe""noframes""map""marquee""blink""style""span")
558 '不需配对的标签
559 tagNameArrayB = Array("!doctype""br""hr""input""img""base""frame""area""bgsound""meta""link")
560 dim nodeInfo()
561 nodeInfoIndex = 0
562 ' 层次号
563 nodeUin = 0
564 nodeInfoID = 0
565 '   nodeInfo
566 '   自动编号
567 '   层数
568 '   子节点数
569 dim tagInfo()
570 tagInfoIndex = 0
571 tagInfoID =0
572 '   tagInfo
573 '   自动编号
574 '   标签名称
575 '   标签类型 A 或者 B
576 '   层次号
577 '   标签文字1
578 '   标签文字2
579 dim tempList()
580 tempListID = 0
581 tempListIndex = 0
582 '   tempList 临时队列
583 '   标签名称
584 
585 ' 解析html, 生成多个有关系的数组
586 htmlParse() 
587 %>


吴烈 倾情制作。

源代码下载 : https://files.cnblogs.com/wulie88/index.rar

posted @ 2008-11-06 23:30  吴烈  阅读(657)  评论(0编辑  收藏  举报