C#通过正则表达式实现提取网页中的图片
目前在做项目中有处理图片的部分,参考了一下网上案例,自己写了一个获取内容中的图片地址的方法。
一般来说一个HTML文档有很多标签,比如“<html>”、“<body>”、“<table>”等,想把文档中的img标签提取出来并不是一件容易的事。由于img标签样式变化多端,使提取的时候用程序寻找并不容易。于是想要寻找它们就必须写一个非常健全的正则表达式,不然有可能会找得不全,或者找出来的不是正确的img标签。
我们可以从HTML标签的格式去想应该怎么建这个正则表达式。首先要想一下img标签有几种写法,忽略大小写不看的话,下面列出img标签可能出现的几种情况。
<img><img/><imgsrc=/>
这一些标签不用考虑,因为没有图片资源地址。
<imgsrc=/images/pic.jpg/><imgsrc="/images/pic.jpg"><imgsrc='/images/pic.jpg'/>
这一些标签都有图片资源地址,另外还有一个特点就是有引号对,可能为单引号,也可能为双引号。因为不需要同时匹配引号对,所以正则表达式可以这么写:@"<img\s*src\s*=\s*[""']?\s*(?[^\s""'<>]*)\s*/?\s*>"
<imgwidth="320"height="240"src=/images/pic.jpgonclick="window.open('/images/pic.jpg')">
因为img和src之间可能会有其他的参数,所以“<img”要有个单词结束,比如说不能是“<imgabc”,同样src前面也是一样,使用单词结束符“\b”有一个好处就是省去了表示空格的“\s*”。另外由于img标签中不可以出现“<”、“>”这样的符号,所以要改写前面的正则表达式:@"<img\b[^<>]*?\bsrc\s*=\s*[""']?\s*(?<imgUrl>[^\s""'<>]*)[^<>]*?/?\s*>"
<imgwidth="320"height="240"src="
/images/pic.jpg"/>
像这种可能会用回车符折行的问题有时候会出现,所以在有空格分开的地方要包含回车换行和TAB字符,另外在图片地址中不能出现空格、TAB、回车和换行字符。
所以上面的正则表达式可以改成:@"<img\b[^<>]*?\bsrc[\s\t\r\n]*=[\s\t\r\n]*[""']?[\s\t\r\n]*(?<imgUrl>[^\s\t\r\n""'<>]*)[^<>]*?/?[\s\t\r\n]*>"
下面写出取得HTML中所有图片地址的类HvtHtmlImage:
usingSystem.Text.RegularExpressions; namespaceHoverTree.HoverTreeFrame.HvtImage { publicclassHvtHtmlImage { ///<summary> ///取得HTML中所有图片的URL。 ///</summary> ///<paramname="sHtmlText">HTML代码</param> ///<returns>图片的URL列表</returns> publicstaticstring[]GetHvtImgUrls(stringsHtmlText) { //定义正则表达式用来匹配img标签 Regexm_hvtRegImg=newRegex(@"<img\b[^<>]*?\bsrc[\s\t\r\n]*=[\s\t\r\n]*[""']?[\s\t\r\n]*(?<imgUrl>[^\s\t\r\n""'<>]*)[^<>]*?/?[\s\t\r\n]*>",RegexOptions.IgnoreCase); //搜索匹配的字符串 MatchCollectionmatches=m_hvtRegImg.Matches(sHtmlText); intm_i=0; string[]sUrlList=newstring[matches.Count]; //取得匹配项列表 foreach(Matchmatchinmatches) sUrlList[m_i++]=match.Groups["imgUrl"].Value; returnsUrlList; } } }
下面我们再来看一个例子
publicArrayMatchHtml(stringhtml,stringcom) { List<string>urls=newList<string>(); html=html.ToLower(); //获取SRC标签中的URL RegexregexSrc=newRegex("src=\"[^\"]*[(.jpg)(.png)(.gif)(.bmp)(.ico)]\""); foreach(MatchminregexSrc.Matches(html)) { stringsrc=m.Value; src=src.Replace("src=","").Replace("\"",""); if(!src.Contains("http")) src=com+src; if(!urls.Contains(src)) urls.Add(src); } //获取HREF标签中URL RegexregexHref=newRegex("href=\"[^\"]*[(.jpg)(.png)(.gif)(.bmp)(.ico)]\""); foreach(MatchminregexHref.Matches(html)) { stringhref=m.Value; href=href.Replace("href=","").Replace("\"",""); if(!href.Contains("http")) href=com+href; if(!urls.Contains(href)) urls.Add(href); } returnurls.ToArray(); }
[DllImport("kernel32.dll")] staticexternboolSetConsoleMode(IntPtrhConsoleHandle,intmode); [DllImport("kernel32.dll")] staticexternboolGetConsoleMode(IntPtrhConsoleHandle,outintmode); [DllImport("kernel32.dll")] staticexternIntPtrGetStdHandle(inthandle); constintSTD_INPUT_HANDLE=-10; constintENABLE_QUICK_EDIT_MODE=0x40|0x80; publicstaticvoidEnableQuickEditMode() { intmode;IntPtrhandle=GetStdHandle(STD_INPUT_HANDLE); GetConsoleMode(handle,outmode); mode|=ENABLE_QUICK_EDIT_MODE; SetConsoleMode(handle,mode); } staticvoidMain(string[]args) { EnableQuickEditMode(); intoldCount=0; Console.Title="TakeImageFromInternet"; stringpath="E:\\Download\\loading\\"; while(true) { Console.Clear(); stringcountFile="E:\\CountFile.txt";//用来计数的文本,以至于文件名不重复 intcursor=0; if(File.Exists(countFile)) { stringtext=File.ReadAllText(countFile); try { cursor=oldCount=Convert.ToInt32(text);//次数多了建议使用long } catch{} } Console.Write("pleaseinputaurl:"); stringurl="http://www.baidu.com/"; stringtemp=Console.ReadLine(); if(!string.IsNullOrEmpty(temp)) url=temp; Matchmcom=newRegex(@"^(?i)http://(\w+\.){2,3}(com(\.cn)?|cn|net)\b").Match(url);//获取域名 stringcom=mcom.Value; //Console.WriteLine(mcom.Value); Console.Write("pleaseinputasavepath:"); temp=Console.ReadLine(); if(Directory.Exists(temp)) path=temp; Console.WriteLine(); WebClientclient=newWebClient(); byte[]htmlData=null; htmlData=client.DownloadData(url); MemoryStreammstream=newMemoryStream(htmlData); stringhtml=""; using(StreamReadersr=newStreamReader(mstream)) { html=sr.ReadToEnd(); } Arrayurls=newMatchHtmlImageUrl().MatchHtml(html,com); foreach(stringimageurlinurls) { Console.WriteLine(imageurl); byte[]imageData=null; try { imageData=client.DownloadData(imageurl); } catch{} if(imageData!=null&&imageData.Length>0) using(MemoryStreamms=newMemoryStream(imageData)) { try { stringext=Aping.Utility.File.FileOpration.ExtendName(imageurl); ImageFormatformat=ImageFormat.Jpeg; switch(ext) { case".jpg": format=ImageFormat.Jpeg; break; case".bmp": format=ImageFormat.Bmp; break; case".png": format=ImageFormat.Png; break; case".gif": format=ImageFormat.Gif; break; case".ico": format=ImageFormat.Icon; break; default: continue; } Imageimage=newBitmap(ms); if(Directory.Exists(path)) image.Save(path+"\\"+cursor+ext,format); } catch(Exceptionex){Console.WriteLine(ex.Message);} } cursor++; } mstream.Close(); File.WriteAllText(countFile,cursor.ToString(),Encoding.UTF8); Console.WriteLine("takedone...imagecount:"+(cursor-oldCount).ToString()); } }