209 lines
9.6 KiB
C#
209 lines
9.6 KiB
C#
|
using System;
|
|||
|
using System.Collections.Generic;
|
|||
|
using System.Linq;
|
|||
|
using System.Security.Cryptography;
|
|||
|
using System.Text;
|
|||
|
using System.Text.RegularExpressions;
|
|||
|
using System.Threading.Tasks;
|
|||
|
using CsharpHttpHelper;
|
|||
|
using CsharpHttpHelper.Enum;
|
|||
|
using Microsoft.ClearScript.V8;
|
|||
|
using Newtonsoft.Json.Linq;
|
|||
|
|
|||
|
namespace Api.Framework.Tools
|
|||
|
{
|
|||
|
/// <summary>
|
|||
|
/// 快手解析助手
|
|||
|
/// </summary>
|
|||
|
public class KSHelper
|
|||
|
{
|
|||
|
/// <summary>
|
|||
|
/// 解析商品内容获取Id
|
|||
|
/// </summary>
|
|||
|
/// <param name="str"></param>
|
|||
|
/// <returns></returns>
|
|||
|
public static string GetItemId(string str, out string title)
|
|||
|
{
|
|||
|
#region 解析链接
|
|||
|
if (Regex.IsMatch(str, @"((?:https://a6chq\.ogwormb\.com)|(?:(https://ac31\.suvmothq\.com)))", RegexOptions.IgnoreCase))
|
|||
|
{
|
|||
|
var url = HttpExtend.RegexMatchUrl(str);
|
|||
|
str = CsharpHttpHelper.HttpExtend.GetLocationUrl(url);
|
|||
|
}
|
|||
|
|
|||
|
var reg = Regex.Match(str,
|
|||
|
@"https:\/\/cps\.kwaixiaodian\.com\/page\/kwaimoney\/promotion\/goods\/detail\/(?<商品ID>\d+)",
|
|||
|
RegexOptions.ExplicitCapture);
|
|||
|
if (!reg.Success)
|
|||
|
reg = Regex.Match(str, @"package-shop/pages/goods/main.*?[\?&]id=(?<商品ID>\d+)",
|
|||
|
RegexOptions.IgnoreCase | RegexOptions.Multiline);
|
|||
|
if (!reg.Success)
|
|||
|
reg = Regex.Match(str, @"page/kwaishop-buyer-goods-detail.*?[\?&]id=(?<商品ID>\d+)",
|
|||
|
RegexOptions.IgnoreCase | RegexOptions.Multiline);
|
|||
|
|
|||
|
if (reg.Success)
|
|||
|
{
|
|||
|
title = string.Empty;
|
|||
|
return reg.Groups["商品ID"].Value;
|
|||
|
}
|
|||
|
#endregion
|
|||
|
|
|||
|
#region 解析解析口令
|
|||
|
//##X7poMxtqkJLk21g##
|
|||
|
|
|||
|
reg = Regex.Match(str, @"((?:##)|(?:[^a-zA-Z0-9-]))(?<口令>X[a-zA-Z0-9-]{13,15})((?:##)|(?:[^a-zA-Z0-9-]))", RegexOptions.IgnoreCase);
|
|||
|
if (reg.Success)
|
|||
|
{
|
|||
|
var result = AnalysisKl(reg.Groups["口令"].Value);
|
|||
|
//....解析操作
|
|||
|
|
|||
|
#region 数据结构
|
|||
|
|
|||
|
//{"result":1,"hostName":"zt-zl-rs296.idczw.hb1.kwaidc.com","cache-scope":"nocache","error_msg":null,"showDialog":{"originKpn":"KUAISHOU","originSubBiz":"GOODS_DETAILS_OF_NATIVE","kpn":"KUAISHOU","subBiz":"share","kwaiUrl":"https://app.kwaixiaodian.com/merchant/shop/detail?fid=2430851481&cc=share_copylink&followRefer=151&shareMethod=TOKEN&kpn=KUAISHOU&subBiz=GOODS_DETAILS_OF_NATIVE&carrierType=24&shareToken=X7WKCOoS0M6bgoi&shareId=16956809344990&shareMode=SYSTEM&originShareId=16956809344990&layoutType=4&shareObjectId=4035974256190&id=4035974256190&shareUrlOpened=0&carrierId=5×tamp=1653385982520","dialog":{"subTitle":"来快手看看这个商品吧","footerText":"来自好友的分享,查看他","actionButtonTargetUrl":"https://app.kwaixiaodian.com/merchant/shop/detail?fid=2430851481&cc=share_copylink&followRefer=151&shareMethod=TOKEN&kpn=KUAISHOU&subBiz=GOODS_DETAILS_OF_NATIVE&carrierType=24&shareId=16956809344990&shareMode=SYSTEM&originShareId=16956809344990&layoutType=4&shareObjectId=4035974256190&id=4035974256190&shareUrlOpened=0&carrierId=5×tamp=1653385982520","shareId":"16956809344990","footerTargetUrl":"kwai://profile/2430851481?fid=2430851481&cc=share_copylink&followRefer=151&shareMethod=TOKEN&kpn=KUAISHOU&subBiz=GOODS_DETAILS_OF_NATIVE&carrierType=24&shareId=16956809344990&shareMode=SYSTEM&originShareId=16956809344990&layoutType=4&shareObjectId=4035974256190&id=4035974256190&shareUrlOpened=0&carrierId=5×tamp=1653385982520","shareObjectId":"4035974256190","iconUrl":"https://p3.eckwai.com/bs2/image-kwaishop-product/item-2763666190-185a99e1c95847b39e39ad59f34c94cf.jpg","iconTargetUrl":"https://app.kwaixiaodian.com/merchant/shop/detail?fid=2430851481&cc=share_copylink&followRefer=151&shareMethod=TOKEN&kpn=KUAISHOU&subBiz=GOODS_DETAILS_OF_NATIVE&carrierType=24&shareId=16956809344990&shareMode=SYSTEM&originShareId=16956809344990&layoutType=4&shareObjectId=4035974256190&id=4035974256190&shareUrlOpened=0&carrierId=5×tamp=1653385982520","title":"1元 快乐旺哥草莓蛋糕【拼满19.9包邮发货】","actionButtonText":"去看看"},"oldShowType":0,"newShowTypes":["bigHeadDialog"],"extParams":{"kwaiUrl":"kwai://home","shareUrl":"/package-shop/pages/goods/main?id=4035974256190&layoutType=4&carrierType=24","iconUrl":"https://p3.eckwai.com/bs2/image-kwaishop-product/item-2763666190-185a99e1c95847b39e39ad59f34c94cf.jpg","title":"1元 快乐旺哥草莓蛋糕【拼满19.9包邮发货】","carrierId":"5","jumpUrl":"https://app.kwaixiaodian.com/merchant/shop/detail?id=4035974256190&layoutType=4&carrierType=24"}},"max-age":0}
|
|||
|
|
|||
|
#endregion
|
|||
|
|
|||
|
var jObj = JObject.Parse(result);
|
|||
|
var jumpUrl = jObj?["showDialog"]?["dialog"]?["shareObjectId"]?.ToString();
|
|||
|
if (!string.IsNullOrWhiteSpace(jumpUrl))
|
|||
|
{
|
|||
|
title = jObj?["showDialog"]?["dialog"]?["title"]?.ToString();
|
|||
|
return jumpUrl;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
#endregion
|
|||
|
|
|||
|
title = string.Empty;
|
|||
|
return string.Empty;
|
|||
|
}
|
|||
|
|
|||
|
#region 快手口令解析
|
|||
|
/// <summary>
|
|||
|
/// Post参数
|
|||
|
/// </summary>
|
|||
|
static string postParam = $"kpf=ANDROID_PHONE&shareMessage=内容&kpn=KUAISHOU&sdkVersion=1.14.0.0&theme=light&sessionId=8a19a62f-fa3c-4097-aae4-cdf0ec11c59d&extTransientParams={{\"source\":\"autoDetectPasteboard\"}}&launchState=firstColdLaunchToday";
|
|||
|
/// <summary>
|
|||
|
/// 参数2
|
|||
|
/// </summary>
|
|||
|
static string getParam = "kpf=ANDROID_PHONE&ver=9.7&gid=&mod=HUAWEI%28HWI-AL00%29&c=OPPO&oDid=TEST_ANDROID_dd6f96475163fa32&android_os=0&os=android&appver=9.7.30.21320&boardPlatform=hi3660&ftt=&kpn=KUAISHOU&subBiz=share&androidApiLevel=28&language=zh-cn&sys=ANDROID_9&mcc=46007&userId=0&memoryTotalSize=5725&did_tag=0&countryCode=CN&rdid=&net=WIFI&did=";
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 解析快手口令
|
|||
|
/// </summary>
|
|||
|
/// <param name="content"></param>
|
|||
|
/// <returns></returns>
|
|||
|
public static string AnalysisKl(string content)
|
|||
|
{
|
|||
|
content = $"##{content}##";
|
|||
|
var sign = GetKlSign(content);
|
|||
|
|
|||
|
var param = postParam.Replace("内容", content) + $"&sig={sign}";
|
|||
|
|
|||
|
var url = $"https://api.kuaishouzt.com/rest/zt/share/show/any?{getParam}";
|
|||
|
HttpHelper http = new HttpHelper();
|
|||
|
HttpItem item = new HttpItem()
|
|||
|
{
|
|||
|
URL = url,
|
|||
|
Method = "post",
|
|||
|
IsToLower = false,
|
|||
|
Cookie = "",
|
|||
|
Referer = "",
|
|||
|
Postdata = param,
|
|||
|
Timeout = 100000,
|
|||
|
ReadWriteTimeout = 30000,
|
|||
|
UserAgent = "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)",
|
|||
|
ContentType = "application/x-www-form-urlencoded",
|
|||
|
Allowautoredirect = false,
|
|||
|
ResultType = ResultType.String
|
|||
|
};
|
|||
|
HttpResult result = http.GetHtml(item);
|
|||
|
string html = result.Html;
|
|||
|
//EventClient.OnEvent("", "口令解析:" + html);
|
|||
|
return html;
|
|||
|
}
|
|||
|
|
|||
|
private static string GetKlSign(string content)
|
|||
|
{
|
|||
|
var paramC = $"{postParam.Replace("内容", content)}&{getParam}";
|
|||
|
|
|||
|
var deContent = System.Web.HttpUtility.UrlDecode(paramC);
|
|||
|
|
|||
|
//var splits = deContent.Split('&').ToList();
|
|||
|
//splits.Sort();
|
|||
|
//var sortContent = string.Join("", splits);
|
|||
|
|
|||
|
|
|||
|
byte[] deContentAAscii = Encoding.ASCII.GetBytes(deContent);
|
|||
|
string deContentUtf8 = Encoding.UTF8.GetString(deContentAAscii);
|
|||
|
|
|||
|
var sortContent = JsStrSort(deContentUtf8);
|
|||
|
|
|||
|
var result = $"{sortContent}382700b563f4";
|
|||
|
|
|||
|
MD5 md5 = MD5.Create();
|
|||
|
var bytes = md5.ComputeHash(Encoding.UTF8.GetBytes(result));
|
|||
|
|
|||
|
// 第五步:把二进制转化为大写的十六进制
|
|||
|
StringBuilder strb = new StringBuilder();
|
|||
|
for (int i = 0; i < bytes.Length; i++)
|
|||
|
{
|
|||
|
strb.Append(bytes[i].ToString("x2"));
|
|||
|
}
|
|||
|
|
|||
|
return strb.ToString();
|
|||
|
}
|
|||
|
|
|||
|
private static string JsStrSort(string content)
|
|||
|
{
|
|||
|
return V8Method(JsSort, $"'{content}'", "getString");
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 使用V8引擎执行JS代码
|
|||
|
/// </summary>
|
|||
|
/// <param name="JsCode">JS代码</param>
|
|||
|
/// <param name="JsParam">当前方法需要的参数</param>
|
|||
|
/// <param name="JsMethodName">执行的JS方法名</param>
|
|||
|
/// <returns></returns>
|
|||
|
private static string V8Method(string JsCode, string JsParam, string JsMethodName)
|
|||
|
{
|
|||
|
string result = string.Empty;
|
|||
|
try
|
|||
|
{
|
|||
|
using (var engine = new V8ScriptEngine())
|
|||
|
{
|
|||
|
V8Script script = engine.Compile(JsCode);
|
|||
|
engine.Execute(script);
|
|||
|
result = engine.ExecuteCommand(string.Format("{0}({1})", JsMethodName, JsParam));
|
|||
|
//其他写法
|
|||
|
}
|
|||
|
}
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
//result = ex.Message.ToString();
|
|||
|
}
|
|||
|
return result;
|
|||
|
}
|
|||
|
|
|||
|
private static string JsSort
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
return @"function getString(str){
|
|||
|
var array;
|
|||
|
array = str.split('&');
|
|||
|
array.sort();
|
|||
|
return array.join('');
|
|||
|
}";
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
}
|
|||
|
#endregion
|
|||
|
|
|||
|
|
|||
|
}
|
|||
|
}
|