邮件群发软件的编写(一)
很多时候,由于是自己做站的关系,经常会碰到邮件群发这个概念。群里也经常有人讨论邮件群发的技术问题,今天趁着中午的休息时间,整理一下思路研究一下。我个人其实并不喜欢邮件群发,只是喜欢研究邮件群发的原理。最近论坛里很多人都要求开发一款特制的邮件群发器,所以我就选择在这里同步这款邮件群发工具的制作步骤,供新手参考,老鸟绕道。 第一步:邮箱批量采集器的制作。 邮箱批量采集,要选择好采集的页面,我在这里就选择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
这样邮箱地址批量提取就完成啦,最后就是您对这些数据的处理了。教程每天更新,欢迎继续关注! |