parse_2.cs 56 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389
  1. using dodohold.core;
  2. using System.Text.RegularExpressions;
  3. using System.Diagnostics;
  4. using System.Text.Json;
  5. using TencentCloud.Fmu.V20191213.Models;
  6. using System;
  7. using MySqlX.XDevAPI;
  8. using static dodohold.core.ZTOExpress.CreateOrderArgs;
  9. using System.Threading;
  10. using TencentCloud.Tcm.V20210413.Models;
  11. using COSXML.Network;
  12. using System.Net;
  13. namespace molilian.core
  14. {
  15. public partial class AlimamaPlus
  16. {
  17. public static async Task<TkDataDTO> testTaskAsync(TkDataDTO result, CancellationToken token)
  18. {
  19. string url = "https://www.taobao.com";
  20. try
  21. {
  22. WebClientUtility client = new WebClientUtility();
  23. Thread.Sleep(5000);
  24. //await Task.Delay(5000, token); // 使用Task.Delay代替Thread.Sleep
  25. client.Timeout = TimeSpan.FromMilliseconds(3000);
  26. var response = await client.RequestAsync(url);
  27. var body = response.Body();
  28. }
  29. catch
  30. {
  31. result.success = false;
  32. result.message = "Error";
  33. }
  34. return result;
  35. }
  36. public void UnionParse2(string content, ref TkDataDTO result)
  37. {
  38. if ("veapi".Equals(_api) && _api_id > 0)
  39. {
  40. var account = VeapiPoolCore.Get(_api_id);
  41. if (account != null)
  42. {
  43. var core = new VeapiPlus(account.name, account.key, account.sessionKey);
  44. core.UnionParse(content, ref result);
  45. return;
  46. }
  47. }
  48. UnionParse(content, ref result);
  49. }
  50. public async Task<TkDataDTO> UnionParse2Async(string content, int commerceType, TkDataDTO result,
  51. CancellationToken cancellationToken = default,
  52. Dictionary<string, long> swData = null)
  53. {
  54. if ("veapi".Equals(_api) && _api_id > 0)
  55. {
  56. var account = VeapiPoolCore.Get(_api_id);
  57. if (account != null)
  58. {
  59. var core = new VeapiPlus(account.name, account.key, account.sessionKey);
  60. result = await core.UnionParseAsync(content, result, cancellationToken);
  61. return result;
  62. }
  63. }
  64. result = await UnionParseAsync(content, commerceType, result, cancellationToken, swData);
  65. return result;
  66. }
  67. /// <summary>
  68. /// 提取url里面的id参数
  69. /// </summary>
  70. /// <param name="url"></param>
  71. /// <returns></returns>
  72. public static string? ExtractItemId(string url)
  73. {
  74. Match match = Regex.Match(url, @"(?:\?|&)id=(\d+)");
  75. if (match.Success)
  76. {
  77. return match.Groups[1].Value;
  78. }
  79. return null;
  80. }
  81. /// <summary>
  82. /// 是否淘宝链接,如果是商品链接就格式化成https://item.taobao.com/item.htm?id=****
  83. /// </summary>
  84. /// <param name="url"></param>
  85. /// <returns></returns>
  86. private static (bool, string) IsTaobaoUrl(string url)
  87. {
  88. if (url.Contains("//a.m.taobao.com/i") ||
  89. url.Contains("//internal.tt.detail.taobao.com/i"))
  90. {
  91. //第一种提取方法
  92. string itemId = url.GetContentPart(".com/i", ".htm");
  93. if (!string.IsNullOrEmpty(itemId) && long.TryParse(itemId, out long _))
  94. {
  95. string resultUrl = $"https://item.taobao.com/item.htm?id={itemId}";
  96. return (true, resultUrl);
  97. }
  98. }
  99. //https://pages-g.m.taobao.com/wow/z/app/detail-next/item/index?x-ssr=true&id=753169018016
  100. if (url.Contains("//item.taobao.com/item.htm?") ||
  101. url.Contains("//pages-g.m.taobao.com/wow/z/app/detail-next/item/index?") ||
  102. url.Contains("//main.m.taobao.com/detail/index.html?") ||
  103. url.Contains("//h5.m.taobao.com/awp/core/detail.htm?") ||
  104. url.Contains("//new.m.taobao.com/detail.htm?") ||
  105. url.Contains("//outfliggys.m.taobao.com/app/trip/rx-travel-detail") ||
  106. url.Contains("//detail.m.tmall.com/item.htm?") ||
  107. url.Contains("//tmallx.tmall.com/app/tmallx-src/goods-detail") ||
  108. url.Contains("//detail.tmall.com/item.htm?") ||
  109. url.Contains("//internal.tt.detail.taobao.com/item.htm?") ||
  110. url.Contains("//internal.tt.detail.taobao.com/") ||
  111. url.Contains("//detail.tmall.hk/hk/item.htm?"))
  112. {
  113. string? itemId = ExtractItemId(url);
  114. if (!string.IsNullOrEmpty(itemId))
  115. {
  116. string resultUrl = $"https://item.taobao.com/item.htm?id={itemId}";
  117. return (true, resultUrl);
  118. }
  119. }
  120. return (false, url);
  121. }
  122. /// <summary>
  123. /// 排除已知的淘客链接
  124. /// </summary>
  125. /// <param name="url"></param>
  126. /// <returns></returns>
  127. public static bool IsAffLink(string url)
  128. {
  129. if (!url.StartsWith("https://") || !url.StartsWith("https://")) url = "https://" + url;
  130. Uri uri = new(url);
  131. if (uri.Host.Equals("s.click.taobao.com", StringComparison.OrdinalIgnoreCase) ||
  132. uri.Host.Equals("uland.taobao.com", StringComparison.OrdinalIgnoreCase))
  133. {
  134. return true;
  135. }
  136. return false;
  137. }
  138. /// <summary>
  139. /// 判断淘客的¥羊角符号
  140. /// </summary>
  141. /// <param name="content"></param>
  142. /// <returns></returns>
  143. static bool ContainsSpecialFormat(string content)
  144. {
  145. // 使用正则表达式匹配内容中是否含有特定格式的字符串
  146. //string pattern = @"¥[a-zA-Z0-9\s]+¥";
  147. string pattern = @"[$¥🗝₴€₤£₳✔《💰🔑🎵✔️💲🔐📲₡]+[a-zA-Z0-9\s]+[$¥🗝₴€₤£₳✔《💰🔑🎵✔️💲🔐📲₡]*";
  148. return Regex.IsMatch(content, pattern);
  149. }
  150. public TimeSpan GetRequestTimeout()
  151. {
  152. int min = (int)(_config.rt_max * 0.5);
  153. if (_config.rt_max == 0) return TimeSpan.FromMilliseconds(1000);
  154. int timeout = _config.rt_max;
  155. timeout -= min;
  156. return TimeSpan.FromMilliseconds(timeout);
  157. }
  158. public TimeSpan GetRequestTimeout2(int deduction = 0)
  159. {
  160. int min = (int)(_config.rt_max * 0.5);
  161. if (_config.rt_max == 0) return TimeSpan.FromMilliseconds(1000);
  162. int timeout = _config.rt_max;
  163. timeout -= deduction;
  164. if (timeout <= min) return TimeSpan.FromMilliseconds(min);
  165. return TimeSpan.FromMilliseconds(timeout);
  166. }
  167. /// <summary>
  168. /// 从http获取跳转的url
  169. /// </summary>
  170. /// <param name="url"></param>
  171. /// <returns></returns>
  172. public async Task<(bool, string)> GetDesiredUrlAsync(WebProxy proxy, string url, CancellationToken cancellationToken = default)
  173. {
  174. string result;
  175. try
  176. {
  177. if (!url.Contains("m.tb.cn") &&
  178. !url.Contains("u.tb.cn") &&
  179. !url.Contains("e.tb.cn") &&
  180. !url.Contains("s.tb.cn"))
  181. return (false, "不是淘宝短网址");
  182. if (!_account.enable_deep_url) return (true, url);
  183. string desiredUrlPattern = "var url = '(.*?)'";
  184. WebClientUtility client = new()
  185. {
  186. Proxy = proxy,
  187. UserAgent = Sayaka.Common.ProviderFakeUserAgent.RandomComputer
  188. };
  189. if (url.Contains("u.tb.cn"))
  190. {
  191. client.AllowAutoRedirect = false;
  192. }
  193. url = url.Replace("http://u.tb.cn", "https://u.tb.cn");
  194. #if DEBUG
  195. client.Proxy = null;
  196. var response = await client.RequestAsync(url, "GET");
  197. #else
  198. client.Timeout = GetRequestTimeout();
  199. var response = await client.RequestAsync(url, "GET", cancellationToken);
  200. #endif
  201. if (response.ResponseMessage.StatusCode == HttpStatusCode.Found &&
  202. !string.IsNullOrEmpty(response.ResponseMessage?.Headers?.Location?.OriginalString))
  203. {
  204. string redirectUrl = response.ResponseMessage?.Headers?.Location?.OriginalString;
  205. return (true, redirectUrl);
  206. }
  207. var responseBody = response.Body();
  208. result = responseBody;
  209. if (response.Successed)
  210. {
  211. if (response.ResponseMessage.IsSuccessStatusCode)
  212. {
  213. Match match = Regex.Match(responseBody, desiredUrlPattern);
  214. if (match.Success)
  215. {
  216. result = match.Groups[1].Value; // 返回匹配的 URL
  217. if (string.IsNullOrEmpty(result)) return (false, "没有匹配的URL");
  218. if (result.StartsWith("//"))
  219. result = "https:" + result;
  220. return (true, result);
  221. }
  222. }
  223. else
  224. {
  225. result = $"{response.ResponseMessage.StatusCode}\n{responseBody}";
  226. }
  227. }
  228. else
  229. {
  230. throw response.ResponseException;
  231. }
  232. }
  233. catch (Exception ex)
  234. {
  235. _ = new LoggerLibrary("api_error", "desiredUrl_error").Info(ex.Message, ex.StackTrace).SaveAsync();
  236. result = "网络异常";
  237. }
  238. return (false, result);
  239. }
  240. /// <summary>
  241. /// 从http获取跳转的url
  242. /// </summary>
  243. /// <param name="url"></param>
  244. /// <returns></returns>
  245. (bool, string) GetDesiredUrl(string url)
  246. {
  247. string result;
  248. try
  249. {
  250. if (!url.Contains("m.tb.cn") && !url.Contains("e.tb.cn") && !url.Contains("s.tb.cn"))
  251. return (false, "不是淘宝短网址");
  252. string desiredUrlPattern = "var url = '(.*?)'";
  253. WebClientUtility client = new()
  254. {
  255. Proxy = ProxyNodesCore.RandomOne(_account.nodeName),
  256. UserAgent = Sayaka.Common.ProviderFakeUserAgent.RandomComputer
  257. };
  258. #if DEBUG
  259. client.Proxy = null;
  260. #endif
  261. client.Timeout = GetRequestTimeout();
  262. var response = client.Request(url);
  263. var responseBody = response.Body();
  264. result = responseBody;
  265. if (response.Successed)
  266. {
  267. if (response.ResponseMessage.IsSuccessStatusCode)
  268. {
  269. Match match = Regex.Match(responseBody, desiredUrlPattern);
  270. if (match.Success)
  271. {
  272. result = match.Groups[1].Value; // 返回匹配的 URL
  273. if (string.IsNullOrEmpty(result)) return (false, "没有匹配的URL");
  274. return (true, result);
  275. }
  276. }
  277. else
  278. {
  279. result = $"{response.ResponseMessage.StatusCode}\n{responseBody}";
  280. }
  281. }
  282. else
  283. {
  284. throw response.ResponseException;
  285. }
  286. }
  287. catch (Exception ex)
  288. {
  289. result = $"{ex.Message}\n{ex.StackTrace}";
  290. }
  291. return (false, result);
  292. }
  293. private void InternalTextProcessing(string content, ref TkDataDTO result)
  294. {
  295. //(result.success, result.content, result.link_type, result.shortLinkurl) = InternalTextProcessing(content,ref result);
  296. bool success;
  297. string resultText;
  298. LinkTypeEnum link_type = LinkTypeEnum.unknown;
  299. string url = GetLink(content);
  300. if (!string.IsNullOrEmpty(url))
  301. {
  302. //排除已知的淘客链接
  303. if (IsAffLink(url))
  304. {
  305. result.success = false;
  306. result.content = "排除淘客链接";
  307. result.link_type = LinkTypeEnum.other_aff;
  308. result.shortLinkurl = url;
  309. return;
  310. //return (false, "排除淘客链接", LinkTypeEnum.other_aff, url);
  311. }
  312. //直接提取
  313. (success, resultText) = IsTaobaoUrl(url);
  314. if (success)
  315. {
  316. result.success = true;
  317. result.content = resultText;
  318. result.link_type = LinkTypeEnum.goods;
  319. result.shortLinkurl = resultText;
  320. return;
  321. //return (true, result, LinkTypeEnum.goods, result);
  322. }
  323. //从http获取跳转的url
  324. Stopwatch stopwatch = Stopwatch.StartNew();
  325. stopwatch.Start();
  326. (success, resultText) = GetDesiredUrl(url);
  327. stopwatch.Stop();
  328. // 获取执行时间
  329. result.elapsedTime2 = (int)stopwatch.ElapsedMilliseconds;
  330. if (success)
  331. {
  332. //排除已知的淘客链接
  333. if (IsAffLink(resultText))
  334. {
  335. result.success = false;
  336. result.content = "排除淘客链接";
  337. result.link_type = LinkTypeEnum.other_aff;
  338. result.shortLinkurl = url;
  339. return;
  340. //return (false, "排除淘客链接", LinkTypeEnum.other_aff, url);
  341. }
  342. (success, resultText) = IsTaobaoUrl(resultText);
  343. if (success)
  344. {
  345. result.success = true;
  346. result.content = resultText;
  347. result.link_type = LinkTypeEnum.goods;
  348. result.shortLinkurl = resultText;
  349. return;
  350. //return (true, resultText, LinkTypeEnum.goods, resultText);
  351. }
  352. link_type = GetLinkType(resultText);
  353. }
  354. else
  355. {
  356. link_type = GetLinkType(url);
  357. }
  358. result.success = false;
  359. result.content = resultText;
  360. result.link_type = link_type;
  361. result.shortLinkurl = url;
  362. return;
  363. //return (false, result, link_type, url);
  364. }
  365. //判断淘客的¥羊角符号
  366. if (ContainsSpecialFormat(content))
  367. {
  368. result.success = false;
  369. result.content = "排除淘口令";
  370. result.link_type = LinkTypeEnum.other_aff;
  371. result.shortLinkurl = null;
  372. return;
  373. //return (false, "排除淘口令", LinkTypeEnum.other_aff, null);
  374. }
  375. //todo 临时应急 0614
  376. //return (false, "纯口令 没链接", link_type, null);
  377. result.success = false;
  378. result.content = "纯口令 没链接";
  379. result.link_type = LinkTypeEnum.other_aff;
  380. result.shortLinkurl = null;
  381. }
  382. public async Task<TkDataDTO> InternalTextProcessingAsync(string content, TkDataDTO result,
  383. CancellationToken cancellationToken = default,
  384. Dictionary<string, long> swData = null)
  385. {
  386. bool success;
  387. string resultText;
  388. result.link_type = LinkTypeEnum.unknown;
  389. //============================== 放弃转链-其他推广链接 ==============================
  390. string url = GetLink(content);
  391. result.shortLinkurl = url;
  392. if (!string.IsNullOrEmpty(url))
  393. {
  394. bool is_aff = IsAffLink(url);
  395. if (is_aff)
  396. {
  397. result.success = false;
  398. result.message = "放弃转链";
  399. result.reason = "其他推广链接";
  400. result.subCode = TkSubCodeEnum.OtherPromo;
  401. result.link_type = LinkTypeEnum.other_aff;
  402. //result.shortLinkurl = url;
  403. return result;
  404. }
  405. (success, resultText) = IsTaobaoUrl(url);
  406. if (success)
  407. {
  408. result.success = true;
  409. result.content = resultText;
  410. result.link_type = LinkTypeEnum.goods;
  411. //result.shortLinkurl = resultText;
  412. return result;
  413. }
  414. Stopwatch sw = Stopwatch.StartNew();
  415. var proxy = ProxyNodesCore.RandomOne(_account.nodeName);
  416. if (_proxy != null && proxy != null && _proxy.Address != proxy.Address)
  417. {
  418. result.proxy_node = proxy?.Address?.Authority;
  419. }
  420. (success, resultText) = await GetDesiredUrlAsync(proxy, url, cancellationToken);
  421. sw.Stop();
  422. // 获取执行时间
  423. result.elapsedTime2 = (int)sw.ElapsedMilliseconds;
  424. swData?.Add("\tGetDesiredUrlAsync", sw.ElapsedMilliseconds);
  425. //============================== 放弃转链-请求超时 ==============================
  426. #if DEBUG
  427. #else
  428. if (result.elapsedTime2 >= _config.rt_max || (!success && resultText.Contains("was canceled")))
  429. {
  430. result.success = false;
  431. result.message = "放弃转链";
  432. result.reason = "请求超时";
  433. result.subCode = TkSubCodeEnum.Other;
  434. return result;
  435. }
  436. #endif
  437. if (success)
  438. {
  439. string desiredUrl = resultText;
  440. //============================== 放弃转链-其他推广链接 ==============================
  441. bool is_aff2 = IsAffLink(desiredUrl);
  442. if (is_aff2)
  443. {
  444. result.success = false;
  445. result.message = "放弃转链";
  446. result.reason = "其他推广链接";
  447. result.subCode = TkSubCodeEnum.OtherPromo;
  448. result.link_type = LinkTypeEnum.other_aff;
  449. //result.shortLinkurl = url;
  450. return result;
  451. }
  452. (success, desiredUrl) = IsTaobaoUrl(desiredUrl);
  453. if (success)
  454. {
  455. result.success = true;
  456. result.content = desiredUrl;
  457. result.link_type = LinkTypeEnum.goods;
  458. //result.shortLinkurl = desiredUrl;
  459. return result;
  460. }
  461. result.link_type = GetLinkType(desiredUrl);
  462. }
  463. else
  464. {
  465. result.link_type = GetLinkType(url);
  466. if ("网络错误".Equals(resultText))
  467. {
  468. result.link_type = LinkTypeEnum.unknown;
  469. result.content = resultText;
  470. result.reason = resultText;
  471. }
  472. }
  473. if (result.content.Contains("霸下通用 web 页面-验证码"))
  474. {
  475. result.subCode = TkSubCodeEnum.Captcha;
  476. result.reason = "霸下验证码";
  477. }
  478. else
  479. {
  480. switch (result.link_type)
  481. {
  482. case LinkTypeEnum.profile:
  483. case LinkTypeEnum.live:
  484. case LinkTypeEnum.video:
  485. case LinkTypeEnum.note:
  486. case LinkTypeEnum.goods:
  487. case LinkTypeEnum.baseDomain:
  488. result.reason = string.Empty;
  489. result.content = content;
  490. break;
  491. default:
  492. result.reason = "非标准链接";
  493. result.subCode = TkSubCodeEnum.NonStdLink;
  494. break;
  495. }
  496. //if (result.link_type == LinkTypeEnum.baseDomain)
  497. //{
  498. // result.content = content;
  499. //}
  500. //else
  501. //{
  502. // result.reason = "非标准链接";
  503. // result.subCode = TkSubCodeEnum.NonStdLink;
  504. //}
  505. }
  506. result.success = false;
  507. result.message = "放弃转链";
  508. result.content = resultText;
  509. result.shortLinkurl = url;
  510. return result;
  511. //return (false, result, link_type, url);
  512. }
  513. //判断淘客的¥羊角符号
  514. bool is_aff3 = ContainsSpecialFormat(content);
  515. if (is_aff3)
  516. {
  517. result.success = false;
  518. result.message = "放弃转链";
  519. result.reason = "排除淘口令";
  520. result.subCode = TkSubCodeEnum.OtherPromo;
  521. result.link_type = LinkTypeEnum.other_aff;
  522. result.shortLinkurl = null;
  523. return result;
  524. //return (false, "排除淘口令", LinkTypeEnum.other_aff, null);
  525. }
  526. //todo 临时应急 0614
  527. //return (false, "纯口令 没链接", link_type, null);
  528. result.success = false;
  529. result.message = "放弃转链";
  530. result.reason = "纯口令 没链接";
  531. result.subCode = TkSubCodeEnum.OtherPromo;
  532. result.link_type = LinkTypeEnum.other_aff;
  533. result.shortLinkurl = null;
  534. return result;
  535. }
  536. private LinkTypeEnum GetLinkType(string url)
  537. {
  538. if (string.IsNullOrEmpty(url)) return LinkTypeEnum.unknown;
  539. if (url.Contains("m.tb.cn") || url.Contains("s.tb.cn") || url.Contains("e.tb.cn")) return LinkTypeEnum.baseDomain;
  540. if (url.StartsWith("https://huodong.m.taobao.com/act/talent/live.html")) return LinkTypeEnum.live;
  541. if (url.StartsWith("https://web.m.taobao.com/app/tnode/web/index")) return LinkTypeEnum.video;
  542. if (url.StartsWith("https://shop.m.taobao.com/shop/shopIndex.htm")) return LinkTypeEnum.profile;
  543. string pattern = @"^https://shop\d+(\.m)*\.taobao\.com";
  544. if (Regex.IsMatch(url, pattern))
  545. {
  546. return LinkTypeEnum.profile;
  547. }
  548. //https://shop.m.taobao.com/shop/shopIndex.htm?
  549. return LinkTypeEnum.unknown;
  550. }
  551. public async Task<TkDataDTO> alimamaParseAsync2(string content, TkDataDTO result, CancellationToken cancellationToken = default)
  552. {
  553. string t = $"{DateTime.Now.Convert2UnixTimestamp(true)}";
  554. Random random = new();
  555. double randomNumber = random.NextDouble();
  556. string randomString = randomNumber.ToString()[2..];
  557. string cna = _cookies.GetContentPart("cna=", ";");
  558. string firstFiveCharacters = cna[..Math.Min(5, cna.Length)];
  559. //var variableMap = new
  560. //{
  561. // url = content,
  562. // union_lens = $"b_pvid:a219t._portal_v2_tool_links_page_home_index_htm_{t}_{randomString}_{firstFiveCharacters}",
  563. // lensScene = "PUB",
  564. // spmB = "_portal_v2_tool_links_page_home_index_htm"
  565. //}.Convert2Json(true).UrlEncode();
  566. string item_id = content.GetContentPart("item.htm?id=", "");
  567. var variableMap = new
  568. {
  569. itemId = item_id
  570. }.Convert2Json(true).UrlEncode();
  571. variableMap = variableMap.Replace(" ", "%20");
  572. _floorId = "102359";
  573. string url = "https://pub.alimama.com/openapi/param2/1/gateway.unionpub/xt.entry.json?" +
  574. $"t={t}&_tb_token_={_tb_token}&floorId={_floorId}&refpid={_refpid}&variableMap={variableMap}";
  575. Stopwatch stopwatch = Stopwatch.StartNew();
  576. stopwatch.Start();
  577. var client = new WebClientUtility().SetContentType("application/json;charset=utf-8")
  578. .AddHeaders("X-Requested-With", "XMLHttpRequest")
  579. .AddHeaders("Cookie", _cookies);
  580. client.Proxy = _proxy;
  581. #if DEBUG
  582. client.Proxy = null;
  583. #endif
  584. if (!string.IsNullOrEmpty(_user_agent)) client.UserAgent = _user_agent;
  585. client.Timeout = GetRequestTimeout2(result.elapsedTime2);
  586. //var response = client.Request(url);
  587. #if DEBUG
  588. var response = await client.RequestAsync(url, "GET");
  589. #else
  590. var response = await client.RequestAsync(url, "GET", cancellationToken);
  591. #endif
  592. stopwatch.Stop();
  593. result.elapsedTime3 = (int)stopwatch.ElapsedMilliseconds;
  594. var body = string.Empty;
  595. try
  596. {
  597. if (!response.Successed)
  598. {
  599. result.channel = TkChannelEnum.tb;
  600. result.link_type = LinkTypeEnum.unknown;
  601. result.success = false;
  602. result.message = "fail";
  603. if (response.ResponseException != null)
  604. {
  605. _ = new LoggerLibrary("api_error", "fail")
  606. .Info(response.ResponseException.Message, response.ResponseException.StackTrace)
  607. .SaveAsync();
  608. throw response.ResponseException;
  609. }
  610. return result;
  611. }
  612. if (response.ResponseMessage.StatusCode == System.Net.HttpStatusCode.Found)
  613. {
  614. _ = new LoggerLibrary("api_error", "fail")
  615. .Info($"302:{response.ResponseMessage.Headers.Location}")
  616. .SaveAsync();
  617. throw new Exception("302 Found, was canceled");
  618. }
  619. JsonElement root;
  620. try
  621. {
  622. body = response.Body();
  623. //{"success":false,"message":"result empty"}
  624. root = body.Convert2JsonElement();
  625. }
  626. catch (Exception ex)
  627. {
  628. _ = new LoggerLibrary("api_error", "fail")
  629. .Info(ex.Message, ex.StackTrace)
  630. .SaveAsync();
  631. if (body.Contains("https://g.alicdn.com/sd/punish/waf_block.html"))
  632. {
  633. result.channel = TkChannelEnum.tb;
  634. result.link_type = LinkTypeEnum.unknown;
  635. result.success = false;
  636. result.message = "waf_block";
  637. result.reason = "接口风控";
  638. return result;
  639. }
  640. throw new Exception(body);
  641. }
  642. bool success = root.Read<bool>("success", false);
  643. string message = root.Read("message", string.Empty);
  644. string info_message = root.PathRead("info.message", string.Empty);
  645. if (!string.IsNullOrEmpty(info_message)) message = info_message;
  646. if ("result empty".Equals(message))
  647. {
  648. result.subCode = TkSubCodeEnum.NoConvert;
  649. }
  650. JsonElement item = default;
  651. if (success)
  652. {
  653. var data = root.ElementRead("data");
  654. var resultList = data.ElementRead("resultList");
  655. if (resultList.ValueKind != JsonValueKind.Array)
  656. {
  657. _ = new LoggerLibrary("api_error", "fail")
  658. .Info("resultList Undefined", body)
  659. .SaveAsync();
  660. throw new Exception("resultList Undefined");
  661. }
  662. item = resultList[0];
  663. }
  664. string taoToken = item.Read("taoToken", string.Empty);
  665. string shortLinkurl = item.Read("shortLinkurl", string.Empty);
  666. string couponLinkTaoToken = item.Read("couponLinkTaoToken", string.Empty);
  667. string couponShortLinkUrl = item.Read("couponShortLinkUrl", string.Empty);
  668. decimal couponAmount = item.Read<decimal>("couponAmount", 0);
  669. string couponEffectiveEndTime = item.Read("couponEffectiveEndTime", string.Empty);
  670. string couponEffectiveStartTime = item.Read("couponEffectiveStartTime", string.Empty);
  671. string itemId = item.Read("itemId", string.Empty);
  672. string mktId = item.Read("outputMktId", string.Empty);
  673. string itemName = item.Read("itemName", string.Empty);
  674. decimal promotionPrice = item.Read<decimal>("promotionPrice", 0);
  675. string sellerNickName = item.Read("sellerNickName", string.Empty);
  676. string shopTitle = item.Read("shopTitle", string.Empty);
  677. string pic = item.Read("data.pic", string.Empty);
  678. if (pic.StartsWith("//")) pic = "https:" + pic;
  679. string qrCodeUrl = item.Read("qrCodeUrl", string.Empty);
  680. if (response.ResponseMessage != null)
  681. {
  682. switch (response.ResponseMessage.StatusCode)
  683. {
  684. case System.Net.HttpStatusCode.OK:
  685. {
  686. if (couponAmount > 0 && !string.IsNullOrEmpty(couponLinkTaoToken) && !string.IsNullOrEmpty(couponShortLinkUrl))
  687. {
  688. taoToken = couponLinkTaoToken;
  689. shortLinkurl = couponShortLinkUrl;
  690. }
  691. string shortLink = GetLink(taoToken);
  692. content = ReplaceUrls(content, shortLink);
  693. }
  694. break;
  695. case System.Net.HttpStatusCode.Found:
  696. string location = response.ResponseMessage.Headers.Location.OriginalString;
  697. if (!string.IsNullOrEmpty(location) && location.Contains("www.alimama.com/member/login.htm"))
  698. {
  699. success = false;
  700. message = "nologin";
  701. }
  702. break;
  703. default:
  704. {
  705. success = false;
  706. message = "other";
  707. }
  708. break;
  709. }
  710. }
  711. if (!success)
  712. {
  713. shortLinkurl = GetLink(content);
  714. switch (message)
  715. {
  716. case "该商品已经下架或未加入淘宝客":
  717. case "该链接不支持转化,请更换链接尝试":
  718. case "result empty":
  719. result.subCode = TkSubCodeEnum.NoConvert;
  720. break;
  721. case "网络错误":
  722. result.subCode = TkSubCodeEnum.NetError;
  723. break;
  724. default:
  725. var _headers = response.ResponseMessage.Headers;
  726. var headers = "";
  727. foreach (var h in _headers)
  728. {
  729. foreach (var Value in h.Value)
  730. {
  731. headers += $"{h.Key}: {Value}\n";
  732. }
  733. }
  734. _ = new LoggerLibrary("api_error", "fail")
  735. .Info(message, content)
  736. .Info(headers, body)
  737. .SaveAsync();
  738. break;
  739. }
  740. }
  741. shortLinkurl = GetLink(taoToken);
  742. string deeplink_url = GetDeeplink(shortLinkurl);
  743. result.channel = TkChannelEnum.tb;
  744. if (success)
  745. {
  746. result.subCode = TkSubCodeEnum.Success;
  747. switch (result.link_type)
  748. {
  749. case LinkTypeEnum.profile:
  750. case LinkTypeEnum.goods:
  751. case LinkTypeEnum.video:
  752. case LinkTypeEnum.live:
  753. break;
  754. default:
  755. result.link_type = LinkTypeEnum.goods;
  756. break;
  757. }
  758. }
  759. result.success = success;
  760. result.message = message;
  761. result.reason = string.Empty;
  762. result.content = content;
  763. result.couponAmount = couponAmount;
  764. result.couponEffectiveEndTime = couponEffectiveEndTime;
  765. result.couponEffectiveStartTime = couponEffectiveStartTime;
  766. result.taoToken = taoToken;
  767. if (!string.IsNullOrEmpty(shortLinkurl))
  768. {
  769. result.shortLinkurl = shortLinkurl;
  770. result.deeplink_url = deeplink_url;
  771. }
  772. result.mktId = mktId;
  773. result.itemId = itemId;
  774. result.itemName = itemName;
  775. result.promotionPrice = promotionPrice;
  776. result.sellerNickName = sellerNickName;
  777. result.shopTitle = shopTitle;
  778. result.pic = pic;
  779. result.qrCodeUrl = qrCodeUrl;
  780. }
  781. catch (Exception ex)
  782. {
  783. if (response.ResponseMessage?.StatusCode == System.Net.HttpStatusCode.OK)
  784. {
  785. if (body.Contains("<p>抱歉!页面无法访问……</p>"))
  786. {
  787. throw new APIException("抱歉!页面无法访问……");
  788. }
  789. }
  790. throw;
  791. }
  792. return result;
  793. }
  794. public async Task<TkDataDTO> alimamaParseAsync(string content, TkDataDTO result, CancellationToken cancellationToken = default)
  795. {
  796. string t = $"{DateTime.Now.Convert2UnixTimestamp(true)}";
  797. Random random = new();
  798. double randomNumber = random.NextDouble();
  799. string randomString = randomNumber.ToString()[2..];
  800. string cna = _cookies.GetContentPart("cna=", ";");
  801. string firstFiveCharacters = cna[..Math.Min(5, cna.Length)];
  802. var variableMap = new
  803. {
  804. url = content,
  805. union_lens = $"b_pvid:a219t._portal_v2_tool_links_page_home_index_htm_{t}_{randomString}_{firstFiveCharacters}",
  806. lensScene = "PUB",
  807. spmB = "_portal_v2_tool_links_page_home_index_htm"
  808. }.Convert2Json(true).UrlEncode();
  809. variableMap = variableMap.Replace(" ", "%20");
  810. string url = "https://pub.alimama.com/openapi/param2/1/gateway.unionpub/xt.entry.json?" +
  811. $"t={t}&_tb_token_={_tb_token}&floorId={_floorId}&refpid={_refpid}&variableMap={variableMap}";
  812. Stopwatch stopwatch = Stopwatch.StartNew();
  813. stopwatch.Start();
  814. var client = new WebClientUtility().SetContentType("application/json;charset=utf-8")
  815. .AddHeaders("X-Requested-With", "XMLHttpRequest")
  816. .AddHeaders("Cookie", _cookies);
  817. client.Proxy = _proxy;
  818. #if DEBUG
  819. client.Proxy = null;
  820. #endif
  821. if (!string.IsNullOrEmpty(_user_agent)) client.UserAgent = _user_agent;
  822. client.Timeout = GetRequestTimeout2(result.elapsedTime2);
  823. //var response = client.Request(url);
  824. #if DEBUG
  825. var response = await client.RequestAsync(url, "GET");
  826. #else
  827. var response = await client.RequestAsync(url, "GET", cancellationToken);
  828. #endif
  829. stopwatch.Stop();
  830. result.elapsedTime3 = (int)stopwatch.ElapsedMilliseconds;
  831. var body = string.Empty;
  832. try
  833. {
  834. if (!response.Successed)
  835. {
  836. result.channel = TkChannelEnum.tb;
  837. result.link_type = LinkTypeEnum.unknown;
  838. result.success = false;
  839. result.message = "fail";
  840. if (response.ResponseException != null)
  841. {
  842. _ = new LoggerLibrary("api_error", "fail")
  843. .Info(response.ResponseException.Message, response.ResponseException.StackTrace)
  844. .SaveAsync();
  845. throw response.ResponseException;
  846. }
  847. return result;
  848. }
  849. if (response.ResponseMessage.StatusCode == System.Net.HttpStatusCode.Found)
  850. {
  851. _ = new LoggerLibrary("api_error", "fail")
  852. .Info($"302:{response.ResponseMessage.Headers.Location}")
  853. .SaveAsync();
  854. throw new Exception("302 Found, was canceled");
  855. }
  856. JsonElement root;
  857. try
  858. {
  859. body = response.Body();
  860. root = body.Convert2JsonElement();
  861. }
  862. catch (Exception ex)
  863. {
  864. _ = new LoggerLibrary("api_error", "fail")
  865. .Info(ex.Message, ex.StackTrace)
  866. .SaveAsync();
  867. if (body.Contains("https://g.alicdn.com/sd/punish/waf_block.html"))
  868. {
  869. result.channel = TkChannelEnum.tb;
  870. result.link_type = LinkTypeEnum.unknown;
  871. result.success = false;
  872. result.message = "waf_block";
  873. return result;
  874. }
  875. if (body.Contains("https://bixi.alicdn.com") && body.Contains("\"action\": \"deny\""))
  876. {
  877. result.channel = TkChannelEnum.tb;
  878. result.link_type = LinkTypeEnum.unknown;
  879. result.subCode = TkSubCodeEnum.ParseDeny;
  880. result.success = false;
  881. result.message = "waf_block";
  882. result.reason = "接口风控";
  883. return result;
  884. }
  885. throw new Exception(body);
  886. }
  887. bool success = root.Read<bool>("success", false);
  888. string message = root.Read("message", string.Empty);
  889. string info_message = root.PathRead("info.message", string.Empty);
  890. if (!string.IsNullOrEmpty(info_message)) message = info_message;
  891. string taoToken = root.PathRead("data.taoToken", string.Empty);
  892. string shortLinkurl = root.PathRead("data.shortLinkurl", string.Empty);
  893. string couponLinkTaoToken = root.PathRead("data.couponLinkTaoToken", string.Empty);
  894. string couponShortLinkUrl = root.PathRead("data.couponShortLinkUrl", string.Empty);
  895. decimal couponAmount = root.PathRead<decimal>("data.couponAmount", 0);
  896. string couponEffectiveEndTime = root.PathRead("data.couponEffectiveEndTime", string.Empty);
  897. string couponEffectiveStartTime = root.PathRead("data.couponEffectiveStartTime", string.Empty);
  898. string itemId = root.PathRead("data.itemId", string.Empty);
  899. string mktId = root.PathRead("data.outputMktId", string.Empty);
  900. string itemName = root.PathRead("data.itemName", string.Empty);
  901. decimal promotionPrice = root.PathRead<decimal>("data.promotionPrice", 0);
  902. string sellerNickName = root.PathRead("data.sellerNickName", string.Empty);
  903. string shopTitle = root.PathRead("data.shopTitle", string.Empty);
  904. string pic = root.PathRead("data.pic", string.Empty);
  905. if (pic.StartsWith("//")) pic = "https:" + pic;
  906. string qrCodeUrl = root.PathRead("data.qrCodeUrl", string.Empty);
  907. if (response.ResponseMessage != null)
  908. {
  909. switch (response.ResponseMessage.StatusCode)
  910. {
  911. case System.Net.HttpStatusCode.OK:
  912. {
  913. if (couponAmount > 0 && !string.IsNullOrEmpty(couponLinkTaoToken) && !string.IsNullOrEmpty(couponShortLinkUrl))
  914. {
  915. taoToken = couponLinkTaoToken;
  916. shortLinkurl = couponShortLinkUrl;
  917. }
  918. string shortLink = GetLink(taoToken);
  919. content = ReplaceUrls(content, shortLink);
  920. }
  921. break;
  922. case System.Net.HttpStatusCode.Found:
  923. string location = response.ResponseMessage.Headers.Location.OriginalString;
  924. if (!string.IsNullOrEmpty(location) && location.Contains("www.alimama.com/member/login.htm"))
  925. {
  926. success = false;
  927. message = "nologin";
  928. }
  929. break;
  930. default:
  931. {
  932. success = false;
  933. message = "other";
  934. }
  935. break;
  936. }
  937. }
  938. if (!success)
  939. {
  940. shortLinkurl = GetLink(content);
  941. switch (message)
  942. {
  943. case "该商品已经下架或未加入淘宝客":
  944. case "该链接不支持转化,请更换链接尝试":
  945. result.subCode = TkSubCodeEnum.NoConvert;
  946. break;
  947. case "网络错误":
  948. result.subCode = TkSubCodeEnum.NetError;
  949. break;
  950. default:
  951. var _headers = response.ResponseMessage.Headers;
  952. var headers = "";
  953. foreach (var h in _headers)
  954. {
  955. foreach (var Value in h.Value)
  956. {
  957. headers += $"{h.Key}: {Value}\n";
  958. }
  959. }
  960. _ = new LoggerLibrary("api_error", "fail")
  961. .Info(message, content)
  962. .Info(headers, body)
  963. .SaveAsync();
  964. break;
  965. }
  966. }
  967. shortLinkurl = GetLink(taoToken);
  968. string deeplink_url = GetDeeplink(shortLinkurl);
  969. result.channel = TkChannelEnum.tb;
  970. if (success)
  971. {
  972. result.subCode = TkSubCodeEnum.Success;
  973. switch (result.link_type)
  974. {
  975. case LinkTypeEnum.profile:
  976. case LinkTypeEnum.goods:
  977. case LinkTypeEnum.video:
  978. case LinkTypeEnum.live:
  979. break;
  980. default:
  981. result.link_type = LinkTypeEnum.goods;
  982. break;
  983. }
  984. }
  985. result.success = success;
  986. result.message = message;
  987. result.reason = string.Empty;
  988. result.content = content;
  989. result.couponAmount = couponAmount;
  990. result.couponEffectiveEndTime = couponEffectiveEndTime;
  991. result.couponEffectiveStartTime = couponEffectiveStartTime;
  992. result.taoToken = taoToken;
  993. if (!string.IsNullOrEmpty(shortLinkurl))
  994. {
  995. result.shortLinkurl = shortLinkurl;
  996. result.deeplink_url = deeplink_url;
  997. }
  998. result.mktId = mktId;
  999. result.itemId = itemId;
  1000. result.itemName = itemName;
  1001. result.promotionPrice = promotionPrice;
  1002. result.sellerNickName = sellerNickName;
  1003. result.shopTitle = shopTitle;
  1004. result.pic = pic;
  1005. result.qrCodeUrl = qrCodeUrl;
  1006. }
  1007. catch (Exception ex)
  1008. {
  1009. if (response.ResponseMessage?.StatusCode == System.Net.HttpStatusCode.OK)
  1010. {
  1011. if (body.Contains("<p>抱歉!页面无法访问……</p>"))
  1012. {
  1013. throw new APIException("抱歉!页面无法访问……");
  1014. }
  1015. }
  1016. throw;
  1017. }
  1018. return result;
  1019. }
  1020. private TkDataDTO alimamaParse(string content, TkDataDTO result)
  1021. {
  1022. string t = $"{DateTime.Now.Convert2UnixTimestamp(true)}";
  1023. Random random = new();
  1024. double randomNumber = random.NextDouble();
  1025. string randomString = randomNumber.ToString()[2..];
  1026. string cna = _cookies.GetContentPart("cna=", ";");
  1027. string firstFiveCharacters = cna[..Math.Min(5, cna.Length)];
  1028. var variableMap = new
  1029. {
  1030. url = content,
  1031. union_lens = $"b_pvid:a219t._portal_v2_tool_links_page_home_index_htm_{t}_{randomString}_{firstFiveCharacters}",
  1032. lensScene = "PUB",
  1033. spmB = "_portal_v2_tool_links_page_home_index_htm"
  1034. }.Convert2Json(true).UrlEncode();
  1035. variableMap = variableMap.Replace(" ", "%20");
  1036. string url = "https://pub.alimama.com/openapi/param2/1/gateway.unionpub/xt.entry.json?" +
  1037. $"t={t}&_tb_token_={_tb_token}&floorId={_floorId}&refpid={_refpid}&variableMap={variableMap}";
  1038. Stopwatch stopwatch = Stopwatch.StartNew();
  1039. stopwatch.Start();
  1040. var client = new WebClientUtility().SetContentType("application/json;charset=utf-8")
  1041. .AddHeaders("X-Requested-With", "XMLHttpRequest")
  1042. .AddHeaders("Cookie", _cookies);
  1043. client.Proxy = _proxy;
  1044. if (!string.IsNullOrEmpty(_user_agent)) client.UserAgent = _user_agent;
  1045. #if DEBUG
  1046. client.Proxy = null;
  1047. url = "https://47.246.177.226/openapi/param2/1/gateway.unionpub/xt.entry.json?" +
  1048. $"t={t}&_tb_token_={_tb_token}&floorId={_floorId}&refpid={_refpid}&variableMap={variableMap}";
  1049. client.Headers["Host"] = "pub.alimama.com";
  1050. #endif
  1051. client.Timeout = GetRequestTimeout2(result.elapsedTime2);
  1052. //var response = client.Request(url);
  1053. var response = client.Request(url);
  1054. stopwatch.Stop();
  1055. result.elapsedTime3 = (int)stopwatch.ElapsedMilliseconds;
  1056. var body = string.Empty;
  1057. try
  1058. {
  1059. if (!response.Successed)
  1060. {
  1061. result.channel = TkChannelEnum.tb;
  1062. result.accountId = _accountId;
  1063. result.accountName = _accountName;
  1064. result.link_type = LinkTypeEnum.unknown;
  1065. result.success = false;
  1066. result.message = "fail";
  1067. if (response.ResponseException != null)
  1068. {
  1069. _ = new LoggerLibrary("api_error", "fail")
  1070. .Info(response.ResponseException.Message, response.ResponseException.StackTrace)
  1071. .SaveAsync();
  1072. throw response.ResponseException;
  1073. }
  1074. return result;
  1075. }
  1076. body = response.Body();
  1077. //{"code":601,"info":{"ok":false,"message":"nologin"}}
  1078. JsonElement root = body.Convert2JsonElement();
  1079. bool success = root.Read<bool>("success", false);
  1080. string message = root.Read("message", string.Empty);
  1081. string info_message = root.PathRead("info.message", string.Empty);
  1082. if (!string.IsNullOrEmpty(info_message)) message = info_message;
  1083. string taoToken = root.PathRead("data.taoToken", string.Empty);
  1084. string shortLinkurl = root.PathRead("data.shortLinkurl", string.Empty);
  1085. string couponLinkTaoToken = root.PathRead("data.couponLinkTaoToken", string.Empty);
  1086. string couponShortLinkUrl = root.PathRead("data.couponShortLinkUrl", string.Empty);
  1087. decimal couponAmount = root.PathRead<decimal>("data.couponAmount", 0);
  1088. string couponEffectiveEndTime = root.PathRead("data.couponEffectiveEndTime", string.Empty);
  1089. string couponEffectiveStartTime = root.PathRead("data.couponEffectiveStartTime", string.Empty);
  1090. string itemId = root.PathRead("data.itemId", string.Empty);
  1091. string itemName = root.PathRead("data.itemName", string.Empty);
  1092. decimal promotionPrice = root.PathRead<decimal>("data.promotionPrice", 0);
  1093. string sellerNickName = root.PathRead("data.sellerNickName", string.Empty);
  1094. string shopTitle = root.PathRead("data.shopTitle", string.Empty);
  1095. string pic = root.PathRead("data.pic", string.Empty);
  1096. string qrCodeUrl = root.PathRead("data.qrCodeUrl", string.Empty);
  1097. if (response.ResponseMessage != null)
  1098. {
  1099. switch (response.ResponseMessage.StatusCode)
  1100. {
  1101. case System.Net.HttpStatusCode.OK:
  1102. {
  1103. if (couponAmount > 0 && !string.IsNullOrEmpty(couponLinkTaoToken) && !string.IsNullOrEmpty(couponShortLinkUrl))
  1104. {
  1105. taoToken = couponLinkTaoToken;
  1106. shortLinkurl = couponShortLinkUrl;
  1107. }
  1108. string shortLink = GetLink(taoToken);
  1109. content = ReplaceUrls(content, shortLink);
  1110. }
  1111. break;
  1112. case System.Net.HttpStatusCode.Found:
  1113. string location = response.ResponseMessage.Headers.Location.OriginalString;
  1114. if (!string.IsNullOrEmpty(location) && location.Contains("www.alimama.com/member/login.htm"))
  1115. {
  1116. success = false;
  1117. message = "nologin";
  1118. }
  1119. break;
  1120. default:
  1121. {
  1122. success = false;
  1123. message = "other";
  1124. }
  1125. break;
  1126. }
  1127. }
  1128. if (!success)
  1129. {
  1130. shortLinkurl = GetLink(content);
  1131. switch (message)
  1132. {
  1133. case "该商品已经下架或未加入淘宝客":
  1134. case "该链接不支持转化,请更换链接尝试":
  1135. case "网络错误":
  1136. break;
  1137. default:
  1138. var _headers = response.ResponseMessage.Headers;
  1139. var headers = "";
  1140. foreach (var h in _headers)
  1141. {
  1142. foreach (var Value in h.Value)
  1143. {
  1144. headers += $"{h.Key}: {Value}\n";
  1145. }
  1146. }
  1147. _ = new LoggerLibrary("api_error", "fail")
  1148. .Info(message, content)
  1149. .Info(headers, body)
  1150. .SaveAsync();
  1151. break;
  1152. }
  1153. }
  1154. if (success)
  1155. {
  1156. if (string.IsNullOrEmpty(itemName))
  1157. {
  1158. itemName = GetTitle(taoToken);
  1159. }
  1160. }
  1161. else
  1162. {
  1163. itemName = GetTitle(content);
  1164. }
  1165. string deeplink_url = GetDeeplink(shortLinkurl);
  1166. result.channel = TkChannelEnum.tb;
  1167. result.accountId = _accountId;
  1168. result.accountName = _accountName;
  1169. if (success)
  1170. {
  1171. switch (result.link_type)
  1172. {
  1173. case LinkTypeEnum.profile:
  1174. case LinkTypeEnum.goods:
  1175. case LinkTypeEnum.video:
  1176. case LinkTypeEnum.live:
  1177. break;
  1178. default:
  1179. result.link_type = LinkTypeEnum.goods;
  1180. break;
  1181. }
  1182. }
  1183. result.success = success;
  1184. result.message = message;
  1185. result.content = content;
  1186. result.couponAmount = couponAmount;
  1187. result.couponEffectiveEndTime = couponEffectiveEndTime;
  1188. result.couponEffectiveStartTime = couponEffectiveStartTime;
  1189. result.taoToken = taoToken;
  1190. result.shortLinkurl = shortLinkurl;
  1191. result.deeplink_url = deeplink_url;
  1192. result.itemId = itemId;
  1193. result.itemName = itemName;
  1194. result.promotionPrice = promotionPrice;
  1195. result.sellerNickName = sellerNickName;
  1196. result.shopTitle = shopTitle;
  1197. result.pic = pic;
  1198. result.qrCodeUrl = qrCodeUrl;
  1199. }
  1200. catch
  1201. {
  1202. if (response.ResponseMessage?.StatusCode == System.Net.HttpStatusCode.OK)
  1203. {
  1204. if (body.Contains("<p>抱歉!页面无法访问……</p>"))
  1205. {
  1206. throw new APIException("抱歉!页面无法访问……");
  1207. }
  1208. }
  1209. throw;
  1210. }
  1211. return result;
  1212. }
  1213. }
  1214. }