www.pudn.com > Crawler_bemjh.rar > ParseHTML.cs


using System; 
using System.Collections; 
using System.Text; 
 
namespace CrawlerLib 
{ 
	///  
	///  
	///  
	public class Tag 
	{ 
		//标记名称 
		private string m_TagName=""; 
		//标记后的文本内容 
		private string m_FollowedText=""; 
		//标记内的属性列表 
		private ArrayList m_TagAttributes=new ArrayList(); 
		///  
		/// 标记名称属性 
		///  
		public string TagName 
		{ 
			set 
			{ 
				m_TagName=value; 
			} 
			get 
			{ 
				return m_TagName; 
			} 
		} 
		///  
		/// 当前标记后的文本内容 
		///  
		public string FollowedText 
		{ 
			set 
			{ 
				m_FollowedText=value; 
			} 
			get 
			{ 
				return m_FollowedText; 
			} 
		} 
		///  
		/// 标记内的属性列表,类型为Attribue类的列表 
		///  
		public ArrayList TagAttributes 
		{ 
			set 
			{ 
				m_TagAttributes=value; 
			} 
			get 
			{ 
				return m_TagAttributes; 
			} 
		} 
	} 
	///  
	/// Summary description for ParseHTML. 
	///  
	/// This spider is copyright 2003 by Jeff Heaton. However, it is 
	/// released under a Limited GNU Public License (LGPL). You may  
	/// use it freely in your own programs. For the latest version visit 
	/// http://www.jeffheaton.com. 
	/// 
	///  
	public class ParseHTML:Parse  
	{
		//获取当前tag的名称
		protected string GetTagName()
		{
			return m_tag;
		}
		protected AttributeList GetTag()
		{
			AttributeList tag = new AttributeList();
			tag.Name = m_tag;
			
			foreach(Attribute x in List)
			{
				tag.Add((Attribute)x.Clone());
			}
			
			return tag;
		}

		protected void ParseTag()
		{
			//初始化m_tag,并且将AttributeList(ArrayList)清空
			m_tag="";
			Clear();

			// 如果后三个字符是注释标记
			if ((GetCurrentChar()=='!') &&
				(GetCurrentChar(1)=='-')&&
				(GetCurrentChar(2)=='-'))  
			{
				while ( !Eof() )  
				{
					//如果后三个字符是注释结束标记,则结束识别
					if ((GetCurrentChar()=='-') &&
						(GetCurrentChar(1)=='-')&&
						(GetCurrentChar(2)=='>'))
						break;
					//否则,一直向前,直到遇到>
					Advance();
				}
				//后移三个字符-->
				Advance(3);
				//分隔符置空
				ParseDelim = (char)0;
				return;
			}
			//如果遇到Style标记
			if( (char.ToUpper(GetCurrentChar()) == 'S') &&
				(char.ToUpper(GetCurrentChar(1)) == 'T') &&
				(char.ToUpper(GetCurrentChar(2)) == 'Y') &&
				(char.ToUpper(GetCurrentChar(3)) == 'L') &&
				(char.ToUpper(GetCurrentChar(4)) == 'E') )
			{
				while( !Eof())
				{
					//向前移动字符,直到遇到标记
					if( char.ToUpper(GetCurrentChar()) == '/'  && 
						char.ToUpper(GetCurrentChar(1)) == 'S' &&
						char.ToUpper(GetCurrentChar(2)) == 'T' &&
						char.ToUpper(GetCurrentChar(3)) == 'Y' &&
						char.ToUpper(GetCurrentChar(4)) == 'L')
						break;
					Advance();
				}
				//后移8个字符"/STYLE>"
				Advance(7);
				ParseDelim = (char)0;
				return;
			}
			//如果遇到Script标记,之间的内容丢弃
			if( (char.ToUpper(GetCurrentChar()) == 'S') &&
				(char.ToUpper(GetCurrentChar(1)) == 'C') &&
				(char.ToUpper(GetCurrentChar(2)) == 'R') &&
				(char.ToUpper(GetCurrentChar(3)) == 'I') &&
				(char.ToUpper(GetCurrentChar(4)) == 'P') &&
				(char.ToUpper(GetCurrentChar(5)) == 'T') )
			{
				while( !Eof())
				{
					//向前移动字符,直到遇到标记
					if( char.ToUpper(GetCurrentChar()) == '/'  && 
						char.ToUpper(GetCurrentChar(1)) == 'S' &&
						char.ToUpper(GetCurrentChar(2)) == 'C' &&
						char.ToUpper(GetCurrentChar(3)) == 'R' &&
						char.ToUpper(GetCurrentChar(4)) == 'I')
						break;
					Advance();
				}
				//后移8个字符/SCRIPT>
				Advance(8);
				ParseDelim = (char)0;
				return;
			}
			
			//对普通标记,一直读到>或\r\t\n及空格标记
			while ( !Eof() )  
			{
				//如果遇到\t\n\r空格或>,标记识别完成,退出循环
				if ( IsWhiteSpace(GetCurrentChar()) || (GetCurrentChar()=='>') )
					break;
				
				//否则,顺次读取标记字符,并向移动字符
				m_tag+=char.ToUpper(GetCurrentChar());
				Advance();
			}
			//跳过后面的所有\r\n\t及空格
			EatWhiteSpace();
			
			// 读取Tag后的属性
			while ( GetCurrentChar() != '>' && !Eof())  
			{
				ParseName = "";
				ParseValue = "";
				ParseDelim = (char)0;
				//分析属性名
				ParseAttributeName();
				//如果当前字符是">",则将属性添加到列表中,并结束当前标记解析
				if ( GetCurrentChar()=='>' )  
				{
					AddAttribute();
					break;
				}
				//尚未遇到>前,解析属性值
				ParseAttributeValue();
				AddAttribute();
			}
			Advance();
		}

		///  
		/// HTML字符解析 
		///  
		/// 
		protected char Parse()
		{
			if( GetCurrentChar()=='<' )  
			{
				//如果获取的字符是"<",发现了Tag,前进一个字符,并开始Tag分析
				Advance();
				char ch=char.ToUpper(GetCurrentChar());
				//如果获取的字符是A-Z或者!或者/,则解析Tag标记 
				if ( (ch>='A') && (ch<='Z') || (ch=='!') || (ch=='/') )  
				{
					ParseTag();
					return (char)0;
				}  
					//若当前字符不是A-Z或/则直接返回当前字符 
				else 
					return(AdvanceCurrentChar());
			}  
				//对于一般字符,直接将其返回 
			else 
				return(AdvanceCurrentChar());
		} 
		///  
		/// HTML文档解析,结果是一个Tag列表集合 
		///  
		/// Tag列表集合 
		public ArrayList Parsing()
		{
			ArrayList tags = new ArrayList();
			StringBuilder tagText = new StringBuilder();
			Tag newTag = new Tag();
			while(!Eof())
			{
				//顺次解析每个字符
				char ch = Parse();
				//如果ch返回0,表示发现一个新的Tag标记
				if(ch==0)
				{
					//如果有文本内容,或者虽无文本内容,但有实际标记
					if(tagText.Length>0 || newTag.TagName != "")
					{
						newTag.FollowedText = tagText.ToString();
						tags.Add(newTag);
						tagText = new StringBuilder();
					}
					
					//则新产生一个Tag对象,将当前标记赋予新标记
					newTag = new Tag();
					string tagName = GetTagName();
					newTag.TagName = tagName;
					newTag.TagAttributes = (ArrayList)List.Clone();
				}
				else
				{
					//如果遇到空格标记( )前行5个字符并返回
					//ch=&,当前字符是n,后续字符是bsp;
					if( ch == '&' &&
						GetCurrentChar() =='n' &&
						GetCurrentChar(1) =='b' &&
						GetCurrentChar(2) =='s' &&
						GetCurrentChar(3) =='p' &&
						GetCurrentChar(4) ==';' )
					{
						Advance(5);
						continue;
					}
					if("\r\n\t ".IndexOf(ch) == -1)
						tagText.Append(ch);
				}
			}
			//如果最后遇到结束标记
			if(GetTagName() != null && GetTagName().StartsWith("/"))
			{
				//添加结束标记
				tags.Add(newTag);
				//如果结标记后还有文本,产生新标记,并将剩余文本写入空标记后
				if(tagText.Length>0)
				{
					newTag = new Tag();
					newTag.TagName = string.Empty;
					newTag.FollowedText = tagText.ToString();
					tags.Add(newTag);
				}
			}
			//如果没遇到任何标记,表明是纯文本
			//产生一空标记,并将文本写入空标记后
			if(tags.Count == 0  && tagText.Length>0)
			{
				newTag=new Tag();
				newTag.TagName="";
				newTag.FollowedText=tagText.ToString();
				tags.Add(newTag);
			}
			return tags;
		} 
	} 
}