首页 > 编程 > C# > 正文

C#通过正则表达式实现提取网页中的图片

2020-01-24 01:20:47
字体:
来源:转载
供稿:网友

目前在做项目中有处理图片的部分,参考了一下网上案例,自己写了一个获取内容中的图片地址的方法。

 一般来说一个 HTML 文档有很多标签,比如“<html>”、“<body>”、“<table>”等,想把文档中的 img 标签提取出来并不是一件容易的事。由于 img 标签样式变化多端,使提取的时候用程序寻找并不容易。于是想要寻找它们就必须写一个非常健全的正则表达式,不然有可能会找得不全,或者找出来的不是正确的 img 标签。

我们可以从 HTML 标签的格式去想应该怎么建这个正则表达式。首先要想一下 img 标签有几种写法,忽略大小写不看的话,下面列出 img 标签可能出现的几种情况。
<img> <img/> <img src=/>

这一些标签不用考虑,因为没有图片资源地址。
<img src = /images/pic.jpg/ > <img src =" /images/pic.jpg" > <img src= '/images/pic.jpg ' / >

这一些标签都有图片资源地址,另外还有一个特点就是有引号对,可能为单引号,也可能为双引号。因为不需要同时匹配引号对,所以正则表达式可以这么写:@"<img/s*src/s*=/s*[""']?/s*(?[^/s""'<>]*)/s*/?/s*>"
<img width="320" height="240" src=/images/pic.jpg onclick="window.open('/images/pic.jpg')">

因为 img 和 src 之间可能会有其他的参数,所以“<img”要有个单词结束,比如说不能是“<imgabc”,同样 src 前面也是一样,使用单词结束符“/b”有一个好处就是省去了表示空格的“/s*”。另外由于 img 标签中不可以出现“<”、“>”这样的符号,所以要改写前面的正则表达式:@"<img/b[^<>]*?/bsrc/s*=/s*[""']?/s*(?<imgUrl>[^/s""'<>]*)[^<>]*?/?/s*>"
<img width="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:

using System.Text.RegularExpressions;namespace HoverTree.HoverTreeFrame.HvtImage{public class HvtHtmlImage{/// <summary> /// 取得HTML中所有图片的 URL。 /// </summary> /// <param name="sHtmlText">HTML代码</param> /// <returns>图片的URL列表</returns> public static string[] GetHvtImgUrls(string sHtmlText){// 定义正则表达式用来匹配 img 标签 Regex m_hvtRegImg = new Regex(@"<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);// 搜索匹配的字符串 MatchCollection matches = m_hvtRegImg.Matches(sHtmlText);int m_i = 0;string[] sUrlList = new string[matches.Count];// 取得匹配项列表 foreach (Match match in matches)sUrlList[m_i++] = match.Groups["imgUrl"].Value;return sUrlList;}}}

下面我们再来看一个例子

public Array MatchHtml(string html,string com)    {      List<string> urls = new List<string>();      html = html.ToLower();      //获取SRC标签中的URL      Regex regexSrc = new Regex("src=/"[^/"]*[(.jpg)(.png)(.gif)(.bmp)(.ico)]/"");      foreach(Match m in regexSrc.Matches(html))      {        string src = m.Value;        src = src.Replace("src=","").Replace("/"","");        if (!src.Contains("http"))          src = com + src;        if(!urls.Contains(src))        urls.Add(src);      }      //获取HREF标签中URL      Regex regexHref = new Regex("href=/"[^/"]*[(.jpg)(.png)(.gif)(.bmp)(.ico)]/"");      foreach (Match m in regexHref.Matches(html))      {        string href = m.Value;        href = href.Replace("href=", "").Replace("/"", "");        if (!href.Contains("http"))          href = com + href;        if(!urls.Contains(href))        urls.Add(href);      }      return urls.ToArray();    }
[DllImport("kernel32.dll")]    static extern bool SetConsoleMode(IntPtr hConsoleHandle, int mode);    [DllImport("kernel32.dll")]    static extern bool GetConsoleMode(IntPtr hConsoleHandle, out int mode);    [DllImport("kernel32.dll")]    static extern IntPtr GetStdHandle(int handle);    const int STD_INPUT_HANDLE = -10;    const int ENABLE_QUICK_EDIT_MODE = 0x40 | 0x80;    public static void EnableQuickEditMode()    {      int mode; IntPtr handle = GetStdHandle(STD_INPUT_HANDLE);      GetConsoleMode(handle, out mode);      mode |= ENABLE_QUICK_EDIT_MODE;      SetConsoleMode(handle, mode);    }    static void Main(string[] args)    {      EnableQuickEditMode();      int oldCount = 0;      Console.Title = "TakeImageFromInternet";      string path = "E://Download//loading//";      while (true)      {        Console.Clear();        string countFile = "E://CountFile.txt";//用来计数的文本,以至于文件名不重复        int cursor = 0;        if (File.Exists(countFile))        {          string text = File.ReadAllText(countFile);          try          {            cursor =oldCount = Convert.ToInt32(text);//次数多了建议使用long          }          catch { }        }        Console.Write("please input a url:");        string url = "http://www.baidu.com/";        string temp = Console.ReadLine();        if (!string.IsNullOrEmpty(temp))          url = temp;        Match mcom = new Regex(@"^(?i)http://(/w+/.){2,3}(com(/.cn)?|cn|net)/b").Match(url);//获取域名        string com = mcom.Value;        //Console.WriteLine(mcom.Value);        Console.Write("please input a save path:");        temp = Console.ReadLine();        if (Directory.Exists(temp))          path = temp;        Console.WriteLine();        WebClient client = new WebClient();        byte[] htmlData = null;        htmlData = client.DownloadData(url);        MemoryStream mstream = new MemoryStream(htmlData);        string html = "";        using (StreamReader sr = new StreamReader(mstream))        {          html = sr.ReadToEnd();        }        Array urls = new MatchHtmlImageUrl().MatchHtml(html,com);         foreach (string imageurl in urls)        {         Console.WriteLine(imageurl);          byte[] imageData = null;          try          {            imageData = client.DownloadData(imageurl);          }          catch { }          if (imageData != null && imageData.Length>0)            using (MemoryStream ms = new MemoryStream(imageData))            {              try              {                                string ext = Aping.Utility.File.FileOpration.ExtendName(imageurl);                ImageFormat format = 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;                }                Image image = new Bitmap(ms);                if (Directory.Exists(path))                  image.Save(path + "//" + cursor + ext, format);              }              catch(Exception ex) { Console.WriteLine(ex.Message); }            }          cursor++;        }        mstream.Close();        File.WriteAllText(countFile, cursor.ToString(), Encoding.UTF8);        Console.WriteLine("take done...image count:"+(cursor-oldCount).ToString());      }          }

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表