[c#] 邮件群发工具的编写(一)邮件地址批量提取

    邮件群发软件的编写(一)


工欲善其事,必先利其器

   很多时候,由于是自己做站的关系,经常会碰到邮件群发这个概念。群里也经常有人讨论邮件群发的技术问题,今天趁着中午的休息时间,整理一下思路研究一下。我个人其实并不喜欢邮件群发,只是喜欢研究邮件群发的原理。最近论坛里很多人都要求开发一款特制的邮件群发器,所以我就选择在这里同步这款邮件群发工具的制作步骤,供新手参考,老鸟绕道。

第一步:邮箱批量采集器的制作。

    邮箱批量采集,要选择好采集的页面,我在这里就选择163邮箱吧。因为这种页面采集比较中规中矩。

http://blog.163.com/findFriend.do

看出什么来了吗?对,这个页面全部是163会员的信息。其中这个页面的html文本里面还有我们要找的邮箱资料。

红框里面的就是我们要找的邮箱地址的“base64字符串格式”,只要提取出来后,将其变化为普通的文本就可以了,这在.net里很好解决。

下面的要做事就是用http嗅探器抓取参数资料了。这一步就直接省略...

接下来就直接贴上代码了。

  

View Code
  1 //
  2 //版权:无
  3 //作者:凌晨的搜索者
  4 //出自:http://www.cnblogs.com/uu102 ,转载请加上版权信息
  5 //
  6 using System;
  7 using System.Collections.Generic;
  8 using System.Linq;
  9 using System.Text;
 10 using System.Web;
 11 using System.Text.RegularExpressions;
 12 using System.Net.Mail;
 13 using System.Net;
 14 namespace System
 15 {  //邮箱提取控制类
 16    public class MailUtil
 17     {
 18         public int Index { get; set; }
 19         public int Type { get; set; }
 20         public string Gender { get; set; }
 21         public string Online { get; set; }
 22         public string Province { get; set; }
 23         public string City { get; set; }
 24         public bool HasNext { get; set; }
 25         #region 构造函数
 26         public MailUtil()
 27         {
 28             this.Init(1, 5, "", "", "", "");
 29         }
 30         public MailUtil(int index)
 31         {
 32             this.Init(index, 5, "", "", "", "");
 33         }
 34         public MailUtil(int index, int type)
 35         {
 36             this.Init(index, type, "", "", "", "");
 37         }
 38         public MailUtil(int index, int type, string gender)
 39         {
 40             this.Init(index, type, gender, "", "", "");
 41         }
 42         public MailUtil(int index, int type, string gender, string online)
 43         {
 44             this.Init(index, type, gender, online, "", "");
 45         }
 46         public MailUtil(int index, int type, string gender, string online, string province)
 47         {
 48             this.Init(index, type, gender, online, province, "");
 49         }
 50         public MailUtil(int index, int type, string gender, string online, string province, string city)
 51         {
 52             this.Init(index, type, gender, online, province, city);
 53         }
 54         #endregion
 55         private void Init(int index, int type, string gender,string online, string province, string city)
 56         {
 57                 index = 1;
 58                 this.Index = index;
 59                 this.Type = type;
 60                 this.Gender = gender;
 61                 this.Online = online;
 62                 this.Province = province;
 63                 this.City = city;
 64                 this.HasNext = true;
 65                 this.Province = HttpUtility.UrlEncode(Encoding.GetEncoding("utf-8").GetBytes(this.Province));
 66                 this.City = HttpUtility.UrlEncode(Encoding.GetEncoding("utf-8").GetBytes(this.City));
 67             
 68         }
 69         private string VisitSite()
 70         {
 71             string url = "http://blog.163.com/findFriend.do";
 72             StringBuilder sb = new StringBuilder();
 73             sb.AppendFormat("{0}?index={1}&type={2}",url,this.Index,this.Type);
 74             if(this.Gender!="") sb.AppendFormat("&{0}",this.Gender);
 75             if(this.Province!="")sb.AppendFormat("&{0}",this.Province);
 76             if(this.City!="")sb.AppendFormat("&{0}",this.City);
 77             if(this.Online!="")sb.AppendFormat("&{0}",this.Online);
 78            
 79             string html = UUHttpHelper.GetHtml(sb.ToString(), "gbk");
 80             return html;
 81         }
 82         public Dictionary<string,LinkMan> Extract()
 83         {
 84             LinkMan linkman =null;
 85              
 86             Dictionary<string, LinkMan> linkmans = new Dictionary<string, LinkMan>();
 87             string html = VisitSite();
 88             this.HasNext = html.Contains("下一页") ;
 89             if (!this.HasNext) return linkmans;
 90             MatchCollection matches = new Regex(@"openurl\('(?'base64'[^']+)','profile'\)""\s*class=""nick""\>(?'nick'[^<>]*)\s*\</a\>", RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace).Matches(html);
 91             foreach (Match match in matches)
 92             {
 93                 linkman = new LinkMan();
 94                 linkman.Base64String = match.Groups["base64"].Value;
 95                      string unicode=Encoding.GetEncoding("Gbk").GetString(Convert.FromBase64String(linkman.Base64String));
 96                 linkman.Email = unicode.Contains("@126")?(string.Format("{0}.com",unicode)):(string.Format("{0}@163.com",unicode));
 97                 linkman.Nick = match.Groups["nick"].Value;
 98                 linkmans.Add(linkman.Base64String, linkman);
 99             }
100             matches = new Regex(@"<a\s*[^>]*>(?'area'[^<]*)</a>\s*</div>\s*</div>\s*<div class=""nav"">\s*<a\s*href=""javascript:void\(0\);""\s*(onclick=""gFindFriend.openurl\s*\('(?'base64'[^']+)','blog'\)"")*>", RegexOptions.IgnoreCase).Matches(html);
101             foreach (Match match in matches)
102             {
103                 linkmans[match.Groups["base64"].Value].Area = match.Groups["area"].Value;
104             }
105             this.Index++;
106             return linkmans;
107 
108         }
109         
110     }
111     /// <summary>
112     /// 联系人信息
113     /// </summary>
114    public class LinkMan
115     {
116         /// <summary>
117         /// 昵称
118         /// </summary>
119         public string Nick { get; set; }
120         /// <summary>
121         /// 邮箱地址前缀的base64字符串
122         /// </summary>
123         public string Base64String { get; set; }
124         /// <summary>
125         /// 邮箱地址
126         /// </summary>
127         public string Email { get; set; }
128         /// <summary>
129         /// 性别
130         /// </summary>
131         public string Sex { get; set; }
132         /// <summary>
133         /// 地区
134         /// </summary>
135         public string Area { get; set; }
136         /// <summary>
137         /// 省份
138         /// </summary>
139         public string Province { get; set; }
140         /// <summary>
141         /// 城市
142         /// </summary>
143         public string City { get; set; }
144         /// <summary>
145         /// 年龄
146         /// </summary>
147         public int Age { get; set; }
148     }
149    public class TestClass
150    {
151        public static bool Paused = false;
152       static MailUtil mailUtil = new MailUtil();
153       static Dictionary<string, LinkMan> linkmans = new Dictionary<string, LinkMan>();
154        public static Dictionary<string, LinkMan> TestMethod(System.Windows.Forms.ListView listView)
155        {
156            
157            System.Threading.Thread thread = new System.Threading.Thread(new System.Threading.ThreadStart(delegate
158            {
159                while (mailUtil.HasNext)
160                {
161 
162                    Dictionary<string, LinkMan> list = mailUtil.Extract();
163                    foreach (KeyValuePair<string, LinkMan> kvp in list)
164                    {
165                        if (!linkmans.ContainsKey(kvp.Key))
166                        {
167                            linkmans.Add(kvp.Key, kvp.Value);
168                            System.Windows.Forms.ListViewItem viewItem = listView.Items.Add(linkmans.Count.ToString());
169                            viewItem.SubItems.Add(kvp.Value.Nick);
170                            viewItem.SubItems.Add(kvp.Value.Email);
171                            viewItem.SubItems.Add(kvp.Value.Area);
172                        }
173                    }
174                    if (Paused)
175                        break;
176                }
177                if (linkmans.Count == 0) throw new Exception("没有找到任何数据");
178 
179            }));
180            thread.Start();
181            return linkmans;
182        }
183    }
184    
185 }

这个类调用起来相当简单,直接new一个实例之后,调用Extract()就可以了。但是这样的话就只能获取所有结果的第一页了,后面还有很多的页面就无法抓去了,因此要将里面一个url地址的index参数加1,并且还要判断返回的html页里面是不是含有“下一页”,没有的话就不用继续再抓了

所以我在后面结尾处又加上了一个测试类,供大家直接调用,省去了很多麻烦。因为是静态类,所直接这样调用就可以了。

TestClass.TestMethod(listView1);//这个中间的listView1是你实际上添加到你代码中的控件名称,当然,前提是这个控件已经添加好了相对应的colume

这样邮箱地址批量提取就完成啦,最后就是您对这些数据的处理了。教程每天更新,欢迎继续关注!

原文地址:https://www.cnblogs.com/uu102/p/2667796.html