正则表达式在远程网页下载中的应用

摘  要:分析了远程网页的结构特征,阐述了正则表达式在网页下载中的应用,提出了运用正则表达式匹配替换多余HTML源文件和直接在HTML源文件中匹配提取元数据的两种获取远程数据的方法,同时完成了数据解析、提取及保存的整个过程,并将文章所附有的附件、图片及音频等文件下载到本地服务器。  
关键词: 正则表达式;元数据;字符串处理;匹配替换  
1 引言  
    目前,博客作为一种新型的交流平台,已广泛地应用于互联网中,然而,由于博客平台本身的特点,其数据大多为非线性,不便于转化为XML或PDF格式的文档,也给数据的扩充及存取带来了极大的不便。为了解决这种非线性数据自动转换为线性数据的问题。本文以敏思博客平台的教研创群组  http://jycbl.group.blogms.com/ )为例,采用正则表达式自动识别、解析远程网页数据的方法,专门开发了一个的博客网页下载软件。软件不但可以把博客文章的标题、作者、内容及评论等文字提取出来,而且还可以利用C#强大的文件处理功能,将文章所附有的附件、图片及音频等文件下载到本地服务器。  
2 正则表达式  
    正则表达式由美国数学家Stephen Kleene于1956年提出,主要用于描述正则集代数。现在,正则表达式标准已经成为ISO(国际标准化组织)的国际标准,已经被广泛地应用于字符格式匹配等信息技术领域。  
    正则表达式提供了一种从字符集合中搜寻特定字符串的机制[1]。它是由普通字符(例如字符a到z)以及特殊字符(称为元字符)组成的文字模式。该模式描述在查找文字主体时待匹配的一个或多个字符串。按照实现的功能集合分为两种:基本的正则表达式(BRE)和扩展的正则表达式(ERE)[2]。正则表达式已经超出了某种语言或某个系统的局限,成为人们广为接受的概念和功能。许多程序中都使用了正则表达式,如xsh、vi等UNIX平台下的程序。正则表达式还被很多其他规范所采纳,如HTML和XML。支持正则表达式的语言也很多,比如PHP 、C# 、JavaScript、VBScript、Perl等。  
    正则表达式最基本的三种功能是:匹配、替换和提取。使用匹配功能,可以把用特殊字符串表达的匹配模式与数据文件、程序输入或者WEB页面的表单输入等目标对象进行比较,根据比较结果,执行相应的程序。替换文本功能,用于在文档中使用匹配模式来标识特定文字,然后将其删除或进行替换。提取子符串功能,用于根据模式匹配,从字符串中提取一个子字符串。  
3 远程网页的特征以及结构分析  
    在应用正则表达式提取数据之前,必须对网页的结构进行详细的分析,根据网页的结构特征来构造最合适的正则表达式。下面列出要处理的远程网页的一部分源文件:  

   


    以上是一段描述一篇文章的标题、作者、发表日期、点击次数及回复次数的源文件,它是一种半结构化的格式[3],各元素之间用“<”和“>”分割开,现在所要做的就是将该文章的标题、作者及点击次数等信息从该源文件中提取出来。根据源文件的特征,通过观察判断,可以看出除了发表日期以外,其他所需要的信息如标题、作者、点击次数及回复次数都属于“<”和“>”之外的内容,故在提取这些信息时,只需要将“<”和“>”之内的源文件去除,剩下的就是所需要的信息。如对以上那段源文件,可以先利用网页里文章列表的开始标志“<!--Begin FCS: Blog.stdsub.TagGroupLog -->”和结束标志“<!-- End FCS:Blog.stdsub. TagCBlogLog Page -->”,进一步缩小信息提取的范围,然后构造正则表达式将多余的源文件去除,最后就可以得到以下的元数据:  
    文章标题:计算机族的眼睛保养  
    文章作者:叶子  
    点击次数及回复次数:12/2            
    对于文章的发表日期,元数据不在“<”和“>”之间而是做为单元格“title”属性一部分内容时,必须运用另一种提取方法,也就是构造正则表达式将匹配的数据直接提取出来,但运用正则表达式时,要尽可能的缩小源文件的范围,以提高正则表达式的匹配效率。  
4  正则表达式在远程网页下载中的应用  
    软件使用C#语言,运用Microsoft公司提供的SQL Server 2000作为数据库,第三方提供的正则表达式完成开发。提取元数据时,一般有两种提取方法:一种是将匹配的数据去除,剩下有用的数据;另一种就是将匹配的数据直接提取出来。  
    Microsoft的.Net Framework类库提供了System.Text.Regu larEx pressions命名空间,作为正则表达式的编程接口,它提供了Regex类、Match类及Group类等。  
    Regex类包含了正则表达式,以及使用正则表达式的各种方法。Regex类不仅可以用来创建正则表达式,还可以操作文本数据。例如:搜索字符模式或进行复杂的查找和替换。若要把正则表达式利用于不同的字符串,就可以创建一个Regex对象,其主要方法有IsMatch()方法、Replace()方法、Split()方法等。Replace()方法用指定的字符串代替一个匹配模式,Split()方法在每次发现匹配的位置分拆字符串,返回一个字符数组。Match类表示单个正则表达式匹配的结果。Group类表示单个捕获组的结果。  
    正则表达式主要有四类字符:首先是匹配字符,包含了需要搜索匹配的对象。例如,“.”号匹配任一字符,“[]”号匹配方括弧之间的任一字符,“[^]”号匹配不在方括弧之间的任一字符。其次是重复操作符,描述了查找一个特定字符的次数。例如,“?”号匹配某一部分一次,“*” 号匹配某一部分多次,“+”号匹配某一部分一次或多次,“[a]+”匹配一个或多个“a”字符,还有“{n}”,“{n,m}”等符号。第三种是锚,它指定了所要匹配的格式,有“^”、“$”、“/>”、“/<”、“b”等,当然还会有一些保留字符,需要用反斜杠来替换它们,比如“/”号,是个保留字符,如果要在表达式里表示这个特定的字符,就得用“// ”这种形式。  
4.1 运用正则表达式去除多余的源文件获取元数据  
    针对以上那段源文件,在提取文章标题、作者、点击次数及回复次数时使用正则表达式去除多余源文件的形式来提取数据。具体的提取过程以下:  
    第一步,构造正则表达式,去除多余的源文件。  
Regex R = new Regex(@"<[^>]*",RegexOptions.Ignore Case);  
string RText = R.Replace(NewText,"$").Replace(">","");  
“<[^>]*”表示匹配“<”与“>”之间的所有内容。“NewText”是待处理的字符串,R.Replace(NewText,"$")就是表示将所匹配的内容替换成“$”。  
    第二步,构造正则表达式,清除所有包括空格、制表符、换页符等空白字符。  
Regex R1 = new Regex(@"[/s]*",RegexOptions.Ignore Case);  
string R1Text = R1.Replace(RText,"");  
    第三步,构造正则表达式,将多个“$”替换成一个“$”,并清除头尾的“$”及源文件中的“$ ”,最后得到以“$”为分隔符的字符串,如“计算机族的眼睛保养$叶子$12/2”。   
Regex RR = new Regex("[$]+",RegexOptions.IgnoreCase);  
string RRText = RR.Replace(R1Text,"$").TrimStart($). TrimEnd($).Replace("$ ","");  
4.2 运用正则表达式从源文件中直接提取元数据  
    在运用正则表达式提取元数据之前,首先构造一个执行正则表达式提取元数据的函数GetUrlByReg(string InputStr,string RegStr,int GroupInt),此函数有三个参数,第一个为待处理的字符串,第二个是根据要筛选的字符串构造的正则表达式,第三个是指定返回的字符串数组匹配项的位置。函数算法思路是先用指定的正则表达式初始化一个Regex类的实例,再用Regex实例的Match()方法返回指定的字符串匹配的结果,同时这里初始化一个StringBuilder的实例,并将返回的字符串追加到该实例中,然后赋给字符串变量ReValue返回,具体如下:  
private string GetUrlByReg(string InputStr,string RegStr,int GroupInt)  
           {  
      //用修改模式的选项为指定的正则表达式初始化并编译 Regex 类的实例  
           Regex r = new Regex(RegStr,RegexOptions. Ignore Case);  
           //在指定的输入字符串中搜索Regex构造函数中指定的正则表达式匹配项  
           Match m = r.Match(InputStr);  
           //初始化一个StringBuilder实例,并将此实例的字符串值设置为 String.Empty  
           StringBuilder SB = new StringBuilder();  
           while(m.Success)  
{  
                             SB.Append(m.Groups[GroupInt].ToString());   
SB.Append("$");  //在每一个匹配项后追加一个“$”  
m = m.NextMatch();  
}  
string ReValue = SB.ToString();  //将实例字符串赋给ReValue  
SB.Remove(0,SB.ToString().Length);   
return ReValue;  
}  
    借助这个自定义函数,就可以构造一些正则表达式来提取所需要的元数据。如对于上面所附的那一段源文件中文章发表日期的获取就可以采用这种方式,应用如下:  
string TextTime = GetUrlByReg(NewText,@"(发表日期:)+(/d+(年)/d+(月)/d+(日)/s/d+(:)/d+)",2).TrimEnd($);  
    “NewText”为待提取的字符串,也就是以上所附的那一段源文件,第二个参数就是根据日期格式构造的正则表达式,“/d+”匹配一个或多个数字字符如“2006”,“/s”表示匹配一个空白字符,这样类似“2006年6月21日 7:35”的日期格式都可以被匹配。在本软件中,这方面应用的例子还有很多,如提取每个栏目访问地址、栏目名称、栏目ID号、内容中附有的图片名称等。以下为返回图片名称的一条正则表达式:  
    string img = GetUrlByReg(TextContent,@"(IMG SRC= /"")+([.]*(([//](/w+))*([.])(jpg|gif|bmp)))",2).Trim End($). TrimStart(.);//返回内容中图片名称  
仔细分析以上的正则表达式就知道,该正则表达式共有三个匹配项,第一个是“(IMG SRC=/"")”,其中这是一个固定的字符串匹配,匹配一个“IMG SRC="”的字符串,第二个是“[.]*”,意思是可以匹配零个或多个“.”号,第三个是“(([//](/w+))*([.])(jpg|gif|bmp))”,这个正则表达式前半部分“([//](/w+))*”表示匹配多组一个“/”加一个或多个单词的字符串,如“/abc/efg/picname”,后半部分“([.])(jpg|gif|bmp)”表示匹配一个“.”号加图片文件扩展名。通过分析知道,整个表达式可以匹配如“IMG SRC="../blogpath/03/ 1000353733.jpg"”类似的字符串。获取到图片的相对路径后,就可以利用C#的WebClient类的DownloadFile()方法将远程服务器上的数据下载到本地服务器。  
4.3 正则表达式的设计误区及思路  
    正则表达式的设计误区主要有以下几种。一是不能准确匹配。在设计匹配模式时,应充分明确各类字符的匹配意义,掌握常用的匹配技巧。例如“/S”表示匹配任何非空白字符,“/d”匹配一个数字字符,“/s”表示匹配任何空白字符等。二是思路不明确,碰到复杂的源文件无从下手。对于复杂的源文件,应该先寻找匹配的规律,化简后分而治之。例如上文提到的图片相对路径的匹配,可以先把路径源文件分为三个部分,分别设计三种匹配模式,然后再连接起来。三是文档范围过大,匹配效率低。正则表达式在匹配文档时是运用匹配模式与源文件逐一比较才得出匹配结果,效率相对较低,因此,在不影响匹配结果的情况下,尽可能的缩短被处理字符串的范围。另外,在对远程数据进行匹配时,最好在调试阶段先把数据下载到本机调试,这样开发的速度会快很多。构造匹配的正则表达式,也就是根据文档的结构特征,将相同或类似的信息归类,再用一系列的字符集抽象表示文档的过程。每一个正则表达式的构造都与所被处理的源文件的结构分不开的,所以在构造正则表达式之前,都必须对网页的结构特征进行详细的分析,找出规律,排除干扰,才能设计出最理想的正则表达式。   
4.4 数据库处理  
    数据库共有三个表,分别是群组基本信息表、文章相关信息表和评论表。群组基本信息表主要是保存群组栏目ID、栏目名称、群组名称和群组地址,文章相关信息表主要保存文章主题、内容、作者、发表时间、点击次数及评论次数等,评论表主要保存文章ID、评论主题、评论内容、Email、网址及评论人等。  
5 结束语  
    目前,这个软件已经下载了教研创群组7千多篇文章,3万多条文章评论,数据下载率在98%以上。一小部分文章未能下载是主要因为网页模板有所变化,或者网络中断,或者内容中含有特殊字符导致数据保存失败等原因造成的。  
    一个理想的匹配模式的设计,需要反复的实践,而且它要求与被处理网页的结构比较稳定、有规可循[4]。因此,该方法也有它的局限性,如智能化程序不够高,可移植性不够好等,但是,由于正则表达式强大的解析、匹配能力,以及得到越来越多的语言的支持,所以在今后的应用中,仍会有很广阔的前景。 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值