Files
KJD_WebService/TEMUKJD/ToolForms/Old/PinDuoDuoCaptchaForm.cs
T

1386 lines
58 KiB
C#

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<string> 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<string, int> moYunCaptchaHashDict = new Dictionary<string, int>();
while (true)
{
try
{
Console.WriteLine("ThreadId:" + Thread.CurrentThread.ManagedThreadId);
//if (cancellationTokenSource.IsCancellationRequested)
//{
// return;
//}
if (captchaTimes > maxCaptchaTimes)
{
PinduoduoProductCollect.PinDuoDuoTokenList.RemoveAll(p => p.PDDAccessToken == pddAccessToken);
TData<PinDuoDuoTokenInfo> 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<PinDuoDuoTokenInfo> objToken = CheckAccessToken(pddAccessToken);
if (objToken.Result.LoginStatus == (int)TokenStatus.Invalid)
{
cancellationTokenSource.Cancel();
return;
}
}
else if (html.Contains("<div class=\"alert-goto-app-cancel\">收起</div>"))
{
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<string, int> 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\">", "</div>");
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<int>();
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<string> 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<string, int> 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, @"(<head[\w\W]*?</head>|<script[\w\W]*?</script>|<style[\w\W]*?</style>|<!--[\w\W]*?-->)", ""), "(<[^>]*?>)", "");
return html;
}
public async Task<string> 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<string> 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<string> 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<string, string> 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<int> lstiNickX = new List<int>();
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<int> 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<JavascriptResponse> 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<string> obj = new TData<string>();
obj.Tag = 1;
obj.Result = pddAccessToken;
this.onSaveComplete(obj);
this.Close();
}
private void btnDeleteToken_Click(object sender, EventArgs e)
{
TData<string> obj = new TData<string>();
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<JavascriptResponse> 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<T>(string value, char split)
{
T[] arr = value.Split(new string[] { split.ToString() }, StringSplitOptions.RemoveEmptyEntries).CastSuper<T>().ToArray();
return arr;
}
public static Dictionary<string, string> GetCookieDictionary(string cookie)
{
Dictionary<string, string> dict = new Dictionary<string, string>();
string[] cookieArr = SplitToArray<string>(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<string, string> 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<string, string>();
}
httpParam.Header.Remove(key);
httpParam.Header.Add(key, value);
}
public TData<PinDuoDuoTokenInfo> CheckAccessToken(string pddAccessToken)
{
TData<PinDuoDuoTokenInfo> obj = new TData<PinDuoDuoTokenInfo>();
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<string, string> 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";
/// <summary>
/// 用MD5加密字符串,可选择生成16位或者32位的加密字符串
/// </summary>
/// <param name="str">待加密的字符串</param>
/// <param name="bit">位数,一般取值16 或 32</param>
/// <returns>返回的加密后的字符串</returns>
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);
}
}
}