zoukankan      html  css  js  c++  java
  • C#使用tesseract3.02识别验证码模拟登录

    一、前言

    使用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+xml,application/xml;q=0.9,image/webp,*/*;q=0.8";
     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             try
    129             {
    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                                 else
    167                                 {
    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                                         do
    185                                         {
    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             finally
    217             {
    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+xml,application/xml;q=0.9,image/webp,*/*;q=0.8";
    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             else
    263             {
    264                 //request.AllowReadStreamBuffering = false;
    265                 request.AllowWriteStreamBuffering = false;
    266             }
    267             try
    268             {
    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                                     do
    312                                     {
    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             finally
    343             {
    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+xml,application/xml;q=0.9,image/webp,*/*;q=0.8";
    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             else
    389             {
    390                 //request.AllowReadStreamBuffering = false;
    391                 request.AllowWriteStreamBuffering = false;
    392             }
    393             try
    394             {
    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             finally
    433             {
    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为单数,则右边比左边大1
    123                 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                     else
    246                         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                         else
    275                         {
    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/12
    304             g.Transform = X;
    305             // Draw image
    306             //Rectangle cloneRect = GetPicValidByValue(128);  //Get Valid Pic Rectangle
    307             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 WebUser
    14     {
    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、登录成功。

  • 相关阅读:
    波特率原理【转】
    求助大神!怎样批量删除数据库表中某个字段中同样的一段字符!
    1033. To Fill or Not to Fill (25)
    http协议
    【数据结构与算法】二叉树深度遍历(递归)
    2015届求职经历
    Codeforces Round #245 (Div. 1)——Working out
    泛泰A900 刷4.4专用中文TWRP2.7.1.1版 支持自己主动识别手机版本号(全球首创)
    实现简答LinkedList
    oracle的内存管理(之中的一个)
  • 原文地址:https://www.cnblogs.com/JinJi-Jary/p/5625414.html
Copyright © 2011-2022 走看看