479 lines
20 KiB
C#
479 lines
20 KiB
C#
using Api.Framework.Cps;
|
||
using CsharpHttpHelper;
|
||
using CsharpHttpHelper.Enum;
|
||
using Newtonsoft.Json;
|
||
using Newtonsoft.Json.Linq;
|
||
using System;
|
||
using System.Collections;
|
||
using System.Collections.Generic;
|
||
using System.Linq;
|
||
using System.Text.RegularExpressions;
|
||
using System.Threading;
|
||
using System.Threading.Tasks;
|
||
|
||
namespace Api.Framework.Tools
|
||
{
|
||
/// <summary>
|
||
/// 拼多多解析助手
|
||
/// </summary>
|
||
public class PDDHelper
|
||
{
|
||
///// <summary>
|
||
///// 随机对象
|
||
///// </summary>
|
||
//private static Random random = new Random(Guid.NewGuid().GetHashCode());
|
||
|
||
///// <summary>
|
||
///// 获取随机公共拼多多查询商品信息账号
|
||
///// </summary>
|
||
///// <returns></returns>
|
||
//public static fl_cps_member RandomGuidePddMembers()
|
||
//{
|
||
// try
|
||
// {
|
||
// //return CpsClient.GuideMembers[0];
|
||
// return CpsClient.GuideMembers[random.Next(0, CpsClient.GuideMembers.Count)];
|
||
// }
|
||
// catch (Exception ex)
|
||
// { }
|
||
// return CpsClient.GuideMembers.FirstOrDefault();
|
||
//}
|
||
|
||
/// <summary>
|
||
/// 多多进宝app中获取高佣商品的招商id
|
||
/// </summary>
|
||
/// <param name="goodsid">商id</param>
|
||
/// <returns></returns>
|
||
public static string FindGoodsSign_H5(string goodsid)
|
||
{
|
||
try
|
||
{
|
||
try
|
||
{
|
||
if (GoodsCacheDic.ContainsKey(goodsid))
|
||
{
|
||
var GoodsCache = GoodsCacheDic[goodsid];
|
||
if (GoodsCache.GetTime.AddHours(1) > DateTime.Now)
|
||
return GoodsCache.GoodsSign;
|
||
GoodsCacheDic.Remove(goodsid);
|
||
}
|
||
}
|
||
catch (Exception)
|
||
{ }
|
||
|
||
for (int i = 0; i < 3; i++)
|
||
{
|
||
try
|
||
{
|
||
HttpHelper http = new HttpHelper();
|
||
HttpItem item = new HttpItem()
|
||
{
|
||
URL = "https://jinbaoh5.pinduoduo.com/network_h5/weak_auth/goods/query_goodslist",
|
||
Method = "POST",
|
||
Timeout = 100000,
|
||
ReadWriteTimeout = 30000,
|
||
IsToLower = false,
|
||
Cookie = "",
|
||
UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:18.0) Gecko/20100101 Firefox/18.0",
|
||
Accept = "text/html, application/xhtml+xml, */*",
|
||
ContentType = "application/json",
|
||
Referer = "",
|
||
Allowautoredirect = false,
|
||
AutoRedirectCookie = false,
|
||
Postdata = @"{""hasCoupon"": false,""pageNumber"": 1,""sortType"": 0,""listId"": """",""pageSize"":10,""keyword"":""" + goodsid + @"""}",
|
||
ResultType = ResultType.String
|
||
};
|
||
HttpResult result = http.GetHtml(item);
|
||
string html = result.Html;
|
||
|
||
var jobj = JObject.Parse(html);
|
||
if (!(bool)jobj["success"])
|
||
continue;
|
||
else
|
||
{
|
||
var goodsList = (JArray)jobj["result"]["goodsList"];
|
||
for (int z = 0; z < goodsList.Count; z++)
|
||
{
|
||
//var zsDuoId = (int)goodsList[0]["zsDuoId"];
|
||
//if (zsDuoId == 0) return string.Empty;
|
||
//return zsDuoId.ToString();
|
||
var goodsSign = goodsList[0]["goodsSign"].ToString();
|
||
if (!string.IsNullOrWhiteSpace(goodsSign))
|
||
{
|
||
return goodsSign;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{ }
|
||
finally
|
||
{
|
||
Thread.Sleep(200);
|
||
}
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{ }
|
||
return string.Empty;
|
||
}
|
||
|
||
private static Dictionary<string, GoodsCahce> GoodsCacheDic = new Dictionary<string, GoodsCahce>();
|
||
|
||
/// <summary>
|
||
/// 清理缓存时间
|
||
/// </summary>
|
||
private static DateTime remove_cache_time = DateTime.Now;
|
||
|
||
#region 临时类
|
||
class GoodsCahce
|
||
{
|
||
public string GoodsSign { get; set; }
|
||
public DateTime GetTime { get; set; }
|
||
}
|
||
#endregion
|
||
|
||
/// <summary>
|
||
/// 缓存异常Cps集合
|
||
/// </summary>
|
||
private static Dictionary<string, string> CacheErrCpsDic = new Dictionary<string, string>();
|
||
|
||
/// <summary>
|
||
/// 获取商品高佣信息
|
||
/// </summary>
|
||
/// <param name="api">PinduoduoApi对象</param>
|
||
/// <param name="pid">推广位pid</param>
|
||
/// <param name="goods_id">商品id</param>
|
||
/// <param name="isBind">是否授权绑定</param>
|
||
/// <returns></returns>
|
||
public static ArrayList FindSendGuideGoodsInfo(PinduoduoApi api, string pid, string goods_id, bool isBind = false)
|
||
{
|
||
#region 清理缓存
|
||
if (remove_cache_time.AddHours(5) < DateTime.Now)
|
||
{
|
||
remove_cache_time = DateTime.Now;
|
||
Task.Run(() =>
|
||
{
|
||
try
|
||
{
|
||
var tmps = GoodsCacheDic.Where(f => f.Value.GetTime.AddHours(1) < DateTime.Now).ToList();
|
||
if (tmps == null || tmps.Count == 0) return;
|
||
for (int i = 0; i < tmps.Count; i++)
|
||
{
|
||
try
|
||
{
|
||
GoodsCacheDic.Remove(tmps[i].Key);
|
||
}
|
||
catch (Exception)
|
||
{ }
|
||
}
|
||
}
|
||
catch (Exception)
|
||
{ }
|
||
});
|
||
}
|
||
#endregion
|
||
|
||
//获取高佣H5信息
|
||
var goodsSign = FindGoodsSign_H5(goods_id);
|
||
if (!string.IsNullOrWhiteSpace(goodsSign))
|
||
{
|
||
try
|
||
{
|
||
if (!GoodsCacheDic.ContainsKey(goods_id))
|
||
GoodsCacheDic[goods_id] = new GoodsCahce() { GoodsSign = goodsSign, GetTime = DateTime.Now };
|
||
}
|
||
catch (Exception)
|
||
{ }
|
||
if (!isBind)//true-已绑定;false-未绑定
|
||
{ //公用的账号
|
||
//var guideCps = RandomGuidePddMembers();
|
||
//if (guideCps == null) throw new Exception("公共账号异常");
|
||
//var guideApi = CpsClient.CreatePinduoduoRequest(guideCps);
|
||
//if (guideApi == null) throw new Exception("创建公共请求对象异常");
|
||
//var fgInfo = FindGoodsInfo(guideApi, goodsSign, guideCps.cookies);
|
||
//if (fgInfo != null)
|
||
// return fgInfo;
|
||
return null;
|
||
}
|
||
var goodsInfo = FindGoodsInfo(api, goodsSign, pid);
|
||
return goodsInfo;
|
||
}
|
||
else
|
||
{
|
||
PinduoduoApi apiTmp = null;
|
||
var pidTmp = pid;
|
||
var cpsUsername = api.Member.username;
|
||
//无法获取高佣这里获取低佣
|
||
for (int i = 0; i < 2; i++)
|
||
{
|
||
Dictionary<string, object> obj_ = null;
|
||
//if (!isBind)//true-已绑定;false-未绑定
|
||
if (CacheErrCpsDic.ContainsKey(cpsUsername) || !isBind)//true-已绑定;false-未绑定
|
||
{ //公用的账号
|
||
//var guideCps = RandomGuidePddMembers();
|
||
//if (guideCps == null) throw new Exception("公共账号异常");
|
||
//var guideApi = CpsClient.CreatePinduoduoRequest(guideCps);
|
||
//if (guideApi == null) throw new Exception("创建公共请求对象异常");
|
||
//apiTmp = guideApi;
|
||
//pidTmp = guideCps.cookies;
|
||
}
|
||
else
|
||
apiTmp = api;
|
||
if (apiTmp == null) continue;
|
||
try
|
||
{
|
||
obj_ = apiTmp.SendPinduoduo("pdd.ddk.oauth.goods.search", new
|
||
{
|
||
keyword = goods_id,
|
||
pid = pidTmp,
|
||
//custom_parameters = "{\"uid\":\"602172712\",\"sid\":\"jdds\"}"
|
||
//page = 1,
|
||
//page_size = 10,
|
||
//with_coupon = true
|
||
});
|
||
|
||
if (obj_ == null) throw new Exception("创建拼多多API请求失败3");
|
||
|
||
var goods_detail_response = obj_["goods_search_response"] as Dictionary<string, object>;
|
||
var goods_list = goods_detail_response["goods_list"] as ArrayList;
|
||
|
||
if (goods_list != null && goods_list.Count != 0)
|
||
{
|
||
var tmp = goods_list[0] as Dictionary<string, object>;
|
||
if (tmp != null && tmp.Count == 2)
|
||
return FindGoodsInfo(api, tmp["goods_sign"].ToString(), pid);
|
||
}
|
||
|
||
|
||
return goods_list;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
if (ex.Message.Contains("涉嫌爬虫或本地缓存商品信息"))
|
||
{
|
||
CacheErrCpsDic[apiTmp.Member.username] = apiTmp.Member.username;
|
||
cpsUsername = apiTmp.Member.username;
|
||
}
|
||
EventClient.OnEvent(null, $"拼多多:public -> {apiTmp.Member.username} 异常:{ex.Message} - {ex.StackTrace} - {(obj_ == null ? string.Empty : JsonConvert.SerializeObject(obj_))}");
|
||
}
|
||
finally
|
||
{
|
||
Thread.Sleep(200);
|
||
}
|
||
}
|
||
}
|
||
return null;
|
||
}
|
||
|
||
///// <summary>
|
||
///// 获取商品高佣信息
|
||
///// </summary>
|
||
///// <param name="api">PinduoduoApi对象</param>
|
||
///// <param name="data">参数</param>
|
||
///// <returns></returns>
|
||
//public static ArrayList FindSendGuideGoodsInfo(PinduoduoApi api, object data)
|
||
//{
|
||
// //公用的账号
|
||
// var guideCps = RandomGuidePddMembers();
|
||
// if (guideCps == null) throw new Exception("公共账号异常");
|
||
// var guideApi = CpsClient.CreatePinduoduoRequest(guideCps);
|
||
// if (guideApi == null) throw new Exception("创建公共请求对象异常");
|
||
// var obj_ = guideApi.SendPinduoduo("pdd.ddk.oauth.goods.search", data);
|
||
// if (obj_ == null) throw new Exception("创建拼多多API请求失败2");
|
||
// //解析商品,获取商品的信息
|
||
// var goods_detail_response = obj_["goods_search_response"] as Dictionary<string, object>;
|
||
// return goods_detail_response["goods_list"] as ArrayList;
|
||
//}
|
||
|
||
/// <summary>
|
||
/// 查询商品信息(自己的账号,以保佣金比例的正确性)
|
||
/// </summary>
|
||
/// <param name="api">PinduoduoApi对象</param>
|
||
/// <param name="goods_sign">商品sign</param>
|
||
/// <param name="pid">推广位pid</param>
|
||
/// <returns></returns>
|
||
public static ArrayList FindGoodsInfo(PinduoduoApi api, string goods_sign, string pid)
|
||
{
|
||
try
|
||
{
|
||
var obj_ = api.SendPinduoduo("pdd.ddk.oauth.goods.search", new { goods_sign_list = $"[\"{goods_sign}\"]", pid = pid });
|
||
|
||
if (obj_ == null) throw new Exception("创建拼多多API请求失败2");
|
||
//解析商品,获取商品的信息
|
||
var goods_detail_response = obj_["goods_search_response"] as Dictionary<string, object>;
|
||
return goods_detail_response["goods_list"] as ArrayList;
|
||
|
||
|
||
//var obj_ = api.SendPinduoduo("pdd.ddk.goods.detail", new { goods_sign = goods_sign, pid = pid });
|
||
|
||
//if (obj_ == null) throw new Exception("创建拼多多API请求失败2");
|
||
////解析商品,获取商品的信息
|
||
//var goods_detail_response = obj_["goods_detail_response"] as Dictionary<string, object>;
|
||
//return goods_detail_response["goods_details"] as ArrayList;
|
||
|
||
|
||
|
||
}
|
||
catch (Exception ex)
|
||
{ }
|
||
return null;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 查询商品信息(自己的账号,以保佣金比例的正确性)
|
||
/// </summary>
|
||
/// <param name="api">PinduoduoApi对象</param>
|
||
/// <param name="goods_sign">商品sign</param>
|
||
/// <param name="pid">推广位pid</param>
|
||
/// <returns></returns>
|
||
public static ArrayList FindSendGuideGoodsInfo(PinduoduoApi api, object data)
|
||
{
|
||
try
|
||
{
|
||
var obj_ = api.SendPinduoduo("pdd.ddk.oauth.goods.search", data);
|
||
if (obj_ == null) throw new Exception("创建拼多多API请求失败2");
|
||
//解析商品,获取商品的信息
|
||
var goods_detail_response = obj_["goods_search_response"] as Dictionary<string, object>;
|
||
return goods_detail_response["goods_list"] as ArrayList;
|
||
}
|
||
catch (Exception ex)
|
||
{ }
|
||
return null;
|
||
}
|
||
|
||
|
||
|
||
/// <summary>
|
||
/// 获取拼多多链接中的商品ID
|
||
/// </summary>
|
||
/// <param name="url">拼多多商品连接</param>
|
||
/// <returns></returns>
|
||
public static string GetPddGoodsID(string url)
|
||
{
|
||
bool flag = false;
|
||
if (url.Contains("goods_id")) flag = true;
|
||
|
||
var _url = HttpExtend.RegexMatchUrl(url);
|
||
if (!flag && !string.IsNullOrWhiteSpace(_url))//有链接的情况
|
||
{
|
||
//TODO 这里好像还有短连接 目前忘记了短连接的格式
|
||
|
||
url = _url;
|
||
if (Regex.IsMatch(url, "(http[s]?://url.cn|http[s]?://a.toutiaonanren.com|http[s]?://p.pinduoduo.com)", RegexOptions.IgnoreCase))
|
||
{
|
||
//可能为短网址//跳转换成真实地址
|
||
url = HttpHelper.URLDecode(GetLocation(url));
|
||
if (url == null || !url.Contains("goods_id")) return string.Empty;
|
||
else flag = true;
|
||
}
|
||
else
|
||
flag = true;
|
||
}
|
||
if (flag)
|
||
{
|
||
var reg = Regex.Match(url, @"goods_sign=(?<goods_sign>[^&]{30,70})", RegexOptions.IgnoreCase);//goods_sign=E9f2ompO5KFHjG7BxODcTu-k-n-0MFtO_JeyAMXRb5&
|
||
if (reg.Success)
|
||
return reg.Groups["goods_sign"].ToString();
|
||
reg = Regex.Match(url, @"goods_id=(?<good_id>\d{4,})", RegexOptions.IgnoreCase);
|
||
if (reg.Success)
|
||
return reg.Groups["good_id"].ToString();
|
||
reg = Regex.Match(HttpHelper.URLDecode(url), @"goods_id=(?<good_id>\d{4,})", RegexOptions.IgnoreCase);
|
||
if (reg.Success)
|
||
return reg.Groups["good_id"].ToString();
|
||
reg = Regex.Match(HttpHelper.URLDecode(url), @"pinduoduo(?:.*)?goodsId=(?<good_id>\d{4,})", RegexOptions.IgnoreCase);
|
||
if (reg.Success)
|
||
return reg.Groups["good_id"].ToString();
|
||
}
|
||
return string.Empty;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取页面的真实Location的地址(比如:获取短连接的真实地址)
|
||
/// </summary>
|
||
/// <param name="url">链接</param>
|
||
/// <returns></returns>
|
||
private static string GetLocation(string url)
|
||
{
|
||
HttpHelper http = new HttpHelper();
|
||
HttpItem item = new HttpItem()
|
||
{
|
||
URL = url,
|
||
Method = "GET",
|
||
Timeout = 100000,
|
||
ReadWriteTimeout = 30000,
|
||
IsToLower = false,
|
||
Cookie = "",
|
||
UserAgent = "Opera/9.27 (Windows NT 5.2; U; zh-cn)",
|
||
Accept = "text/html, application/xhtml+xml, */*",
|
||
ContentType = "text/html",
|
||
Referer = "",
|
||
Postdata = "",
|
||
};
|
||
HttpResult result = http.GetHtml(item);
|
||
return result.Header.Get("Location");
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 获取单人团 / 多人团地址
|
||
/// </summary>
|
||
/// <param name="api">PinduoduoApi对象</param>
|
||
/// <param name="obj">接口的必要参数</param>
|
||
/// <returns></returns>
|
||
public string GetShoppingUrl(PinduoduoApi api, object obj)
|
||
{
|
||
for (int i = 0; i < 3; i++)
|
||
{
|
||
try
|
||
{
|
||
var goods_promotion_url_generate_response = api.SendPinduoduo("pdd.ddk.oauth.goods.prom.url.generate", obj)["goods_promotion_url_generate_response"] as Dictionary<string, object>;
|
||
|
||
var goods_promotion_url_list = goods_promotion_url_generate_response["goods_promotion_url_list"] as ArrayList;
|
||
string url = string.Empty;
|
||
foreach (var _url in goods_promotion_url_list)
|
||
{
|
||
//return (_url as Dictionary<string, object>)["short_url"].ToString();
|
||
return (_url as Dictionary<string, object>)["mobile_short_url"].ToString();
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{ }
|
||
Thread.Sleep(100);
|
||
}
|
||
return string.Empty;
|
||
}
|
||
|
||
/// <summary>
|
||
///
|
||
/// </summary>
|
||
/// <param name="api">PinduoduoApi对象</param>
|
||
/// <param name="obj">参数</param>
|
||
/// <returns></returns>
|
||
public Dictionary<string, object> GetShoppingUrls(PinduoduoApi api, object obj)
|
||
{
|
||
for (int i = 0; i < 2; i++)
|
||
{
|
||
try
|
||
{
|
||
var goods_promotion_url_generate_response = api.SendPinduoduo("pdd.ddk.oauth.goods.prom.url.generate", obj)["goods_promotion_url_generate_response"] as Dictionary<string, object>;
|
||
|
||
var goods_promotion_url_list = goods_promotion_url_generate_response["goods_promotion_url_list"] as ArrayList;
|
||
string url = string.Empty;
|
||
foreach (var _url in goods_promotion_url_list)
|
||
{
|
||
return (_url as Dictionary<string, object>);
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
EventClient.OnEvent(this, $"生成拼多多推广连接失败:{ex.Message},{ex.StackTrace}");
|
||
}
|
||
Thread.Sleep(100);
|
||
}
|
||
return null;
|
||
}
|
||
|
||
}
|
||
}
|