792 lines
40 KiB
C#
792 lines
40 KiB
C#
using AllBase;
|
|
using NaiBa.Util.Extension;
|
|
using Newtonsoft.Json;
|
|
using Newtonsoft.Json.Linq;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using Work.Api;
|
|
|
|
namespace Work.CollectClass
|
|
{
|
|
public class WeiDianProductCollect
|
|
{
|
|
public string Name, TempHtml = "";
|
|
public string message = "";
|
|
public bool OnSale = true;
|
|
public static List<long> TempIds = new List<long>();
|
|
public static List<long> DeleteIds = new List<long>();
|
|
public ProductCollectBase pb = new ProductCollectBase();
|
|
public TaobaoProductBase Product;
|
|
public WeiDianProductCollect(TaobaoProductBase product)
|
|
{
|
|
Product = product;
|
|
}
|
|
public WeiDianProductCollect(string name, TaobaoProductBase product)
|
|
{
|
|
Name = name;
|
|
Product = product;
|
|
}
|
|
public void Get()
|
|
{
|
|
try
|
|
{
|
|
Getx();
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
}
|
|
|
|
|
|
public void Getx()
|
|
{
|
|
message = "";
|
|
if (DeleteIds.Contains(Product.FromId))
|
|
{
|
|
LogSave.Add(Name, "商品已经下架:" + Product.FromId);
|
|
message = "商品已经下架:" + Product.FromId;
|
|
OnSale = false;
|
|
Thread.Sleep(500);
|
|
return;
|
|
}
|
|
string cookies = "";
|
|
if (TaobaoMobileCollect.ProductTemp.ContainsKey(Product.FromId))
|
|
{
|
|
pb = TaobaoMobileCollect.ProductTemp[Product.FromId].Clone();
|
|
return;
|
|
}
|
|
if (TempIds.Contains(Product.FromId) && string.IsNullOrEmpty(TempHtml))
|
|
Thread.Sleep(5 * 1000);
|
|
if (!TempIds.Contains(Product.FromId))
|
|
TempIds.Add(Product.FromId);
|
|
if (TaobaoMobileCollect.ProductTemp.ContainsKey(Product.FromId))
|
|
{
|
|
pb = TaobaoMobileCollect.ProductTemp[Product.FromId].Clone();
|
|
return;
|
|
}
|
|
bool canUse=false;
|
|
bool userData = false;
|
|
string serverTempHtml = ServerTemp.Get(4, Product.FromId.ToString(), out canUse);
|
|
if (canUse)
|
|
{
|
|
userData = true;
|
|
TempHtml = serverTempHtml;
|
|
}
|
|
string url = "https://weidian.com/item.html?itemID=" + Product.FromId;
|
|
string refere ="";
|
|
string html = "";
|
|
if (string.IsNullOrEmpty(TempHtml) || (!TempHtml.Contains("item_name") && !TempHtml.Contains("item_name")))
|
|
{
|
|
Thread.Sleep(2000);
|
|
if (UploadPinduoduoMain.Running || UploadPinduoduoMain.RunningReplace)
|
|
{
|
|
int it = UploadPinduoduoMain.ShopThreadCount * UploadPinduoduoMain.SingleThreadCount;
|
|
Thread.Sleep(it * 200);
|
|
}
|
|
html = GetPostTaobaoHtml.UploadTaobao(url, refere, true, cookies);
|
|
TempHtml = html;
|
|
}
|
|
else
|
|
{
|
|
html = TempHtml;
|
|
}
|
|
if ((string.IsNullOrEmpty(html) || !html.Contains("catID1") || !html.Contains("cat_id_1")) && !string.IsNullOrEmpty(serverTempHtml))
|
|
{
|
|
userData = true;
|
|
html = serverTempHtml;
|
|
}
|
|
#region 微店平台数据解析
|
|
if (html.Contains("item_name"))
|
|
{
|
|
html = GetHtml.Decode(html);
|
|
pb.from = "微店";
|
|
pb.id = Product.FromId;
|
|
pb.from_id = Product.FromId;
|
|
LogSave.Add(Name, "获取成功:" + Product.FromId);
|
|
pb.name = BaseRegex.GetStringJson(ref html, "item_name");
|
|
pb.name_share = BaseRegex.GetStringJson(ref html, "shareDesc");
|
|
pb.from_shop_name = BaseRegex.GetStringJson(ref html, "shopName");
|
|
pb.content_pinduoduo = "";// BaseRegex.GetStringJson(ref html, "goodsDesc");
|
|
string temp = BaseRegex.GetMatchRegexString(ref html, @"""imgs"":\[(""[\w\W]+?"")\],");
|
|
var m = BaseRegex.GetMatchRegex(ref temp, @"""([^""]+?)""");
|
|
for (int i = 0; i < m.Count; i++)
|
|
{
|
|
string img = m[i].Groups[1].Value.Replace("@750w_1l_50Q", "");
|
|
if (img.Contains("?"))
|
|
img = img.Substring(0, img.IndexOf("?"));
|
|
pb.Images.Add(img);
|
|
}
|
|
m = BaseRegex.GetMatchRegex(ref html, @"\{""attr_ids""[\w\W]+?\}");
|
|
if (m.Count==0)
|
|
{
|
|
temp = BaseRegex.GetMatchRegexString(ref html, @"""sku"":([\w\W]+?})}");
|
|
m = BaseRegex.GetMatchRegex(ref temp, @"""id"":[\w\W]+?""title""[\w\W]+?}");
|
|
}
|
|
for (int i = 0; i < m.Count; i++)
|
|
{
|
|
string list = m[i].Groups[0].Value;
|
|
SkuMapBase s = new SkuMapBase();
|
|
s.id = BaseRegex.GetLongJson(ref list, "id");
|
|
s.price = BaseRegex.GetDecimalJson(ref list, "price");
|
|
if (s.price < 1)
|
|
continue;
|
|
int num = BaseRegex.GetIntJson(ref list, "stock");
|
|
s.number = num;
|
|
s.sale_count = BaseRegex.GetIntJson(ref list, "soldQuantity");
|
|
pb.saleCount += s.sale_count;
|
|
s.prop_image = BaseRegex.GetStringJson(ref list, "img");
|
|
if (!string.IsNullOrEmpty(s.prop_image))
|
|
s.prop_image = s.prop_image.Replace("@750w_1l_50Q", "");
|
|
if (s.prop_image.Contains("?"))
|
|
s.prop_image = s.prop_image.Substring(0, s.prop_image.IndexOf("?"));
|
|
s.name = BaseRegex.GetStringJson(ref list, "title");//GetName(list, ref pb, s.prop_image);
|
|
pb.SkuMaps.Add(s);
|
|
}
|
|
temp = BaseRegex.GetMatchRegexString(ref html, @"\{""attr_list"":([\w\W]+?\}\]\}\])");
|
|
m = BaseRegex.GetMatchRegex(ref temp, @"\{""attr_title"":[\w\W]+?\}\]\}");
|
|
string image = "";
|
|
pb.Props.Clear();
|
|
for (int k = 0;m!=null&&k < m.Count; k++)
|
|
{
|
|
string list = m[k].Groups[0].Value;
|
|
bool had = false;
|
|
PropBase p = new PropBase();
|
|
for (int j = 0; j < pb.Props.Count; j++)
|
|
{
|
|
if (pb.Props[j].name == m[k].Groups[1].Value)
|
|
{
|
|
had = true;
|
|
p = pb.Props[j];
|
|
break;
|
|
}
|
|
}
|
|
if (!had)
|
|
{
|
|
var item = m[k].Groups[0].Value;
|
|
p = new PropBase();
|
|
p.name = BaseRegex.GetStringJson(ref item, "attr_title");
|
|
pb.Props.Add(p);
|
|
}
|
|
var mc= BaseRegex.GetMatchRegex(ref list, @"\{""attr_id"":[\w\W]+?\}");
|
|
for (int i = 0; i < mc.Count; i++)
|
|
{
|
|
|
|
had = false;
|
|
for (int j = 0; j < p.Values.Count; j++)
|
|
{
|
|
if (p.Values[j].name == mc[i].Groups[2].Value)
|
|
{
|
|
p.Values[j].image = image;
|
|
p.Values[j].image_from_url = image;
|
|
had = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!had)
|
|
{
|
|
var item = mc[i].Groups[0].Value;
|
|
PropValueBase pv = new PropValueBase();
|
|
pv.id = BaseRegex.GetStringJson(ref item, "attr_id");
|
|
pv.name = BaseRegex.GetStringJson(ref item, "attr_value");
|
|
pv.image = BaseRegex.GetStringJson(ref item, "img");
|
|
pv.image_from_url = BaseRegex.GetStringJson(ref item, "img");
|
|
p.Values.Add(pv);
|
|
}
|
|
}
|
|
}
|
|
if (pb.Props.Count==0)
|
|
{
|
|
PropBase p = new PropBase();
|
|
p.name = "型号尺寸";
|
|
pb.Props.Add(p);
|
|
for (int i = 0; i < pb.SkuMaps.Count; i++)
|
|
{
|
|
var sku = pb.SkuMaps[i];
|
|
PropValueBase pv = new PropValueBase();
|
|
pv.id = sku.id.ToString();
|
|
pv.name = sku.name;
|
|
pv.image = sku.prop_image;
|
|
pv.image_from_url = sku.prop_image;
|
|
p.Values.Add(pv);
|
|
}
|
|
}
|
|
|
|
|
|
decimal maxPriceNew = 0;
|
|
for (int i = 0; i < pb.SkuMaps.Count; i++)
|
|
{
|
|
if (maxPriceNew < pb.SkuMaps[i].price)
|
|
maxPriceNew = pb.SkuMaps[i].price;
|
|
}
|
|
string firstSkuImage = pb.SkuMaps[0].prop_image;
|
|
if (pb.Props.Count == 1)
|
|
{
|
|
for (int j = 0; j < pb.Props[0].Values.Count; j++)
|
|
{
|
|
bool ishad = false;
|
|
for (int k = 0; k < pb.SkuMaps.Count; k++)
|
|
{
|
|
if (pb.SkuMaps[k].name.Replace(" ", "+").Contains(pb.Props[0].Values[j].name))
|
|
{
|
|
ishad = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!ishad)
|
|
{
|
|
SkuMapBase sm = new SkuMapBase();
|
|
sm.id = BaseClass.GetTime(DateTime.Today);
|
|
sm.price = maxPriceNew;
|
|
sm.number = 0;
|
|
sm.sale_count = 0;
|
|
pb.saleCount += sm.sale_count;
|
|
sm.prop_image = firstSkuImage;
|
|
sm.name = pb.Props[0].name + ":" + pb.Props[0].Values[j].name + ";";
|
|
pb.SkuMaps.Add(sm);
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
if (pb.Props.Count == 2)
|
|
{
|
|
|
|
for (int j = 0; j < pb.Props[0].Values.Count; j++)
|
|
{
|
|
for (int k = 0; k < pb.Props[1].Values.Count; k++)
|
|
{
|
|
bool ishad = false;
|
|
for (int l = 0; l < pb.SkuMaps.Count; l++)
|
|
{
|
|
|
|
string[] li = pb.SkuMaps[l].name.Split(';');
|
|
if (li.Length == 2)
|
|
{
|
|
string n1 = li[0].Substring(li[0].IndexOf(":") + 1).Trim().Replace(" ","+");
|
|
string n2 = li[1].Substring(li[1].IndexOf(":") + 1).Trim().Replace(" ", "+");
|
|
if (pb.Props[0].Values[j].name == n1 && pb.Props[1].Values[k].name == n2 || pb.Props[0].Values[j].name == n2 && pb.Props[1].Values[k].name == n1)
|
|
{
|
|
ishad = true;
|
|
break;
|
|
}
|
|
|
|
}
|
|
if (li.Length == 3)
|
|
{
|
|
string n1 = li[0].Substring(li[0].IndexOf(":") + 1).Trim().Replace(" ", "+");
|
|
string n2 = li[1].Substring(li[1].IndexOf(":") + 1).Trim().Replace(" ", "+");
|
|
string n3 = li[2].Substring(li[2].IndexOf(":") + 1).Trim().Replace(" ", "+");
|
|
if (pb.Props[0].Values[j].name == n1 && pb.Props[1].Values[k].name == n2 || pb.Props[0].Values[j].name == n2 && pb.Props[1].Values[k].name == n1
|
|
|| pb.Props[0].Values[j].name == n1 && pb.Props[1].Values[k].name == n3 || pb.Props[0].Values[j].name == n3 && pb.Props[1].Values[k].name == n1
|
|
|| pb.Props[0].Values[j].name == n2 && pb.Props[1].Values[k].name == n3 || pb.Props[0].Values[j].name == n3 && pb.Props[1].Values[k].name == n2)
|
|
{
|
|
ishad = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (li.Length == 4)
|
|
{
|
|
string n1 = li[0].Substring(li[0].IndexOf(":") + 1).Trim().Replace(" ", "+");
|
|
string n2 = li[1].Substring(li[1].IndexOf(":") + 1).Trim().Replace(" ", "+");
|
|
string n3 = li[2].Substring(li[2].IndexOf(":") + 1).Trim().Replace(" ", "+");
|
|
string n4 = li[3].Substring(li[3].IndexOf(":") + 1).Trim().Replace(" ", "+");
|
|
if (pb.Props[0].Values[j].name == n1 && pb.Props[1].Values[k].name == n2 || pb.Props[0].Values[j].name == n2 && pb.Props[1].Values[k].name == n1
|
|
|| pb.Props[0].Values[j].name == n1 && pb.Props[1].Values[k].name == n3 || pb.Props[0].Values[j].name == n3 && pb.Props[1].Values[k].name == n1
|
|
|| pb.Props[0].Values[j].name == n2 && pb.Props[1].Values[k].name == n3 || pb.Props[0].Values[j].name == n3 && pb.Props[1].Values[k].name == n2)
|
|
{
|
|
ishad = true;
|
|
break;
|
|
}
|
|
if (pb.Props[0].Values[j].name == n3 && pb.Props[1].Values[k].name == n4 || pb.Props[0].Values[j].name == n4 && pb.Props[1].Values[k].name == n3
|
|
|| pb.Props[0].Values[j].name == n1 && pb.Props[1].Values[k].name == n4 || pb.Props[0].Values[j].name == n4 && pb.Props[1].Values[k].name == n1
|
|
|| pb.Props[0].Values[j].name == n2 && pb.Props[1].Values[k].name == n4 || pb.Props[0].Values[j].name == n4 && pb.Props[1].Values[k].name == n2)
|
|
{
|
|
ishad = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
}
|
|
if (!ishad)
|
|
{
|
|
SkuMapBase sm = new SkuMapBase();
|
|
sm.id = BaseClass.GetTime(DateTime.Today);
|
|
sm.price = maxPriceNew;
|
|
sm.number = 0;
|
|
sm.sale_count = 0;
|
|
pb.saleCount += sm.sale_count;
|
|
sm.prop_image = firstSkuImage;
|
|
sm.name = pb.Props[0].name + ":" + pb.Props[0].Values[j].name + ";" + pb.Props[1].name + ":" + pb.Props[1].Values[k].name + ";";
|
|
pb.SkuMaps.Add(sm);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (pb.cat1 == 0)
|
|
{
|
|
FromTitleToCat.UserApi = true;
|
|
FromTitleToCat ftx = new FromTitleToCat();
|
|
ftx.TaobaoProduct = new TaobaoProductBase();
|
|
ftx.Title = pb.name;
|
|
ftx.TaobaoProduct.Titlte = pb.name;
|
|
ftx.TaobaoProduct.FromId = pb.from_id;
|
|
ftx.TaobaoCatId = BaseRegex.GetIntJson(ref html, "bg_category_id");
|
|
ftx.JustGetCat = true;
|
|
ftx.Get();
|
|
if (!string.IsNullOrEmpty(ftx.Cat1) && ftx.Cat1 != "0")
|
|
{
|
|
pb.cat1 = int.Parse(ftx.Cat1);
|
|
pb.cat2 = int.Parse(ftx.Cat2);
|
|
pb.cat3 = int.Parse(ftx.Cat3);
|
|
pb.cat4 = int.Parse(ftx.Cat4);
|
|
}
|
|
}
|
|
var ftc = new FromTitleToCat();
|
|
pb.main_cid = ftc.GetMainCatId(pb.cat1);
|
|
pb.main_cat_name = ftc.MainCatName;
|
|
|
|
string eprice = BaseRegex.GetMatchRegexString(ref html, @"""expressFeeDesc"":""([\w\W]+?)元起""");
|
|
pb.express_price = string.IsNullOrEmpty(eprice) ? 0 : decimal.Parse(eprice);
|
|
|
|
pb.mall_id = BaseRegex.GetLongJson(ref html, "mallID");
|
|
pb.from_site_id = 6;
|
|
if (pb.price<=0 && pb.SkuMaps.Count > 0)
|
|
pb.price = pb.SkuMaps[0].price;
|
|
string sale = BaseRegex.GetStringJson(ref html, "soldText");
|
|
sale = BaseRegex.GetMatchRegexString(ref sale, @"销量\s*([\d\.万]+)");
|
|
if (!string.IsNullOrEmpty(sale))
|
|
{
|
|
sale = sale.Replace(".", "").Replace("万", "0000");
|
|
int sa = 0;
|
|
int.TryParse(sale, out sa);
|
|
pb.saleCount = sa;
|
|
}
|
|
string content = BaseRegex.GetMatchRegexString(ref html, @"""desc_content"":\[[\w\W]+?\{""text"":""([\w\W]+?)""");
|
|
if (string.IsNullOrEmpty(content))
|
|
{
|
|
string vItemId = BaseRegex.GetMatchRegexString(ref html, @"itemID=([\w\W]+?)""");
|
|
string detailUrl = "https://thor.weidian.com/detail/getDetailDesc/1.0?param={\"vItemId\":\"" + vItemId + "\"}";
|
|
string htmldetail = GetPostTaobaoHtml.UploadTaobao(detailUrl, refere, true, cookies);
|
|
content = BaseRegex.GetMatchRegexString(ref htmldetail, @"""desc_content"":\[[\w\W]+?\{""text"":""([\w\W]+?)""");
|
|
pb.before_price = BaseRegex.GetIntJson(ref htmldetail, "marketPrice") / 100m;
|
|
m = BaseRegex.GetMatchRegex(ref htmldetail, @"""url"":""([^""]+?)""");
|
|
for (int i = 0; i < m.Count; i++)
|
|
{
|
|
string img = m[i].Groups[1].Value.Replace("@750w_1l_50Q", "");
|
|
if (img.Contains("?"))
|
|
img = img.Substring(0, img.IndexOf("?"));
|
|
content += "<img src='" + img + "'>";
|
|
}
|
|
pb.content = content;
|
|
html += "<br/>" + htmldetail;
|
|
}
|
|
else
|
|
{
|
|
content = BaseRegex.GetMatchRegexString(ref html, @"""desc_content"":\[[\w\W]+?\{""text"":""([\w\W]+?)""");
|
|
pb.before_price = BaseRegex.GetIntJson(ref html, "marketPrice") / 100m;
|
|
m = BaseRegex.GetMatchRegex(ref html, @"""url"":""([^""]+?)""");
|
|
for (int i = 0; i < m.Count; i++)
|
|
{
|
|
string img = m[i].Groups[1].Value.Replace("@750w_1l_50Q", "");
|
|
if (img.Contains("?"))
|
|
img = img.Substring(0, img.IndexOf("?"));
|
|
content += "<img src='" + img + "'>";
|
|
}
|
|
pb.content = content;
|
|
}
|
|
if (!userData)
|
|
ServerTemp.Set(4, Product.FromId.ToString(), html);
|
|
}
|
|
#endregion
|
|
if (TaobaoMobileCollect.ProductTemp.Count > 1000)
|
|
{
|
|
TaobaoMobileCollect.ProductTemp.Clear();
|
|
}
|
|
if (!TaobaoMobileCollect.ProductTemp.ContainsKey(pb.from_id))
|
|
{
|
|
try
|
|
{
|
|
|
|
TaobaoMobileCollect.ProductTemp.Add(pb.from_id, pb);
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TaobaoMobileCollect.ProductTemp[pb.from_id] = pb;
|
|
}
|
|
}
|
|
|
|
public bool DeleteAndDown(string html)
|
|
{
|
|
if (string.IsNullOrEmpty(html))
|
|
return false;
|
|
if (html.Contains("<p>商品不存在</p>"))
|
|
return true;
|
|
if (html.Contains(">原商品已下架"))
|
|
return true;
|
|
if (html.Contains(">预售<"))
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
|
|
|
|
public string GetName(string list, ref ProductCollectBase pb, string image)
|
|
{
|
|
string temp = "";
|
|
var m = BaseRegex.GetMatchRegex(ref list, @"\{""spec_key"":""([^""]+?)"",""spec_value"":""([^""]+?)"",""spec_key_id"":([\d]+),""spec_value_id"":([\d]+)");
|
|
if (m.Count == 0)
|
|
m = BaseRegex.GetMatchRegex(ref list, @"\{""spec_key"":""([^""]+?)"",""spec_value"":""([^""]+?)""");
|
|
for (int i = 0; i < m.Count; i++)
|
|
{
|
|
temp += m[i].Groups[1].Value + ":" + m[i].Groups[2].Value + ";";
|
|
bool had = false;
|
|
PropBase p = new PropBase();
|
|
for (int j = 0; j < pb.Props.Count; j++)
|
|
{
|
|
if (pb.Props[j].name == m[i].Groups[1].Value)
|
|
{
|
|
had = true;
|
|
p = pb.Props[j];
|
|
break;
|
|
}
|
|
}
|
|
if (!had)
|
|
{
|
|
p = new PropBase();
|
|
p.name = m[i].Groups[1].Value;
|
|
if (m[i].Groups.Count > 3)
|
|
p.pinduoduo_id = m[i].Groups[3].Value;
|
|
pb.Props.Add(p);
|
|
}
|
|
had = false;
|
|
for (int j = 0; j < p.Values.Count; j++)
|
|
{
|
|
if (p.Values[j].name == m[i].Groups[2].Value)
|
|
{
|
|
p.Values[j].image = image;
|
|
p.Values[j].image_from_url = image;
|
|
had = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!had)
|
|
{
|
|
PropValueBase pv = new PropValueBase();
|
|
if (m[i].Groups.Count > 4)
|
|
pv.id = m[i].Groups[4].Value;
|
|
pv.name = m[i].Groups[2].Value;
|
|
pv.image = image;
|
|
pv.image_from_url = image;
|
|
p.Values.Add(pv);
|
|
}
|
|
}
|
|
return temp;
|
|
}
|
|
|
|
|
|
|
|
public static string GetPinDuoDuoSimilarProductNameByImage(string imageUrl, string pddToken)
|
|
{
|
|
var url = "http://api.yangkeduo.com/api/search/img";
|
|
var data = JsonConvert.SerializeObject(new { flip = "1#1#" + Guid.NewGuid().ToString(), url = imageUrl.StartsWith("//") ? "https:" + imageUrl : imageUrl, sort = "_sales" });
|
|
string userAgent = BaseClass.AndroidUserAgent;
|
|
WebClientx wb = new WebClientx();
|
|
wb.Timeout = 30;
|
|
wb.Headers.Add("AccessToken", pddToken);
|
|
wb.Headers.Add("User-Agent", userAgent);
|
|
wb.Proxy = null;
|
|
wb.Headers.Add("Referer", "Android");
|
|
wb.Headers.Add("Content-Type", "application/json; charset=UTF-8");
|
|
string antiToken = SignHelper.GetSign();
|
|
wb.Headers.Add("anti-token", antiToken);
|
|
wb.Headers.Add("PDD-CONFIG", "00102");
|
|
wb.Headers.Add("p-appname", "pinduoduo");
|
|
wb.Headers.Add("X-PDD-QUERIES", "width=810&height=1440&net=1&brand=Android&model=MuMu&osv=6.0.1&appv=4.70.0&pl=2");
|
|
byte[] postData = Encoding.UTF8.GetBytes(data);
|
|
try
|
|
{
|
|
wb.Headers.Add("ContentLength", postData.Length.ToString());
|
|
var html = Encoding.UTF8.GetString(wb.UploadData(url, "POST", postData));
|
|
JObject jObj = JObject.Parse(html);
|
|
var productName = string.Empty;
|
|
if (jObj["items"] != null)
|
|
{
|
|
foreach (var item in jObj["items"])
|
|
{
|
|
productName = item["goods_name"].ParseToString();
|
|
break;
|
|
}
|
|
}
|
|
return productName;
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
LogSave.Add(e.ToString());
|
|
return "";
|
|
}
|
|
}
|
|
|
|
public static string GetPDDProductImageUrl(long goodsId, string pddToken)
|
|
{
|
|
var imgUrl = GetProductImageUrlViaYouHui(goodsId);
|
|
if (string.IsNullOrEmpty(imgUrl))
|
|
{
|
|
imgUrl = GetProductImageUrlViaProductId(goodsId, pddToken);
|
|
}
|
|
return imgUrl;
|
|
}
|
|
|
|
public static string GetProductImageUrlViaYouHui(long goodsId)
|
|
{
|
|
string imgUrl = string.Empty;
|
|
try
|
|
{
|
|
string url = "https://youhui.pinduoduo.com/goods/goods-detail?goodsId=" + goodsId + "&r=" + BitConverter.ToInt32(Guid.NewGuid().ToByteArray(), 0);
|
|
string html = GetHtml.GetUtf8(url, BaseClass.ChromeUserAgent, "", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3");
|
|
string json = GetHtml.Resove(html, "<script id=\"__NEXT_DATA__\" type=\"application/json\">", "</script>");
|
|
if (!string.IsNullOrEmpty(json))
|
|
{
|
|
JObject jObj = JObject.Parse(json);
|
|
if (jObj != null)
|
|
{
|
|
foreach (string image in jObj["props"]["pageProps"]["goodsDetail"]["goodsGalleryUrls"].ToObject<JArray>())
|
|
{
|
|
imgUrl = image;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
LogSave.Add(ex.ToString());
|
|
}
|
|
return imgUrl;
|
|
}
|
|
|
|
public static string GetProductImageUrlViaProductId(long goodsId, string pddToken)
|
|
{
|
|
string imgUrl = string.Empty;
|
|
try
|
|
{
|
|
string url = "http://yangkeduo.com/goods.html?goods_id=" + goodsId;
|
|
string html = GetHtml.GetUtf8(url, BaseClass.ChromeUserAgent, "PDDAccessToken=" + pddToken);
|
|
string json = GetHtml.Resove(html, "window.rawData=", "}};");
|
|
if (!string.IsNullOrEmpty(json))
|
|
{
|
|
json += "}}";
|
|
JObject jObj = JObject.Parse(json);
|
|
if (jObj != null)
|
|
{
|
|
foreach (string image in jObj["store"]["initDataObj"]["goods"]["topGallery"].ToObject<JArray>())
|
|
{
|
|
imgUrl = image;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
LogSave.Add(ex.ToString());
|
|
}
|
|
return imgUrl;
|
|
}
|
|
|
|
public static string GenerateLowPriceSkus(long goodsId, decimal lowPrice, List<PropBase> productPropList, List<string> lowPriceSpecs, string pddToken)
|
|
{
|
|
string skuContent = string.Empty;
|
|
if (productPropList == null || productPropList.Count < 1)
|
|
return skuContent;
|
|
try
|
|
{
|
|
string url = "http://yangkeduo.com/goods.html?goods_id=" + goodsId;
|
|
string html = GetHtml.GetUtf8(url, BaseClass.ChromeUserAgent, "PDDAccessToken=" + pddToken);
|
|
string json = GetHtml.Resove(html, "window.rawData=", "}};");
|
|
if (!string.IsNullOrEmpty(json))
|
|
{
|
|
json += "}}";
|
|
JObject jObj = JObject.Parse(json);
|
|
if (jObj != null)
|
|
{
|
|
var goodsDetail = jObj["store"]["initDataObj"]["goods"];
|
|
if (goodsDetail != null)
|
|
{
|
|
StringBuilder sbSkuContent = new StringBuilder();
|
|
//把spec value名字从要上传的商品中拿出
|
|
List<string>[] propValueList = new List<string>[2];
|
|
string[] specTypeNames = new string[2];
|
|
for (int i = 0; i < productPropList.Count; i++)
|
|
{
|
|
propValueList[i] = new List<string>();
|
|
specTypeNames[i] = productPropList[i].pinduoduo_id;
|
|
foreach (var propValue in productPropList[i].Values)
|
|
{
|
|
if (propValue.is_used)
|
|
propValueList[i].Add(propValue.id);
|
|
}
|
|
}
|
|
|
|
var skuList = goodsDetail["skus"].ToObject<JArray>();
|
|
JToken pickedSku = null;
|
|
string specFirstValue = null;
|
|
List<string> specSecondList = new List<string>();
|
|
List<JToken> pickedSkuList = new List<JToken>();
|
|
var thumbUrl = string.Empty;
|
|
int specFirstIndex = -1;
|
|
//从低价引流商品中选出一个sku,有上传商品spec第一组中没有的spec
|
|
foreach (var sku in skuList)
|
|
{
|
|
var specs = sku["specs"].ToObject<JArray>();
|
|
decimal groupPrice = sku["groupPrice"].ParseToDecimal();
|
|
int quantity = sku["quantity"].ParseToInt();
|
|
if (specs.Count > 0 && quantity != 0 && groupPrice != 0 && groupPrice <= lowPrice)
|
|
{
|
|
for (int ii = 0; specFirstIndex == -1 && ii < specs.Count; ii++)
|
|
{
|
|
// 比较得出上传商品中第一组spec对应低价引流商品的spec索引
|
|
if (specs[ii]["spec_key_id"].ParseToString() == specTypeNames[0])
|
|
{
|
|
specFirstIndex = ii;
|
|
if (productPropList.Count == 2)
|
|
{
|
|
if (specs[1 - specFirstIndex]["spec_key_id"].ParseToString() != specTypeNames[1])
|
|
{
|
|
specFirstIndex = -1;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
if (specFirstIndex == -1)
|
|
{
|
|
break;
|
|
}
|
|
if (specFirstValue == null && !propValueList[0].Contains(specs[specFirstIndex]["spec_value_id"].ParseToString()))
|
|
{
|
|
specFirstValue = specs[specFirstIndex]["spec_value_id"].ParseToString();
|
|
pickedSku = sku;
|
|
thumbUrl = pickedSku["thumbUrl"].ParseToString();
|
|
thumbUrl = thumbUrl.StartsWith("//") ? "https:" + thumbUrl : thumbUrl;
|
|
if (productPropList.Count == 1)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
if (specFirstValue != null && specs[specFirstIndex]["spec_value_id"].ParseToString() == specFirstValue)
|
|
{
|
|
specSecondList.Add(specs[1 - specFirstIndex]["spec_value_id"].ParseToString());
|
|
pickedSkuList.Add(sku);
|
|
}
|
|
}
|
|
}
|
|
if (specSecondList.Count > 0)
|
|
{
|
|
//比较上传商品中第二组spec中没有的spec进行增加,保证使用最低价格区间的价格并且高于上家价格
|
|
int addNewSpecSecondIndex = -1;
|
|
for (int i = 0; i < specSecondList.Count; i++)
|
|
{
|
|
if (!propValueList[1].Contains(specSecondList[i]))
|
|
{
|
|
foreach (var productSpecFirst in propValueList[0])
|
|
{
|
|
//在上传商品中增加第二组没有的spec
|
|
sbSkuContent.AppendFormat(",{{\"is_onsale\":1,\"limit_quantity\":0,\"price\":\"{0}\",\"weight\":1000,\"multi_price\":\"{1}\"," +
|
|
"\"thumb_url\":\"{2}\",\"out_sku_sn\":\"{3}\",\"quantity\":0,\"spec_id_list\":\"[{4}]\",\"defaultQuantity\":0}}",
|
|
((int)((lowPrice + 1) * 100)).ToString(),
|
|
((int)(lowPrice * 100)).ToString(),
|
|
thumbUrl, goodsId.ToString(),
|
|
productSpecFirst + "," + ChooseSpecValue(lowPriceSpecs, 2, 1, specSecondList[i]));
|
|
}
|
|
addNewSpecSecondIndex = i;
|
|
//只需要增加一组没有的spec即可
|
|
break;
|
|
}
|
|
}
|
|
if (addNewSpecSecondIndex != -1)
|
|
{
|
|
//增加低价引流商品的一组sku
|
|
for (int i = 0; i < propValueList[1].Count; i++)
|
|
{
|
|
if (specSecondList.Contains(propValueList[1][i]))
|
|
{
|
|
//增加低价引流中第二组spec在上传商品中存在的
|
|
var ind = specSecondList.IndexOf(propValueList[1][i]);
|
|
sbSkuContent.AppendFormat(",{{\"is_onsale\":1,\"limit_quantity\":{0},\"price\":\"{1}\",\"weight\":1000,\"multi_price\":\"{2}\"," +
|
|
"\"thumb_url\":\"{3}\",\"out_sku_sn\":\"{4}\",\"quantity\":{5},\"spec_id_list\":\"[{6}]\",\"defaultQuantity\":{7}}}",
|
|
pickedSkuList[ind]["limitQuantity"].ParseToString(),
|
|
((int)((lowPrice + 1) * 100)).ToString(),
|
|
((int)(lowPrice * 100)).ToString(),
|
|
thumbUrl, goodsId.ToString(), pickedSkuList[ind]["quantity"].ParseToString(),
|
|
ChooseSpecValue(lowPriceSpecs, 2, 0, specFirstValue) + "," + ChooseSpecValue(lowPriceSpecs, 2, 1, specSecondList[ind]),
|
|
pickedSkuList[ind]["defaultQuantity"].ParseToString());
|
|
}
|
|
else
|
|
{
|
|
//在低价引流中增加上传商品有但低价引流第二组spec没有的
|
|
sbSkuContent.AppendFormat(",{{\"is_onsale\":1,\"limit_quantity\":0,\"price\":\"{0}\",\"weight\":1000,\"multi_price\":\"{1}\"," +
|
|
"\"thumb_url\":\"{2}\",\"out_sku_sn\":\"{3}\",\"quantity\":0,\"spec_id_list\":\"[{4}]\",\"defaultQuantity\":0}}",
|
|
((int)((lowPrice + 1) * 100)).ToString(),
|
|
((int)(lowPrice * 100)).ToString(),
|
|
thumbUrl, goodsId.ToString(),
|
|
ChooseSpecValue(lowPriceSpecs, 2, 0, specFirstValue) + "," + propValueList[1][i]);
|
|
}
|
|
}
|
|
//在低价引流中增加上传商品中第二组spec中没有的spec,保证有库存
|
|
sbSkuContent.AppendFormat(",{{\"is_onsale\":1,\"limit_quantity\":{0},\"price\":\"{1}\",\"weight\":1000,\"multi_price\":\"{2}\"," +
|
|
"\"thumb_url\":\"{3}\",\"out_sku_sn\":\"{4}\",\"quantity\":{5},\"spec_id_list\":\"[{6}]\",\"defaultQuantity\":{7}}}",
|
|
pickedSkuList[addNewSpecSecondIndex]["limitQuantity"].ParseToString(),
|
|
((int)((lowPrice + 1) * 100)).ToString(),
|
|
((int)(lowPrice * 100)).ToString(),
|
|
thumbUrl, goodsId.ToString(), pickedSkuList[addNewSpecSecondIndex]["quantity"].ParseToString(),
|
|
ChooseSpecValue(lowPriceSpecs, 2, 0, specFirstValue) + "," + ChooseSpecValue(lowPriceSpecs, 2, 1, specSecondList[addNewSpecSecondIndex]),
|
|
pickedSkuList[addNewSpecSecondIndex]["defaultQuantity"].ParseToString());
|
|
}
|
|
}
|
|
else if (specFirstValue != null)
|
|
{
|
|
//只有一个类型的spec
|
|
sbSkuContent.AppendFormat(",{{\"is_onsale\":1,\"limit_quantity\":{0},\"price\":\"{1}\",\"weight\":1000,\"multi_price\":\"{2}\"," +
|
|
"\"thumb_url\":\"{3}\",\"out_sku_sn\":\"{4}\",\"quantity\":{5},\"spec_id_list\":\"[{6}]\",\"defaultQuantity\":{7}}}",
|
|
pickedSku["limitQuantity"].ParseToString(),
|
|
((int)((lowPrice + 1) * 100)).ToString(),
|
|
((int)(lowPrice * 100)).ToString(),
|
|
thumbUrl, goodsId.ToString(), pickedSku["quantity"].ParseToString(),
|
|
ChooseSpecValue(lowPriceSpecs, 1, 0, specFirstValue), pickedSku["defaultQuantity"].ParseToString());
|
|
}
|
|
skuContent = sbSkuContent.ToString();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
LogSave.Add(ex.ToString());
|
|
}
|
|
return skuContent;
|
|
}
|
|
|
|
private static string ChooseSpecValue(List<string> lowPriceSpecs, int itemsCount, int itemIndex, string defaultValue)
|
|
{
|
|
return (lowPriceSpecs != null && lowPriceSpecs.Count == itemsCount && !string.IsNullOrEmpty(lowPriceSpecs[itemIndex])) ? lowPriceSpecs[itemIndex] : defaultValue;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
}
|