class Tag

 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;
  }
 }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值