一、前言
使用tesseract3.02识别有验证码的网站 安装tesseract3.02 在VS nuget 搜索Tesseract即可。
二、项目结构图
三、项目主要代码
1 using System; 2 using System.Collections.Concurrent; 3 using System.Collections.Generic; 4 using System.Diagnostics; 5 using System.Drawing; 6 using System.IO; 7 using System.Net; 8 using System.Net.Cache; 9 using System.Text; 10 11 namespace Tesseract.Test.Tools 12 { 13 /// <summary> 14 /// http帮助类 15 /// </summary> 16 public class HttpHelper 17 { 18 /// <summary> 19 /// 异步事件 20 /// </summary> 21 public HttpHelper() 22 { 23 CookieContainer = new CookieContainer(); 24 Encoding = Encoding.UTF8; 25 } 26 27 /// <summary> 28 /// 访问次数字典 29 /// </summary> 30 private ConcurrentDictionary<String, int> urlTryList = new ConcurrentDictionary<string, int>(); 31 32 /// <summary> 33 /// Cookie 容器 34 /// </summary> 35 public CookieContainer CookieContainer { set; get; } 36 37 /// <summary> 38 /// Post数据 39 /// </summary> 40 public String PostData { set; private get; } 41 42 /// <summary> 43 /// 页面语言 44 /// </summary> 45 public Encoding Encoding { set; private get; } 46 47 /// <summary> 48 /// 验证码路径 49 /// </summary> 50 public string CodePath { get; set; } 51 52 /// <summary> 53 /// 文件保存路径 54 /// </summary> 55 public String FileSavePath { set; private get; } 56 57 /// <summary> 58 /// 回调时间 59 /// </summary> 60 public Action<String, String> CallBackAction; 61 62 63 /// <summary> 64 /// 异步请求 65 /// </summary> 66 /// <param name="url">请求地址</param> 67 /// <param name="tryTimes">错误重试次数</param> 68 public void AsynRequest(String url, int tryTimes = 3) 69 { 70 Trace.TraceInformation(String.Concat("开始异步请求:", url)); 71 urlTryList.TryAdd(url, tryTimes); 72 var request = WebRequest.Create(url) as HttpWebRequest; 73 if (request == null) return; 74 request.Headers.Add("Accept-Encoding", "gzip,deflate,sdch"); 75 request.Headers.Add("Accept-Language", "zh-CN,zh;q=0.8"); 76 request.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate | 77 DecompressionMethods.None; 78 request.Credentials = CredentialCache.DefaultNetworkCredentials; 79 request.UseDefaultCredentials = false; 80 request.KeepAlive = false; 81 request.PreAuthenticate = false; 82 request.ProtocolVersion = HttpVersion.Version10; 83 request.UserAgent = 84 "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.116 Safari/537.36"; 85 request.Accept = "text/html,application/xhtml+"; 86 //request.CachePolicy = new RequestCachePolicy(RequestCacheLevel.NoCacheNoStore); 87 request.Timeout = 1000*60*3; 88 request.CookieContainer = CookieContainer; 89 //request.AllowAutoRedirect = false; 90 91 if (!String.IsNullOrEmpty(PostData)) 92 { 93 request.ContentType = "application/x-www-form-urlencoded"; 94 request.Method = "POST"; 95 request.BeginGetRequestStream(GetRequestStreamCallback, request); 96 } 97 else 98 { 99 //request.AllowReadStreamBuffering = false;100 request.AllowWriteStreamBuffering = false;101 request.BeginGetResponse(GetResponseCallback, request);102 }103 }104 105 /// <summary>106 /// 开始对用来写入数据的 Stream 对象的异步请求。107 /// </summary>108 /// <param name="ar"></param>109 private void GetRequestStreamCallback(IAsyncResult ar)110 {111 var request = ar.AsyncState as HttpWebRequest;112 if (request == null) return;113 var postStream = request.EndGetRequestStream(ar);114 var byteArray = Encoding.GetBytes(PostData);115 postStream.Write(byteArray, 0, PostData.Length);116 postStream.Close();117 request.BeginGetResponse(GetResponseCallback, request);118 }119 120 /// <summary>121 /// 开始对 Internet 资源的异步请求。 122 /// </summary>123 /// <param name="ar"></param>124 private void GetResponseCallback(IAsyncResult ar)125 {126 var request = ar.AsyncState as HttpWebRequest;127 if (request == null) return;128 try129 {130 using (var response = request.EndGetResponse(ar) as HttpWebResponse)131 {132 if (response != null)133 {134 //if (response.StatusCode == HttpStatusCode.Found)135 //{136 // string redirect = response.Headers["Location"];137 // if (!String.IsNullOrEmpty(redirect)) AsynRequest(redirect);138 // return;139 //}140 141 if (response.StatusCode != HttpStatusCode.OK)142 {143 Trace.TraceError(String.Concat("请求地址:", request.RequestUri, " 失败,HttpStatusCode",144 response.StatusCode));145 return;146 }147 148 using (var streamResponse = response.GetResponseStream())149 {150 if (streamResponse != null)151 {152 if (!IsText(response.ContentType))153 {154 var contentEncodingStr = response.ContentEncoding;155 var contentEncoding = Encoding;156 if (!String.IsNullOrEmpty(contentEncodingStr))157 contentEncoding = Encoding.GetEncoding(contentEncodingStr);158 using (var streamRead = new StreamReader(streamResponse, contentEncoding))159 {160 var str = streamRead.ReadToEnd();161 if (CallBackAction != null && !String.IsNullOrEmpty(str))162 CallBackAction.BeginInvoke(str, request.RequestUri.ToString(), (s) => { },163 null);164 }165 }166 else167 {168 var fileName = String.Concat(DateTime.Now.ToString("yyyyMMdd"), "/",169 DateTime.Now.ToString("yyyyMMddHHmmssffff"),170 //Extensions.String_.Extensions.GetRnd(6, true, false, false, false, String.Empty),171 ".jpg");172 var fileDirectory = Path.Combine(FileSavePath, DateTime.Now.ToString("yyyyMMdd"));173 CodePath = Path.Combine(FileSavePath, fileName);174 if (!Directory.Exists(fileDirectory))175 Directory.CreateDirectory(fileDirectory);176 177 //下载文件178 using (179 var fileStream = new FileStream(Path.Combine(FileSavePath, fileName),180 FileMode.Create))181 {182 var buffer = new byte[2048];183 int readLength;184 do185 {186 readLength = streamResponse.Read(buffer, 0, buffer.Length);187 fileStream.Write(buffer, 0, readLength);188 } while (readLength != 0);189 }190 if (CallBackAction != null && !String.IsNullOrEmpty(fileName))191 CallBackAction.BeginInvoke(fileName, request.RequestUri.ToString(), (s) => { },192 null);193 }194 }195 }196 response.Close();197 }198 }199 }200 catch (WebException ex)201 {202 Trace.TraceError(String.Concat("请求地址:", request.RequestUri, " 失败信息:", ex.Message));203 var toUrl = request.RequestUri.ToString();204 int tryTimes;205 if (urlTryList.TryGetValue(toUrl, out tryTimes))206 {207 urlTryList.TryUpdate(toUrl, tryTimes, tryTimes - 1);208 if (tryTimes - 1 <= 0)209 {210 urlTryList.TryRemove(toUrl, out tryTimes);211 return;212 }213 AsynRequest(toUrl);214 }215 }216 finally217 {218 request.Abort();219 }220 }221 222 223 /// <summary>224 /// 同步请求225 /// </summary>226 /// <param name="url">请求地址</param>227 /// <param name="tryTimes">错误重试次数</param>228 public String SyncRequest(String url, int tryTimes = 3)229 {230 Trace.TraceInformation(String.Concat("开始同步请求:", url));231 urlTryList.TryAdd(url, tryTimes);232 var request = WebRequest.Create(url) as HttpWebRequest;233 if (request == null) return String.Empty;234 request.Headers.Add("Accept-Encoding", "gzip,deflate,sdch");235 request.Headers.Add("Accept-Language", "zh-CN,zh;q=0.8");236 request.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate |237 DecompressionMethods.None;238 request.Credentials = CredentialCache.DefaultNetworkCredentials;239 request.UseDefaultCredentials = false;240 request.KeepAlive = false;241 request.PreAuthenticate = false;242 request.ProtocolVersion = HttpVersion.Version10;243 request.UserAgent =244 "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.116 Safari/537.36";245 request.Accept = "text/html,application/xhtml+";246 request.CachePolicy = new RequestCachePolicy(RequestCacheLevel.NoCacheNoStore);247 request.Timeout = 1000*60*3;248 request.CookieContainer = CookieContainer;249 request.AllowAutoRedirect = true;250 251 if (!String.IsNullOrEmpty(PostData))252 {253 request.ContentType = "application/x-www-form-urlencoded";254 request.Method = "POST";255 using (var postStream = request.GetRequestStream())256 {257 var byteArray = Encoding.GetBytes(PostData);258 postStream.Write(byteArray, 0, PostData.Length);259 postStream.Close();260 }261 }262 else263 {264 //request.AllowReadStreamBuffering = false;265 request.AllowWriteStreamBuffering = false;266 }267 try268 {269 using (var response = request.GetResponse() as HttpWebResponse)270 {271 if (response != null)272 {273 if (response.StatusCode != HttpStatusCode.OK)274 {275 Trace.TraceError(String.Concat("请求地址:", request.RequestUri, " 失败,HttpStatusCode",276 response.StatusCode));277 return String.Empty;278 }279 using (var streamResponse = response.GetResponseStream())280 {281 if (streamResponse != null)282 {283 if (!IsText(response.ContentType))284 {285 var contentEncodingStr = response.ContentEncoding;286 var contentEncoding = Encoding;287 if (!String.IsNullOrEmpty(contentEncodingStr))288 contentEncoding = Encoding.GetEncoding(contentEncodingStr);289 var streamRead = new StreamReader(streamResponse, contentEncoding);290 var str = streamRead.ReadToEnd();291 if (CallBackAction != null && !String.IsNullOrEmpty(str))292 CallBackAction.BeginInvoke(str, request.RequestUri.ToString(), (s) => { }, null);293 return str;294 }295 296 var fileName = String.Concat(DateTime.Now.ToString("yyyyMMdd"), "/",297 DateTime.Now.ToString("yyyyMMddHHmmssffff"),298 //Extensions.String_.Extensions.GetRnd(6, true, false, false, false, String.Empty),299 Path.GetExtension(request.RequestUri.AbsoluteUri));300 var fileDirectory = Path.Combine(FileSavePath, DateTime.Now.ToString("yyyyMMdd"));301 if (!Directory.Exists(fileDirectory))302 Directory.CreateDirectory(fileDirectory);303 304 //下载文件305 using (306 var fileStream = new FileStream(Path.Combine(FileSavePath, fileName),307 FileMode.Create))308 {309 var buffer = new byte[2048];310 int readLength;311 do312 {313 readLength = streamResponse.Read(buffer, 0, buffer.Length);314 fileStream.Write(buffer, 0, readLength);315 } while (readLength != 0);316 }317 if (CallBackAction != null && !String.IsNullOrEmpty(fileName))318 CallBackAction.BeginInvoke(fileName, request.RequestUri.ToString(), (s) => { }, null);319 return fileName;320 }321 }322 response.Close();323 }324 }325 }326 catch (WebException ex)327 {328 Trace.TraceError(String.Concat("请求地址:", request.RequestUri, " 失败信息:", ex.Message));329 var toUrl = request.RequestUri.ToString();330 if (urlTryList.TryGetValue(toUrl, out tryTimes))331 {332 urlTryList.TryUpdate(toUrl, tryTimes, tryTimes - 1);333 if (tryTimes - 1 <= 0)334 {335 urlTryList.TryRemove(toUrl, out tryTimes);336 Trace.TraceError(String.Concat("请求地址重试失败:", request.RequestUri));337 return String.Empty;338 }339 SyncRequest(toUrl);340 }341 }342 finally343 {344 request.Abort();345 }346 return String.Empty;347 }348 349 /// <summary>350 /// 验证码获取351 /// </summary>352 /// <param name="url">请求地址</param>353 /// <param name="tryTimes">错误重试次数</param>354 public Bitmap GetCheckCode(String url, int tryTimes = 3)355 {356 Trace.TraceInformation(String.Concat("开始同步请求:", url));357 urlTryList.TryAdd(url, tryTimes);358 var request = WebRequest.Create(url) as HttpWebRequest;359 if (request == null) return null;360 request.Headers.Add("Accept-Encoding", "gzip,deflate,sdch");361 request.Headers.Add("Accept-Language", "zh-CN,zh;q=0.8");362 request.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate |363 DecompressionMethods.None;364 request.Credentials = CredentialCache.DefaultNetworkCredentials;365 request.UseDefaultCredentials = false;366 request.KeepAlive = false;367 request.PreAuthenticate = false;368 request.ProtocolVersion = HttpVersion.Version10;369 request.UserAgent =370 "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.116 Safari/537.36";371 request.Accept = "text/html,application/xhtml+";372 request.CachePolicy = new RequestCachePolicy(RequestCacheLevel.NoCacheNoStore);373 request.Timeout = 1000*60*3;374 request.CookieContainer = CookieContainer;375 request.AllowAutoRedirect = true;376 377 if (!String.IsNullOrEmpty(PostData))378 {379 request.ContentType = "application/x-www-form-urlencoded";380 request.Method = "POST";381 using (var postStream = request.GetRequestStream())382 {383 var byteArray = Encoding.GetBytes(PostData);384 postStream.Write(byteArray, 0, PostData.Length);385 postStream.Close();386 }387 }388 else389 {390 //request.AllowReadStreamBuffering = false;391 request.AllowWriteStreamBuffering = false;392 }393 try394 {395 using (var response = request.GetResponse() as HttpWebResponse)396 {397 if (response != null)398 {399 if (response.StatusCode != HttpStatusCode.OK)400 {401 Trace.TraceError(String.Concat("请求地址:", request.RequestUri, " 失败,HttpStatusCode",402 response.StatusCode));403 return null;404 }405 using (var streamResponse = response.GetResponseStream())406 {407 if (streamResponse != null)408 {409 return (Bitmap) Bitmap.FromStream(streamResponse);410 }411 }412 response.Close();413 }414 }415 }416 catch (WebException ex)417 {418 Trace.TraceError(String.Concat("请求地址:", request.RequestUri, " 失败信息:", ex.Message));419 var toUrl = request.RequestUri.ToString();420 if (urlTryList.TryGetValue(toUrl, out tryTimes))421 {422 urlTryList.TryUpdate(toUrl, tryTimes, tryTimes - 1);423 if (tryTimes - 1 <= 0)424 {425 urlTryList.TryRemove(toUrl, out tryTimes);426 Trace.TraceError(String.Concat("请求地址重试失败:", request.RequestUri));427 return null;428 }429 GetCheckCode(toUrl);430 }431 }432 finally433 {434 request.Abort();435 }436 return null;437 }438 439 /// <summary>440 /// 判断文件是否为文本类型441 /// </summary>442 /// <param name="contentType">内容类型</param>443 /// <returns></returns>444 private static bool IsText(String contentType)445 {446 var fileContentType = new List<string>447 {448 "image/Bmp",449 "image/gif",450 "image/jpeg",451 "image/png",452 "image/tiff",453 "application/octet-stream"454 };455 return fileContentType.Contains(contentType);456 }457 }458 }
HttpHepler
1 using System; 2 using System.Drawing; 3 using System.Drawing.Drawing2D; 4 using System.Drawing.Imaging; 5 using System.Runtime.InteropServices; 6 7 namespace Tesseract.Test.Tools 8 { 9 public class UnCodebase 10 { 11 public Bitmap bmpobj; 12 13 public UnCodebase(Bitmap pic) 14 { 15 bmpobj = new Bitmap(pic); //转换为Format32bppRgb 16 } 17 18 /// <summary> 19 /// 根据RGB,计算灰度值 20 /// </summary> 21 /// <param name="posClr">Color值</param> 22 /// <returns>灰度值,整型</returns> 23 private int GetGrayNumColor(Color posClr) 24 { 25 return (posClr.R*19595 + posClr.G*38469 + posClr.B*7472) >> 16; 26 } 27 28 /// <summary> 29 /// 灰度转换,逐点方式 30 /// </summary> 31 public Bitmap GrayByPixels() 32 { 33 for (int i = 0; i < bmpobj.Height; i++) 34 { 35 for (int j = 0; j < bmpobj.Width; j++) 36 { 37 int tmpValue = GetGrayNumColor(bmpobj.GetPixel(j, i)); 38 bmpobj.SetPixel(j, i, Color.FromArgb(tmpValue, tmpValue, tmpValue)); 39 } 40 } 41 return bmpobj; 42 } 43 44 /// <summary> 45 /// 去图形边框 46 /// </summary> 47 /// <param name="borderWidth"></param> 48 public Bitmap ClearPicBorder(int borderWidth) 49 { 50 for (int i = 0; i < bmpobj.Height; i++) 51 { 52 for (int j = 0; j < bmpobj.Width; j++) 53 { 54 if (i < borderWidth || j < borderWidth || j > bmpobj.Width - 1 - borderWidth || 55 i > bmpobj.Height - 1 - borderWidth) 56 bmpobj.SetPixel(j, i, Color.FromArgb(255, 255, 255)); 57 } 58 } 59 return bmpobj; 60 } 61 62 /// <summary> 63 /// 灰度转换,逐行方式 64 /// </summary> 65 public Bitmap GrayByLine() 66 { 67 Rectangle rec = new Rectangle(0, 0, bmpobj.Width, bmpobj.Height); 68 BitmapData bmpData = bmpobj.LockBits(rec, ImageLockMode.ReadWrite, bmpobj.PixelFormat); 69 // PixelFormat.Format32bppPArgb); 70 // bmpData.PixelFormat = PixelFormat.Format24bppRgb; 71 IntPtr scan0 = bmpData.Scan0; 72 int len = bmpobj.Width*bmpobj.Height; 73 int[] pixels = new int[len]; 74 Marshal.Copy(scan0, pixels, 0, len); 75 76 //对图片进行处理 77 int GrayValue = 0; 78 for (int i = 0; i < len; i++) 79 { 80 GrayValue = GetGrayNumColor(Color.FromArgb(pixels[i])); 81 pixels[i] = (byte) (Color.FromArgb(GrayValue, GrayValue, GrayValue)).ToArgb(); //Color转byte 82 } 83 84 bmpobj.UnlockBits(bmpData); 85 return bmpobj; 86 } 87 88 /// <summary> 89 /// 得到有效图形并调整为可平均分割的大小 90 /// </summary> 91 /// <param name="dgGrayValue">灰度背景分界值</param> 92 /// <param name="CharsCount">有效字符数</param> 93 /// <returns></returns> 94 public void GetPicValidByValue(int dgGrayValue, int CharsCount) 95 { 96 int posx1 = bmpobj.Width; 97 int posy1 = bmpobj.Height; 98 int posx2 = 0; 99 int posy2 = 0;100 for (int i = 0; i < bmpobj.Height; i++) //找有效区101 {102 for (int j = 0; j < bmpobj.Width; j++)103 {104 int pixelValue = bmpobj.GetPixel(j, i).R;105 if (pixelValue < dgGrayValue) //根据灰度值106 {107 if (posx1 > j) posx1 = j;108 if (posy1 > i) posy1 = i;109 110 if (posx2 < j) posx2 = j;111 if (posy2 < i) posy2 = i;112 }113 ;114 }115 ;116 }117 ;118 // 确保能整除119 int Span = CharsCount - (posx2 - posx1 + 1)%CharsCount; //可整除的差额数120 if (Span < CharsCount)121 {122 int leftSpan = Span/2; //分配到左边的空列 ,如span为单数,则右边比左边大1123 if (posx1 > leftSpan)124 posx1 = posx1 - leftSpan;125 if (posx2 + Span - leftSpan < bmpobj.Width)126 posx2 = posx2 + Span - leftSpan;127 }128 //复制新图129 Rectangle cloneRect = new Rectangle(posx1, posy1, posx2 - posx1 + 1, posy2 - posy1 + 1);130 bmpobj = bmpobj.Clone(cloneRect, bmpobj.PixelFormat);131 }132 133 /// <summary>134 /// 得到有效图形,图形为类变量135 /// </summary>136 /// <param name="dgGrayValue">灰度背景分界值</param>137 /// <param name="CharsCount">有效字符数</param>138 /// <returns></returns>139 public void GetPicValidByValue(int dgGrayValue)140 {141 int posx1 = bmpobj.Width;142 int posy1 = bmpobj.Height;143 int posx2 = 0;144 int posy2 = 0;145 for (int i = 0; i < bmpobj.Height; i++) //找有效区146 {147 for (int j = 0; j < bmpobj.Width; j++)148 {149 int pixelValue = bmpobj.GetPixel(j, i).R;150 if (pixelValue < dgGrayValue) //根据灰度值151 {152 if (posx1 > j) posx1 = j;153 if (posy1 > i) posy1 = i;154 155 if (posx2 < j) posx2 = j;156 if (posy2 < i) posy2 = i;157 }158 ;159 }160 ;161 }162 ;163 //复制新图164 Rectangle cloneRect = new Rectangle(posx1, posy1, posx2 - posx1 + 1, posy2 - posy1 + 1);165 bmpobj = bmpobj.Clone(cloneRect, bmpobj.PixelFormat);166 }167 168 /// <summary>169 /// 得到有效图形,图形由外面传入170 /// </summary>171 /// <param name="dgGrayValue">灰度背景分界值</param>172 /// <param name="CharsCount">有效字符数</param>173 /// <returns></returns>174 public Bitmap GetPicValidByValue(Bitmap singlepic, int dgGrayValue)175 {176 int posx1 = singlepic.Width;177 int posy1 = singlepic.Height;178 int posx2 = 0;179 int posy2 = 0;180 for (int i = 0; i < singlepic.Height; i++) //找有效区181 {182 for (int j = 0; j < singlepic.Width; j++)183 {184 int pixelValue = singlepic.GetPixel(j, i).R;185 if (pixelValue < dgGrayValue) //根据灰度值186 {187 if (posx1 > j) posx1 = j;188 if (posy1 > i) posy1 = i;189 190 if (posx2 < j) posx2 = j;191 if (posy2 < i) posy2 = i;192 }193 ;194 }195 ;196 }197 ;198 //复制新图199 Rectangle cloneRect = new Rectangle(posx1, posy1, posx2 - posx1 + 1, posy2 - posy1 + 1);200 return singlepic.Clone(cloneRect, singlepic.PixelFormat);201 }202 203 /// <summary>204 /// 平均分割图片205 /// </summary>206 /// <param name="RowNum">水平上分割数</param>207 /// <param name="ColNum">垂直上分割数</param>208 /// <returns>分割好的图片数组</returns>209 public Bitmap[] GetSplitPics(int RowNum, int ColNum)210 {211 if (RowNum == 0 || ColNum == 0)212 return null;213 int singW = bmpobj.Width/RowNum;214 int singH = bmpobj.Height/ColNum;215 Bitmap[] PicArray = new Bitmap[RowNum*ColNum];216 217 Rectangle cloneRect;218 for (int i = 0; i < ColNum; i++) //找有效区219 {220 for (int j = 0; j < RowNum; j++)221 {222 cloneRect = new Rectangle(j*singW, i*singH, singW, singH);223 PicArray[i*RowNum + j] = bmpobj.Clone(cloneRect, bmpobj.PixelFormat); //复制小块图224 }225 }226 return PicArray;227 }228 229 /// <summary>230 /// 返回灰度图片的点阵描述字串,1表示灰点,0表示背景231 /// </summary>232 /// <param name="singlepic">灰度图</param>233 /// <param name="dgGrayValue">背前景灰**限</param>234 /// <returns></returns>235 public string GetSingleBmpCode(Bitmap singlepic, int dgGrayValue)236 {237 Color piexl;238 string code = "";239 for (int posy = 0; posy < singlepic.Height; posy++)240 for (int posx = 0; posx < singlepic.Width; posx++)241 {242 piexl = singlepic.GetPixel(posx, posy);243 if (piexl.R < dgGrayValue) // Color.Black )244 code = code + "1";245 else246 code = code + "0";247 }248 return code;249 }250 251 /// <summary>252 /// 去掉噪点253 /// </summary>254 /// <param name="dgGrayValue"></param>255 /// <param name="MaxNearPoints"></param>256 public Bitmap ClearNoise(int dgGrayValue, int MaxNearPoints)257 {258 Color piexl;259 int nearDots = 0;260 int XSpan, YSpan, tmpX, tmpY;261 //逐点判断262 for (int i = 0; i < bmpobj.Width; i++)263 for (int j = 0; j < bmpobj.Height; j++)264 {265 piexl = bmpobj.GetPixel(i, j);266 if (piexl.R < dgGrayValue)267 {268 nearDots = 0;269 //判断周围8个点是否全为空270 if (i == 0 || i == bmpobj.Width - 1 || j == 0 || j == bmpobj.Height - 1) //边框全去掉271 {272 bmpobj.SetPixel(i, j, Color.FromArgb(255, 255, 255));273 }274 else275 {276 if (bmpobj.GetPixel(i - 1, j - 1).R < dgGrayValue) nearDots++;277 if (bmpobj.GetPixel(i, j - 1).R < dgGrayValue) nearDots++;278 if (bmpobj.GetPixel(i + 1, j - 1).R < dgGrayValue) nearDots++;279 if (bmpobj.GetPixel(i - 1, j).R < dgGrayValue) nearDots++;280 if (bmpobj.GetPixel(i + 1, j).R < dgGrayValue) nearDots++;281 if (bmpobj.GetPixel(i - 1, j + 1).R < dgGrayValue) nearDots++;282 if (bmpobj.GetPixel(i, j + 1).R < dgGrayValue) nearDots++;283 if (bmpobj.GetPixel(i + 1, j + 1).R < dgGrayValue) nearDots++;284 }285 286 if (nearDots < MaxNearPoints)287 bmpobj.SetPixel(i, j, Color.FromArgb(255, 255, 255)); //去掉单点 && 粗细小3邻边点288 }289 else //背景290 bmpobj.SetPixel(i, j, Color.FromArgb(255, 255, 255));291 }292 return bmpobj;293 }294 295 /// <summary>296 /// 扭曲图片校正297 /// </summary>298 public Bitmap ReSetBitMap()299 {300 Graphics g = Graphics.FromImage(bmpobj);301 Matrix X = new Matrix();302 // X.Rotate(30);303 X.Shear((float) 0.16666666667, 0); // 2/12304 g.Transform = X;305 // Draw image306 //Rectangle cloneRect = GetPicValidByValue(128); //Get Valid Pic Rectangle307 Rectangle cloneRect = new Rectangle(0, 0, bmpobj.Width, bmpobj.Height);308 Bitmap tmpBmp = bmpobj.Clone(cloneRect, bmpobj.PixelFormat);309 g.DrawImage(tmpBmp,310 new Rectangle(0, 0, bmpobj.Width, bmpobj.Height),311 0, 0, tmpBmp.Width,312 tmpBmp.Height,313 GraphicsUnit.Pixel);314 315 return tmpBmp;316 }317 }318 }
UnCodebase
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 using Tesseract.Test.Tools; 7 8 namespace Tesseract.Test 9 {10 /// <summary>11 /// 网站用户12 /// </summary>13 public class WebUser14 {15 /// <summary>16 /// 用户名17 /// </summary>18 private string _userName = string.Empty;19 20 /// <summary>21 /// 密码22 /// </summary>23 private string _password = string.Empty;24 25 /// <summary>26 /// 验证码27 /// </summary>28 private string _checkCode = string.Empty;29 30 private HttpHelper _httpHelper = new HttpHelper();31 32 /// <summary>33 /// 构造函数34 /// </summary>35 public WebUser()36 {37 _userName = "admin"; //初始化用户38 _password = "password"; //初始化密码39 Login();40 }41 42 43 /// <summary>44 /// 登录45 /// </summary>46 private void Login()47 {48 //登录页49 _httpHelper.SyncRequest("Login.html");50 51 //获取验证码图片52 var bitmap = _httpHelper.GetCheckCode("CheckCode.html");53 54 //解析验证码55 using (var engine = new TesseractEngine(@"./tessdata", "eng", EngineMode.Default))56 {57 using (var entity = engine.Process(bitmap))58 {59 _checkCode = entity.GetText();60 }61 }62 63 //登录验证64 _httpHelper.PostData = string.Format("userName={0}&password={1}&checkcode={2}",65 _userName, _password, _checkCode);66 _httpHelper.SyncRequest("CheckLogin.html");67 }68 }69 }
WebUser
四、代码解释
1、模拟登录的过程基本都是访问登录页面获取相关的cookie。
2、访问验证码页面这样就不用将验证码下载到本地再解析。直接在程序内解析。减少验证码本地图片文件增加。
3、使用tesseract来解析验证码。(需要看验证码的干扰是否严重,使用UnCodebase对验证码图片适当的处理可以增加识别正确率)
4、访问登录验证页面将用户名密码验证码POST过去。
5、登录成功。
原标题:C#使用tesseract3.02识别验证码模拟登录
关键词:C#