using AllBase; using CefSharp; using CefSharp.WinForms; using TemuKJD.BaseForms; using NaiBa.CefHelper; using NaiBa.CefHelper.Handler; using NaiBa.Util.Extension; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Drawing.Drawing2D; using System.Drawing.Imaging; using System.IO; using System.IO.Compression; using System.Linq; using System.Net; using System.Security.Cryptography; using System.Text; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; using Work; using Work.CollectClass; namespace TemuKJD.KJDForms.ToolForms { public partial class PinDuoDuoCaptchaForm : LRBaseForm { public static string PersonUrl = BaseClass.NewUrl+"/personal.html"; public static string GoodsUrl = "http://yangkeduo.com/goods.html?goods_id=17252982258"; public static string SearchUrl = "http://yangkeduo.com/search_result.html?search_key=垃圾桶"; public static string userAgent = "Mozilla/5.0 (Linux; Android 7.1.1; OD103 Build/NMF26F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.84 Mobile Safari/537.36"; private string pddAccessToken = string.Empty; private string url = string.Empty; public bool isAutoCaptcha = false; private ChromiumWebBrowser cefWebBrowser = null; public delegate void OnSaveComplete(TData msg); public event OnSaveComplete onSaveComplete; private int maxCaptchaTimes = 12; public PinDuoDuoCaptchaForm(string token) { pddAccessToken = token; InitializeComponent(); } private async void PinDuoDuoCaptchaForm_Load(object sender, EventArgs e) { TitleText = this.Text; PinDuoDuoTokenInfo tokenInfo = PinduoduoProductCollect.PinDuoDuoTokenList.Where(p => p.PDDAccessToken == pddAccessToken).FirstOrDefault(); //if (tokenInfo.SearchStatus == (int)TokenStatus.Invalid) //{ // url = SearchUrl; //} //else if (tokenInfo.ProductDetailStatus == (int)TokenStatus.Invalid) //{ // url = GoodsUrl; //} //else //{ // url = PersonUrl; //} if (cefWebBrowser == null) { //cefWebBrowser = CEFBrowser.CreateChromiumWebBrowser(PinDuoDuoHelper.PinDuoDuoPersonUrl, false); //requestHandler = new RequestHandler(); //requestHandler.UserAgent = userAgent; //requestHandler.ResourceLoadComplete += RequestHandler_ResourceLoadComplete; //cefWebBrowser.RequestHandler = requestHandler; //cefWebBrowser.KeyboardHandler = new KeyboardHandler(); //cefWebBrowser.FrameLoadEnd += CefWebBrowser_FrameLoadEnd; //cefWebBrowser.FrameLoadStart += CefWebBrowser_FrameLoadStart; //cefWebBrowser.IsBrowserInitializedChanged += CefWebBrowser_IsBrowserInitializedChanged; //cefWebBrowser.Dock = DockStyle.Fill; //scPinDuoDuo.Panel1.Controls.Add(cefWebBrowser); cefWebBrowser = CreateChromiumWebBrowser("https://yangkeduo.com/personal.htm", false); CustomResourceRequestHandler resourceRequestHandler = new CustomResourceRequestHandler(); resourceRequestHandler.UserAgent = userAgent; resourceRequestHandler.ResourceLoadCompleteEvent += RequestHandler_ResourceLoadComplete; cefWebBrowser.RequestHandler = new CustomRequestHandler(resourceRequestHandler); cefWebBrowser.FrameLoadStart += CefWebBrowser_FrameLoadStart; cefWebBrowser.IsBrowserInitializedChanged += CefWebBrowser_IsBrowserInitializedChanged; cefWebBrowser.KeyboardHandler = new CefKeyboardHandler(); cefWebBrowser.FrameLoadEnd += CefWebBrowser_FrameLoadEnd; cefWebBrowser.Dock = DockStyle.Fill; scPinDuoDuo.Panel1.Controls.Add(cefWebBrowser); } else { await ClearCookie(); } if (isAutoCaptcha) { AutoCaptcha(); } //cefWebBrowser = CreateChromiumWebBrowser(url, false); //RequestHandler requestHandler = new RequestHandler(); //requestHandler.ResourceLoadComplete += RequestHandler_ResourceLoadComplete; //cefWebBrowser.RequestHandler = requestHandler; //cefWebBrowser.KeyboardHandler = new CefKeyboardHandlerOwn(); //cefWebBrowser.FrameLoadEnd += CefWebBrowser_FrameLoadEnd; //cefWebBrowser.Dock = DockStyle.Fill; //scPinDuoDuo.Panel1.Controls.Add(cefWebBrowser); //await SetCookieAsync(".yangkeduo.com", "PDDAccessToken=" + pddAccessToken, cefWebBrowser.RequestContext.GetCookieManager(null)); } public async Task ClearCookie() { //await cefWebBrowser.DeleteCookieAsync(cefWebBrowser.RequestContext.GetCookieManager(null)); DelCookies(); cefWebBrowser.Load("https://yangkeduo.com/personal.htm"); } public void DelCookies() { ICookieManager cookieManager = cefWebBrowser.RequestContext.GetCookieManager(null); Task deleteTask = cookieManager.DeleteCookiesAsync("yangkeduo.com", null); deleteTask.Wait(); } private void CefWebBrowser_IsBrowserInitializedChanged(object sender, EventArgs e) { } private void CefWebBrowser_FrameLoadStart(object sender, FrameLoadStartEventArgs e) { // 使用JavaScript修改UserAgent cefWebBrowser.GetBrowser().MainFrame.ExecuteJavaScriptAsync("navigator.__defineGetter__('userAgent', function(){ return '" + userAgent + "'});navigator.userAgent;"); } private void RequestHandler_ResourceLoadComplete(object sender, string url, string postData, string responseData) { if (url.Contains("user_verify_auth")) { if (responseData.Contains("\"result\":true")) { this.BeginInvoke(new Action(() => { btnSaveToken_Click(null, null); })); } } } public CancellationTokenSource cancellationTokenSource { get; set; } private bool isBrowserDisposed = false; public async void AutoCaptcha() { //Task.Run(async () => //{ int captchaTimes = 0; Dictionary moYunCaptchaHashDict = new Dictionary(); while (true) { try { Console.WriteLine("ThreadId:" + Thread.CurrentThread.ManagedThreadId); //if (cancellationTokenSource.IsCancellationRequested) //{ // return; //} if (captchaTimes > maxCaptchaTimes) { PinduoduoProductCollect.PinDuoDuoTokenList.RemoveAll(p => p.PDDAccessToken == pddAccessToken); TData objToken = CheckAccessToken(pddAccessToken); PinDuoDuoTokenInfo pinDuoDuoTokenInfo = objToken.Result; if (pinDuoDuoTokenInfo.ProductDetailStatus == (int)TokenStatus.Valid) { PinduoduoProductCollect.PinDuoDuoTokenList.Add(objToken.Result); } cancellationTokenSource.Cancel(); return; } if (isBrowserDisposed) { return; } if (cefWebBrowser.IsBrowserInitialized) { string html = await cefWebBrowser.GetMainFrame().GetSourceAsync(); string url = cefWebBrowser.GetMainFrame().Url; if (url.Contains("https://yangkeduo.com/login.html")) { TData objToken = CheckAccessToken(pddAccessToken); if (objToken.Result.LoginStatus == (int)TokenStatus.Invalid) { cancellationTokenSource.Cancel(); return; } } else if (html.Contains("
收起
")) { LocationPoint locationPoint = GetElementLocationPoint(cefWebBrowser, "alert-goto-app-cancel"); locationPoint.Left += SecurityHelper.GetRandom(10, 100); locationPoint.Top += SecurityHelper.GetRandom(5, 30); SimulateMouseLeftClick(cefWebBrowser.GetBrowser().GetHost(), locationPoint.Left, locationPoint.Top); } else if (html.Contains("聊天") && url.Contains("https://yangkeduo.com/personal.html")) { JavascriptResponse task = await EvaluateScriptAsync(cefWebBrowser, "document.getElementsByClassName('footer-item')[3].click();"); } else if (html.Contains("聊天") && url.Contains("https://yangkeduo.com/chat_list.html")) { JavascriptResponse task = await EvaluateScriptAsync(cefWebBrowser, "document.getElementsByClassName('footer-item')[4].click();"); } else if (html.Contains("点击下方“安全验证”按钮,完成拼多多官方验证")) { LocationPoint locationPoint = GetElementLocationPoint(cefWebBrowser, "intel-btn"); locationPoint.Left += SecurityHelper.GetRandom(10, 100); locationPoint.Top += SecurityHelper.GetRandom(5, 40); SimulateMouseLeftClick(cefWebBrowser.GetBrowser().GetHost(), locationPoint.Left, locationPoint.Top); } else if (html.Contains("点击此圆圈内进行验证")) { LocationPoint locationPoint = GetElementLocationPoint(cefWebBrowser, "circle-small"); locationPoint.Left += SecurityHelper.GetRandom(10, 50); locationPoint.Top += SecurityHelper.GetRandom(5, 50); SimulateMouseLeftClick(cefWebBrowser.GetBrowser().GetHost(), locationPoint.Left, locationPoint.Top); } else if (html.Contains("请绘制图中路径")) { ClickRefresh("gesture-refresh"); } else if (html.Contains("向右拖动滑块填充拼图") || html.Contains("拖动滑块完成上方拼图")) { LocationPoint locationPoint = GetElementLocationPoint(cefWebBrowser, "slider-img-bg"); SlideCaptcha(html, locationPoint); } else if (html.Contains("captchaClickImg")) { LocationPoint locationPoint = GetElementLocationPoint(cefWebBrowser, "picture-img"); if (html.Contains("请点击") && html.Contains("data:image/jpeg")) { string typeId = "10010"; await CaptchaError(moYunCaptchaHashDict, typeId); RandomCaptcha(locationPoint); await Captcha(html, locationPoint, moYunCaptchaHashDict, typeId); } else if (html.Contains("data:image/png")) { string typeId = "10008"; await CaptchaError(moYunCaptchaHashDict, typeId); RandomCaptcha(locationPoint); await Captcha(html, locationPoint, moYunCaptchaHashDict, typeId); } else { ClickRefresh(); } Thread.Sleep(1000); } else if (!html.Contains("data:image")) { cefWebBrowser.Load("https://yangkeduo.com/personal.html"); } captchaTimes++; } Thread.Sleep(2000); } catch (Exception ex) { } } //}); } private bool isFirstCaptcha = false; private void RandomCaptcha(LocationPoint locationPoint) { if (isFirstCaptcha) { for (int i = 1; i <= int.MaxValue; i++) { if (!isFirstCaptcha) { break; } SimulateMouseLeftClick(cefWebBrowser.GetBrowser().GetHost(), SecurityHelper.GetRandom(1, locationPoint.Left + locationPoint.Width), SecurityHelper.GetRandom(1, locationPoint.Top + locationPoint.Height)); } } } private string lastBase64Captcha = string.Empty; // 用来判断验证码是否刷新 private async Task Captcha(string html, LocationPoint locationPoint, Dictionary moYunCaptchaHashDict, string typeId) { string elementRefresh = "document.getElementsByClassName('refresh')[0].style='display:{0}'"; if (locationPoint.Width > 0 && locationPoint.Height > 0) { string base64 = GetBase64ImageString(html, "data:image/png;base64,", locationPoint); if (string.IsNullOrEmpty(base64)) { base64 = GetBase64ImageString(html, "data:image/jpeg;base64,", locationPoint); } if (lastBase64Captcha == base64) { ClickRefresh(); } else { lastBase64Captcha = base64; string text = Resove(html, "\"picture-text\">", ""); text = ClearHtml(text); string code = await Captcha(typeId, base64, text); if (!string.IsNullOrEmpty(code)) { JObject jObj = JObject.Parse(code); if (jObj != null) { if (jObj["code"].ParseToString() == "1") { await EvaluateScriptAsync(cefWebBrowser, string.Format(elementRefresh, "none")); moYunCaptchaHashDict.Add(typeId, jObj["data"]["hash"].ToString().ParseToInt()); // 识别成功,进行验证 foreach (string point in jObj["data"]["result"].ParseToString().Split(new string[] { "|" }, StringSplitOptions.RemoveEmptyEntries)) { int[] captchaLocationArr = point.Split(',').Select(p => p.ParseToInt()).ToArray(); if (cefWebBrowser.IsBrowserInitialized) { SimulateMouseLeftClick(cefWebBrowser.GetBrowser().GetHost(), locationPoint.Left + captchaLocationArr[0], locationPoint.Top + captchaLocationArr[1]); } } Thread.Sleep(1000); if (cefWebBrowser.IsBrowserInitialized) { await EvaluateScriptAsync(cefWebBrowser, string.Format(elementRefresh, "block")); ClickRefresh(); Thread.Sleep(500); } } else { // 识别失败,刷新验证码 ClickRefresh(); } } } else { // 识别失败,刷新验证码 ClickRefresh(); } } } } public async Task Captcha(string typeId, string base64Image, string text) { string url = BaseClass.LoginApiUrl + "?obj=api/check_code&act=my_upload"; url += "&" + UserLogin.GetSignature(); HttpParam httpParam = new HttpParam { Url = url, PostData = string.Format("typeid={0}&check_img={1}&fujia={2}", typeId, UrlEncode(base64Image), text) }; string html = await PostAsync(httpParam); return html; } public static string UrlEncode(string url, bool isUppercase = false) { if (string.IsNullOrEmpty(url)) { return string.Empty; } else { string encodeUrl = HttpUtility.UrlEncode(url, Encoding.UTF8); if (isUppercase) { Regex reg = new Regex(@"%[a-f0-9]{2}"); encodeUrl = reg.Replace(encodeUrl, m => m.Value.ToUpperInvariant()); } return encodeUrl; } } private async Task CaptchaError(Dictionary moYunCaptchaHashDict, string typeId) { if (moYunCaptchaHashDict.ContainsKey(typeId)) { await CaptchaError(moYunCaptchaHashDict[typeId]); moYunCaptchaHashDict.Remove(typeId); } } public static string ClearHtml(string html) { html = html.ParseToString(); html = Regex.Replace(Regex.Replace(html, @"(|||)", ""), "(<[^>]*?>)", ""); return html; } public async Task CaptchaError(int hash) { string url = BaseClass.LoginApiUrl + "?obj=api/check_code&act=my_upload_error"; url += "&" + UserLogin.GetSignature(); HttpParam httpParam = new HttpParam { Url = url, PostData = string.Format("hash={0}", hash) }; string html = await PostAsync(httpParam); return html; } public static async Task PostAsync(HttpParam httpParam) { try { HttpWebRequest request = GetHttpWebRequest(httpParam); request.Method = "Post"; request.ServicePoint.Expect100Continue = false; byte[] postDataByte = Encoding.UTF8.GetBytes(httpParam.PostData); request.ContentLength = postDataByte.Length; request.AllowAutoRedirect = false; using (Stream requestStream = await request.GetRequestStreamAsync()) { requestStream.Write(postDataByte, 0, postDataByte.Length); } return await ReadResponseAsync(httpParam, (HttpWebResponse)request.GetResponse()); } catch (Exception ex) { return string.Empty; } } public static Stream DecompressStream(HttpWebResponse response) { Stream responseStream = response.GetResponseStream(); Stream stream = null; if (response.ContentEncoding.ToLower().Contains("gzip")) { stream = new GZipStream(responseStream, CompressionMode.Decompress); } else if (response.ContentEncoding.ToLower().Contains("deflate")) { stream = new DeflateStream(responseStream, CompressionMode.Decompress); } if (stream == null) { return responseStream; } else { return stream; } } public static async Task ReadResponseAsync(HttpParam httpParam, HttpWebResponse response) { using (Stream stream = DecompressStream(response)) { using (StreamReader streamReader = new StreamReader(stream, httpParam.ResponseEncoding)) { return await streamReader.ReadToEndAsync(); } } } public static HttpWebRequest GetHttpWebRequest(HttpParam param) { HttpWebRequest request = (HttpWebRequest)WebRequest.Create(param.Url); if (param.Proxy != null) { request.Proxy = param.Proxy; } if (!string.IsNullOrEmpty(param.UserAgent)) { request.UserAgent = param.UserAgent; } else { request.UserAgent = "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36"; } if (!string.IsNullOrEmpty(param.Accept)) { request.Accept = param.Accept; } else { request.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"; } if (string.IsNullOrEmpty(param.AcceptLanguage)) { request.Headers.Add("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8"); } else { request.Headers.Add("Accept-Language", param.AcceptLanguage); } if (!string.IsNullOrEmpty(param.ContentType)) { request.ContentType = param.ContentType; } else { request.ContentType = "application/x-www-form-urlencoded;charset=UTF-8"; } if (!string.IsNullOrEmpty(param.Referer)) { request.Referer = param.Referer; } request.Headers.Remove("Cookie"); if (!string.IsNullOrEmpty(param.Cookie)) { request.Headers.Add("Cookie", param.Cookie); } if (param.Header != null) { foreach (KeyValuePair header in param.Header) { request.Headers.Add(header.Key, header.Value); } } if (param.Timeout > 0) { request.Timeout = param.Timeout; } else { request.Timeout = 60 * 1000; } return request; } private void ClickRefresh(string className = "refresh") { if (cefWebBrowser.IsBrowserInitialized) { LocationPoint locationPoint = GetElementLocationPoint(cefWebBrowser, className); locationPoint.Left += SecurityHelper.GetRandom(10, 50); locationPoint.Top += SecurityHelper.GetRandom(5, 20); SimulateMouseLeftClick(cefWebBrowser.GetBrowser().GetHost(), locationPoint.Left, locationPoint.Top); } } private string GetBase64ImageString(string html, string imagePrefix, LocationPoint locationPoint) { string base64Image = Resove(html, imagePrefix, "\""); if (!string.IsNullOrEmpty(base64Image)) { byte[] byteArr = Convert.FromBase64String(base64Image); byte[] byteArrScale = ConvertImageToScaleSize(byteArr, locationPoint.Width, locationPoint.Height); string base64ImageScale = Convert.ToBase64String(byteArrScale); return base64ImageScale; } return string.Empty; } public static string Resove(string html, string prefix, string subfix) { int inl = html.IndexOf(prefix); if (inl == -1) { prefix = prefix.Replace("\"", "'"); subfix = subfix.Replace("\"", "'"); inl = html.IndexOf(prefix); } if (inl == -1) { return null; } inl += prefix.Length; if (!string.IsNullOrEmpty(subfix)) { int inl2 = html.IndexOf(subfix, inl); if (inl2 == -1) { return null; } string result = html.Substring(inl, inl2 - inl); return result; } else { string result = html.Substring(inl); return result; } } public static Bitmap ByteToBitmap(byte[] byteArr) { TypeConverter tc = TypeDescriptor.GetConverter(typeof(Bitmap)); Bitmap bitmap = (Bitmap)tc.ConvertFrom(byteArr); return bitmap; } public static byte[] ImageToByte(Image img) { ImageConverter converter = new ImageConverter(); return (byte[])converter.ConvertTo(img, typeof(byte[])); } public static byte[] ConvertImageToScaleSize(byte[] byteArr, int maxWidth = 0, int maxHeight = 0, bool expand = false, int quality = 100, int maxFileSize = 1024) { if (maxWidth == 0 && maxHeight == 0) { throw new Exception("宽度和高度不能同时为0"); } using (Bitmap bitmap = ByteToBitmap(byteArr)) { // Get the image's original width and height int originalWidth = bitmap.Width; int originalHeight = bitmap.Height; // To preserve the aspect ratio float ratioX = (float)maxWidth / (float)originalWidth; float ratioY = (float)maxHeight / (float)originalHeight; float ratio = Math.Min(ratioX, ratioY); if (ratio > 1) { // 图片像素不增大 if (!expand) { return ImageToByte(bitmap); } } if (maxHeight == 0) { // 高度不缩放 ratio = ratioX; } if (maxWidth == 0) { // 宽度不缩放 ratio = ratioY; } // New width and height based on aspect ratio int newWidth = (int)(originalWidth * ratio); int newHeight = (int)(originalHeight * ratio); // Convert other formats (including CMYK) to RGB. Bitmap bitmapTemplate = new Bitmap(newWidth, newHeight, PixelFormat.Format24bppRgb); // Draws the image in the specified size with quality mode set to HighQuality using (Graphics graphics = Graphics.FromImage(bitmapTemplate)) { graphics.CompositingQuality = CompositingQuality.HighSpeed; graphics.InterpolationMode = InterpolationMode.Low; graphics.SmoothingMode = SmoothingMode.HighSpeed; graphics.DrawImage(bitmap, 0, 0, newWidth, newHeight); using (Image img = (Image)bitmapTemplate.Clone()) { ImageCodecInfo imageCodecInfo = ImageCodecInfo.GetImageDecoders().SingleOrDefault(c => c.FormatID == ImageFormat.Jpeg.Guid); using (MemoryStream ms = new MemoryStream()) { img.Save(ms, imageCodecInfo, GetEncoderParameters(quality)); bitmapTemplate.Dispose(); return ms.ToArray(); } } } } } private static EncoderParameters GetEncoderParameters(int quality) { // Create an Encoder object for the Quality parameter. System.Drawing.Imaging.Encoder encoder = System.Drawing.Imaging.Encoder.Quality; // Create an EncoderParameters object. EncoderParameters encoderParameters = new EncoderParameters(1); // Save the image as a JPEG file with quality level. EncoderParameter encoderParameter = new EncoderParameter(encoder, quality); encoderParameters.Param[0] = encoderParameter; return encoderParameters; } public static Bitmap Base64StringToBitmap(string base64) { byte[] byteArr = Convert.FromBase64String(base64); TypeConverter tc = TypeDescriptor.GetConverter(typeof(Bitmap)); Bitmap bitmap = (Bitmap)tc.ConvertFrom(byteArr); return bitmap; } private void SlideCaptcha(string html, LocationPoint locationPoint) { string base64 = GetBase64ImageString(html, "data:image/jpeg;base64,", locationPoint); Bitmap bitmap = Base64StringToBitmap(base64); int holeLeft = CalculateNick(bitmap, 33); if (holeLeft > 0) { LocationPoint dragLocation = GetElementLocationPoint(cefWebBrowser, "slide-icon"); if (dragLocation.Width == 0) { dragLocation = GetElementLocationPoint(cefWebBrowser, "slide-btn-wrap"); dragLocation.Left += 25; dragLocation.Top += 35; } int startX = dragLocation.Left; int startY = dragLocation.Top; //startX = 90; //startY = 345; // CEFBrowser.SimulateMouseMove(cefWebBrowser.GetBrowser().GetHost(), startX, startY, startX + holeLeft + SecurityHelper.GetRandom(-8, 0), startY); CefMouseDragPDD(startX, startY, startX + holeLeft + SecurityHelper.GetRandom(-8, 0), startY); } } private void CefMouseDragPDD(int x1, int y1, int x2, int y2) { Thread.Sleep(100); Random random = new Random(); var host = cefWebBrowser.GetBrowser().GetHost(); Thread.Sleep(random.Next(5)); var ranX = -2 + SecurityHelper.GetRandom(0, 5); var ranY = -2 + SecurityHelper.GetRandom(0, 5); int xlen = x2 - x1 - ranX; int x = x1 + ranX; int y = y1 + ranY; host.SendMouseClickEvent(x, y, MouseButtonType.Left, false, 1, CefEventFlags.None);//按下鼠标左键 Thread.Sleep(200 + random.Next(200)); int z = x + xlen / 2 + SecurityHelper.GetRandom(0, xlen / 4); int times = 0; while (x < x2 - 4)//后半部分 { times++; x += 4 + random.Next(4); y = y - 1 + SecurityHelper.GetRandom(0, 3); Thread.Sleep(6 + times / 6 + random.Next(4)); host.SendMouseMoveEvent((int)x, (int)y, false, CefEventFlags.LeftMouseButton); // 移动鼠标 } x = x2 - 1 + SecurityHelper.GetRandom(0, 3); Thread.Sleep(100 + random.Next(100)); host.SendMouseMoveEvent((int)x, (int)y, false, CefEventFlags.LeftMouseButton); // 移动鼠标 Thread.Sleep(400 + random.Next(600)); host.SendMouseClickEvent(x, y, MouseButtonType.Left, true, 1, CefEventFlags.None); // 抬起鼠标左键 } private int CalculateNick(Bitmap bitmap, int v) { int iNickX = 0; int iDis = 5; //差异值 List lstiNickX = new List(); for (int y = 0; y < bitmap.Height; y++) { for (int x = bitmap.Width / 2; x < bitmap.Width - v; x++) { Color color1 = bitmap.GetPixel(x, y); Color color2 = bitmap.GetPixel(x + 1, y); int icolor1 = GetRGBFromColor(color1); int icolor2 = GetRGBFromColor(color2); double dDistance = GetDistance(color2, color1); if (dDistance > iDis && icolor2 < icolor1) { for (int i = 0; i < v + v / 2; i++) { iNickX = x + i; if (iNickX >= bitmap.Width - 1) { continue; } Color colorNickPre = bitmap.GetPixel(iNickX, y); Color colorNickAft = bitmap.GetPixel(iNickX + 1, y); int icolorNickPre = GetRGBFromColor(colorNickPre); int icolorNickAft = GetRGBFromColor(colorNickAft); double dNickDistance = GetDistance(colorNickAft, colorNickPre); if (dNickDistance > dDistance && icolorNickAft > icolorNickPre) { int iGap = Math.Abs(iNickX - x - v); if (iGap <= 2) { lstiNickX.Add(x); } break; } } } } } if (lstiNickX.Count > 0) { iNickX = GetRight(lstiNickX); } return iNickX; } private double GetDistance(Color color1, Color color2) { double y1, u1, v1, y2, u2, v2; y1 = 0.299 * color1.R + 0.587 * color1.G + 0.114 * color1.B; u1 = -0.14713 * color1.R - 0.28886 * color1.G + 0.436 * color1.B; v1 = 0.615 * color1.R - 0.51498 * color1.G - 0.10001 * color1.B; y2 = 0.299 * color2.R + 0.587 * color2.G + 0.114 * color2.B; u2 = -0.14713 * color2.R - 0.28886 * color2.G + 0.436 * color2.B; v2 = 0.615 * color2.R - 0.51498 * color2.G - 0.10001 * color2.B; return Math.Sqrt((y1 - y2) * (y1 - y2) + (u1 - u2) * (u1 - u2) + (v1 - v2) * (v1 - v2)); } private int GetRight(List lstiNickX) { var res = from n in lstiNickX group n by n into g orderby g.Count() descending select g; var gr = res.First(); return gr.Key; } private int GetRGBFromColor(Color color) { return (int)(((int)color.B << 16) | (ushort)(((ushort)color.G << 8) | color.R)); } public static async Task EvaluateScriptAsync(ChromiumWebBrowser cefWebBrowser, string js) { JavascriptResponse javascriptResponse = await cefWebBrowser.GetBrowser().MainFrame.EvaluateScriptAsync(js); return javascriptResponse; } public static ChromiumWebBrowser CreateChromiumWebBrowser(string url, bool isGlobal = true) { ChromiumWebBrowser cefBrowser = new ChromiumWebBrowser(url); if (!isGlobal) { cefBrowser.RequestContext = new RequestContext(GetRequestContextIsolateSettings()); } cefBrowser.BrowserSettings = new BrowserSettings { /*Plugins = CefState.Disabled*/ /*cef92*/ }; return cefBrowser; } public static RequestContextSettings GetRequestContextIsolateSettings() { RequestContextSettings requestContextSettings = new RequestContextSettings(); requestContextSettings.PersistSessionCookies = false; //cef138//requestContextSettings.PersistUserPreferences = false; return requestContextSettings; } public static async Task SetCookieAsync(string domain, string cookies, ICookieManager cookieManager = null) { try { foreach (string cookie in cookies.Split(new string[] { ";" }, StringSplitOptions.RemoveEmptyEntries)) { int i = cookie.IndexOf('='); if (i > 0) { string name = cookie.Substring(0, i).ToString().Trim(); string value = cookie.Substring(i + 1).ToString().Trim(); if (name.ToLower() == "expires" || name.ToLower() == "path" || name.ToLower() == "domain") { continue; } CefSharp.Cookie newCookie = new CefSharp.Cookie { Domain = domain, Name = name, Value = value, Path = "/" }; if (cookieManager == null) { bool result = await Cef.GetGlobalCookieManager().SetCookieAsync("http://" + domain, newCookie); } else { bool result = await cookieManager.SetCookieAsync("http://" + domain, newCookie); } } } } catch { } } //cancellationTokenSource = new CancellationTokenSource(); bool getWay = false; private async void CefWebBrowser_FrameLoadEnd(object sender, CefSharp.FrameLoadEndEventArgs e) { if (e.Frame.IsMain) { string url = e.Frame.Url; string html = await e.Frame.GetSourceAsync(); //if (url == "https://yangkeduo.com/personal.html") // return; await SetCookieAsync(".yangkeduo.com", "PDDAccessToken=" + pddAccessToken, cefWebBrowser.RequestContext.GetCookieManager(null)); if (url== "https://mobile.yangkeduo.com/portal.html") cefWebBrowser.Load(PersonUrl); //if (url.Contains("VerifyAuthToken")) //{ // if (getWay) // return; // getWay = true; // AutoCaptcha(); //} } } private void btnValidateLogin_Click(object sender, EventArgs e) { cefWebBrowser.Load(PersonUrl); } private void btnValidateSearchStatus_Click(object sender, EventArgs e) { cefWebBrowser.Load(SearchUrl); } private void btnValidateProductDetailStatus_Click(object sender, EventArgs e) { cefWebBrowser.Load(GoodsUrl); } private void btnSaveToken_Click(object sender, EventArgs e) { TData obj = new TData(); obj.Tag = 1; obj.Result = pddAccessToken; this.onSaveComplete(obj); this.Close(); } private void btnDeleteToken_Click(object sender, EventArgs e) { TData obj = new TData(); obj.Tag = 0; obj.Result = pddAccessToken; this.onSaveComplete(obj); this.Close(); } public static string GetElementLocation(ChromiumWebBrowser cefWebBrowser, string elementIdOrClass) { string js = @"function getElementLocation() { var element = document.getElementById('{0}'); if (element == null || element == undefined) { var elements = document.getElementsByClassName('{0}'); if(elements){ element = elements[0]; } } if (element == null || element == undefined) { return '0,0,0,0'; } return element.getBoundingClientRect().left.toString() + ',' + element.getBoundingClientRect().top.toString() + ',' + (element.width?element.width.toString():'0') + ',' + (element.height?element.height.toString():'0'); } getElementLocation(); "; string formatJs = js.Replace("{0}", elementIdOrClass); Task task = cefWebBrowser.EvaluateScriptAsync(formatJs); task.Wait(); string location = task.Result.Result.ParseToString(); return location; } public static int DecimalPointParseToInt(string str) { try { string temp = str.ParseToString(); int i = temp.IndexOf('.'); if (i > 0) { temp = temp.Substring(0, i); } return Convert.ToInt32(temp); } catch { return 0; } } public static LocationPoint GetElementLocationPoint(ChromiumWebBrowser cefWebBrowser, string elementIdOrClass) { LocationPoint locationPoint = new LocationPoint(); string location = GetElementLocation(cefWebBrowser, elementIdOrClass); if (location.Contains(",")) { string[] xy = location.Split(','); locationPoint.Left = DecimalPointParseToInt(xy[0]); locationPoint.Top = DecimalPointParseToInt(xy[1]); locationPoint.Width = DecimalPointParseToInt(xy[2]); locationPoint.Height = DecimalPointParseToInt(xy[3]); } return locationPoint; } public static void SimulateMouseLeftClick(IBrowserHost host, int x, int y) { Random random = new Random(Guid.NewGuid().GetHashCode()); host.SendMouseClickEvent(x, y, MouseButtonType.Left, false, 1, CefEventFlags.None); // 按下鼠标左键 Thread.Sleep(75 + random.Next(50)); host.SendMouseClickEvent(x, y, MouseButtonType.Left, true, 1, CefEventFlags.None); // 松开鼠标左键 Thread.Sleep(300); } public string GetProductDetail(string url, string pddAccessToken) { HttpParam httpParam = new HttpParam { Url = url }; AddRequestParamForPinDuoDuoWeb(httpParam, pddAccessToken); string html = Get(httpParam); return html; } public static string ReadResponse(HttpParam httpParam, HttpWebResponse response) { using (Stream stream = DecompressStream(response)) { using (StreamReader streamReader = new StreamReader(stream, httpParam.ResponseEncoding)) { return streamReader.ReadToEnd(); } } } public static string Get(HttpParam httpParam) { try { HttpWebRequest request = GetHttpWebRequest(httpParam); request.Method = "Get"; return ReadResponse(httpParam, (HttpWebResponse)request.GetResponse()); } catch (Exception ex) { return string.Empty; } } public static T[] SplitToArray(string value, char split) { T[] arr = value.Split(new string[] { split.ToString() }, StringSplitOptions.RemoveEmptyEntries).CastSuper().ToArray(); return arr; } public static Dictionary GetCookieDictionary(string cookie) { Dictionary dict = new Dictionary(); string[] cookieArr = SplitToArray(cookie, ';'); foreach (string line in cookieArr) { int index = line.IndexOf('='); if (index > 0) { string key = line.Substring(0, index); string value = line.Substring(index + 1); if (!dict.ContainsKey(key)) { dict.Add(key, value); } } } return dict; } private void AddRequestParamForPinDuoDuoWeb(HttpParam httpParam, string accessToken) { httpParam.Cookie = "PDDAccessToken=" + accessToken; httpParam.UserAgent = userAgent; if (!string.IsNullOrEmpty(httpParam.Cookie)) { Dictionary cookieDict = GetCookieDictionary(httpParam.Cookie); string key = "VerifyAuthToken"; if (cookieDict.ContainsKey(key)) { AddHeader(httpParam, key, cookieDict[key]); } } } public static void AddHeader(HttpParam httpParam, string key, string value) { if (httpParam.Header == null) { httpParam.Header = new Dictionary(); } httpParam.Header.Remove(key); httpParam.Header.Add(key, value); } public TData CheckAccessToken(string pddAccessToken) { TData obj = new TData(); obj.Result = new PinDuoDuoTokenInfo { PDDAccessToken = pddAccessToken }; string url = BaseClass.NewUrl + "/personal.html"; string refere = ""; string html = GetPostTaobaoHtml.UploadTaobao(url, refere, true, "PDDAccessToken=" + pddAccessToken); if (string.IsNullOrEmpty(html)) { obj.Result.LoginStatus = obj.Result.ProductDetailStatus = -1; } else if (html.Contains("我的订单")) { obj.Result.LoginStatus = 1; url = "http://yangkeduo.com/goods.html?goods_id=17252982258"; html = GetProductDetail(url, pddAccessToken); if (!IsNotPinDuoDuoProductDetail(html)) { if (html.Contains("垃圾桶")) { obj.Result.ProductDetailStatus = 1; } else { html = GetProductDetailByApi(17252982258, pddAccessToken); } } if (html.Contains("goodsName") || html.Contains("垃圾桶")) { obj.Result.ProductDetailStatus = 1; } else { obj.Result.ProductDetailStatus = -1; obj.Result.IsCaptcha = true; } url = "http://yangkeduo.com/search_result.html?search_key=垃圾桶"; html = GetPostTaobaoHtml.UploadTaobao(url, refere, true, "PDDAccessToken=" + pddAccessToken); if (html.Contains("goodsName")) { obj.Result.SearchStatus = 1; } else { int keyWordIndex = url.LastIndexOf('='); if (keyWordIndex > 0) { var keyWord = url.Substring(keyWordIndex + 1); if (html.Contains(keyWord)) { obj.Result.SearchStatus = -1; } } obj.Result.IsCaptcha = true; } } else { obj.Result.LoginStatus = -1; obj.Result.IsCaptcha = true; } return obj; } public static bool IsNotPinDuoDuoProductDetail(string html) { return !html.Contains("topGallery") && !html.Contains("商品不存在") && !html.Contains("商品已下架") && !html.Contains("\"mall\""); } public string GetProductDetailByApi(long productId, string pddAccessToken) { string url = "https://yangkeduo.com/proxy/api/api/oak/integration/render?pdduid={0}"; HttpParam httpParam = new HttpParam(); string cookie = "PDDAccessToken=" + pddAccessToken; Dictionary cookieDict = GetCookieDictionary(cookie); string key = "pdd_user_id"; if (cookieDict.ContainsKey(key)) { httpParam.Url = string.Format(url, cookieDict[key]); } else { httpParam.Url = string.Format(url, 0); } httpParam.ContentType = "application/json;charset=UTF-8"; httpParam.PostData = JsonConvert.SerializeObject(new { page_version = "7", goods_id = productId, page_from = 0, hostname = "yangkeduo.com", client_time = GetUnixMilliSecondTimeStamp(DateTime.Now) + BaseClass.TimeDifferent * 1000 }); AddHeader(httpParam, "AccessToken", pddAccessToken); AddRequestParamForPinDuoDuoWeb(httpParam, pddAccessToken); string html = Post(httpParam); if (html.Contains("goods_id") && html.Contains("mall_id")) { JObject jObj = JObject.Parse(html); return html; } return ""; } public static long GetUnixMilliSecondTimeStamp(DateTime dt) { DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1)); return (long)(dt - startTime).TotalMilliseconds; } public static string Post(HttpParam httpParam) { try { HttpWebRequest request = GetHttpWebRequest(httpParam); request.Method = "Post"; request.ServicePoint.Expect100Continue = false; byte[] postDataByte = Encoding.UTF8.GetBytes(httpParam.PostData); request.ContentLength = postDataByte.Length; request.AllowAutoRedirect = false; using (Stream requestStream = request.GetRequestStream()) { requestStream.Write(postDataByte, 0, postDataByte.Length); } return ReadResponse(httpParam, (HttpWebResponse)request.GetResponse()); } catch { return ""; } } } public class LocationPoint { public int Left { get; set; } public int Top { get; set; } public int Width { get; set; } public int Height { get; set; } } public class SecurityHelper { private static readonly string DESKey = "20190813"; /// /// 用MD5加密字符串,可选择生成16位或者32位的加密字符串 /// /// 待加密的字符串 /// 位数,一般取值16 或 32 /// 返回的加密后的字符串 public static string MD5Encrypt(string str, int bit = 32) { MD5CryptoServiceProvider md5Hasher = new MD5CryptoServiceProvider(); byte[] hashedDataBytes; hashedDataBytes = md5Hasher.ComputeHash(Encoding.GetEncoding("gb2312").GetBytes(str)); StringBuilder sb = new StringBuilder(); foreach (byte i in hashedDataBytes) { sb.Append(i.ToString("x2")); } if (bit == 16) { return sb.ToString().Substring(8, 16).ToUpper(); } else { return sb.ToString().ToUpper(); } } public static string GetGuid(bool replaceDash = false) { string guid = Guid.NewGuid().ToString(); if (replaceDash) { guid = guid.Replace("-", string.Empty); } return guid; } public static bool IsSafeSqlParam(string value) { return !Regex.IsMatch(value, @"[-|;|,|\/|\(|\)|\[|\]|\}|\{|%|@|\*|!|\']"); } public static string DESEncrypt(string encrypt, string key = "") { if (string.IsNullOrEmpty(key)) { key = DESKey; } try { DESCryptoServiceProvider oDESCryptoServiceProvider = new DESCryptoServiceProvider(); byte[] inputByteArray = Encoding.Default.GetBytes(encrypt); oDESCryptoServiceProvider.Key = ASCIIEncoding.ASCII.GetBytes(DESKey); oDESCryptoServiceProvider.IV = ASCIIEncoding.ASCII.GetBytes(DESKey); MemoryStream oMemoryStream = new MemoryStream(); CryptoStream oCryptoStream = new CryptoStream(oMemoryStream, oDESCryptoServiceProvider.CreateEncryptor(), CryptoStreamMode.Write); oCryptoStream.Write(inputByteArray, 0, inputByteArray.Length); oCryptoStream.FlushFinalBlock(); StringBuilder sb = new StringBuilder(); foreach (byte b in oMemoryStream.ToArray()) { sb.AppendFormat("{0:X2}", b); } sb.ToString(); return sb.ToString(); } catch (System.Exception ex) { return string.Empty; } } public static string DESDecrypt(string decrypt, string key = "") { if (string.IsNullOrEmpty(key)) { key = DESKey; } try { DESCryptoServiceProvider oDESCryptoServiceProvider = new DESCryptoServiceProvider(); byte[] inputByteArray = new byte[decrypt.Length / 2]; for (int x = 0; x < decrypt.Length / 2; x++) { int i = (Convert.ToInt32(decrypt.Substring(x * 2, 2), 16)); inputByteArray[x] = (byte)i; } oDESCryptoServiceProvider.Key = ASCIIEncoding.ASCII.GetBytes(key); oDESCryptoServiceProvider.IV = ASCIIEncoding.ASCII.GetBytes(key); MemoryStream oMemoryStream = new MemoryStream(); CryptoStream oCryptoStream = new CryptoStream(oMemoryStream, oDESCryptoServiceProvider.CreateDecryptor(), CryptoStreamMode.Write); oCryptoStream.Write(inputByteArray, 0, inputByteArray.Length); oCryptoStream.FlushFinalBlock(); return Encoding.Default.GetString(oMemoryStream.ToArray()); } catch (System.Exception ex) { return string.Empty; } } public static bool IsBase64(string str) { try { string base64Pattern = "^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{4}|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)$"; return Regex.IsMatch(str, base64Pattern); } catch (Exception ex) { return false; } } public static string Base64Encrypt(string encrypt) { try { byte[] bytes = Encoding.UTF8.GetBytes(encrypt); string base64 = Convert.ToBase64String(bytes); return base64; } catch (Exception ex) { return encrypt; } } public static string Base64Decrypt(string decrypt) { try { byte[] bytes = Convert.FromBase64String(decrypt); string base64 = Encoding.UTF8.GetString(bytes); return base64; } catch (Exception ex) { return decrypt; } } public static string HMACSHA256(string encrypt, string key = "") { var encoding = new ASCIIEncoding(); byte[] keyByte = encoding.GetBytes(key); byte[] encryptByte = encoding.GetBytes(encrypt); using (var hmacsha256 = new HMACSHA256(keyByte)) { byte[] hashmessage = hmacsha256.ComputeHash(encryptByte); StringBuilder builder = new StringBuilder(); for (int i = 0; i < hashmessage.Length; i++) { builder.Append(hashmessage[i].ToString("X2")); } return builder.ToString(); } } public static int GetRandSeed() { byte[] buffer = Guid.NewGuid().ToByteArray(); int iSeed = BitConverter.ToInt32(buffer, 0); return iSeed; } public static int GetRandom(int min, int max) { return new Random(GetRandSeed()).Next(min, max + 1); } } }