using AllBase;
using AllBase.Helper;
using NaiBa.Util;
using NaiBa.Util.Extension;
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using WebSocketSharp;
namespace Work.CollectClass
{
/*
* 调用示例:
ProductCollectBase pb = new ProductCollectBase();
pb.from_id=132465123;
pb.from_url = "https://item.m.jd.com/product/" + skuID + ".html";
JingXiCollect tm = new JingXiCollect(pb);
tm.Get();
var p = tm.Product;
*/
public class JingXiCollect
{
public static bool IsProxyOverdue = false;
///
/// 已经下架的商品集合
///
public static List DeleteIds = new List();
public static bool IsIpOver = false;
public static List listIp = null;
///
/// 验证码URL,如果有值,代表需要用户输入验证码,进行验证。
///
public static string VerifyCodeUrl = "";
public string Name = "发布商品";
public bool IsOnSale = true;
public bool IsUseProxy = false;//是否使用代理ip
public bool IsVerify = false; // 京喜采集是否受限
public ProductCollectBase Product;
public GoodsStatusEnum GoodsStatus = GoodsStatusEnum.NotExist;
///
/// 是否使用服务器缓存
///
private static bool UseServerCache = true; // 开发专用,当缓存服务器出故障时,设置为false,调试代码专用
private int IpListCount = 0;
///
/// 拼购商品拼购价格字典(商品详情中已无拼购价格信息)
///
private Dictionary dicPinGouPrice = new Dictionary();
public JingXiCollect(ProductCollectBase product)
{
this.Product = product;
}
public void Get()
{
this.GoodsStatus = GoodsStatusEnum.NotExist;
if (JingXiCollect.VerifyCodeUrl.Length > 0)
return;
//判断商品是否下架
if (JingXiCollect.DeleteIds.Contains(this.Product.from_id))
{
LogSave.Add(this.Name, "商品已经下架:" + Product.from_id);
IsOnSale = false;
return;
}
//采集历史缓存
if (TaobaoMobileCollect.ProductTemp.ContainsKey(Product.from_id))
{
this.Product = TaobaoMobileCollect.ProductTemp[Product.from_id].Clone();
this.GoodsStatus = GoodsStatusEnum.Exist;
return;
}
SkuInfo sm = GetSkuInfo(this.Product.from_id);
if (sm.msg.Contains("404"))
{
JingXiCollect.DeleteIds.Add(this.Product.from_id);
LogSave.Add(this.Name, "商品已经下架:" + Product.from_id);
IsOnSale = false;
return;
}
if (sm.msg.Contains("proxyCount"))
{
JingXiCollect.VerifyCodeUrl = "代理ip已用完";
return;
}
if (sm.msg.Contains("获取京喜商品详情失败"))
{
this.IsVerify = true;
return;
}
if (sm.msg.Contains("spider_check.shtml"))
{
JingXiCollect.VerifyCodeUrl = sm.msg;//通知前端,当前端收到此信息后,可以弹出验证界面,获取cookie--后续继续验证
return;
}
this.Product.id = this.Product.from_id;
this.Product.from_url = "https://item.m.jd.com/product/" + this.Product.from_id + ".html";
string pName = sm.PName.RemoveSpecialChar(":", ":", "/", "\\", "\"", "?", "✅", "◆", "‼️");
//【XX进口】【XX直邮】【XX直供】不可以填入商品标题中,请修改后重新操作【XX进口】【XX直邮】【XX直供】不可以填入商品标题中,请修改后重新操作
//pName = BaseRegex.Relpace(pName, "【.*?】", "");
this.Product.name = pName;//商品名称
this.Product.from_title = pName;//商品标题
this.Product.image = sm.Image;//第一张轮播图
this.Product.image_from_url = sm.Image;//第一张轮播图
this.Product.Images = sm.ImageList;//轮播图
this.Product.content = sm.DetailImageListHTML.Replace("http://img", "//img");
this.Product.express_price = sm.ExpressPrice;//运费
this.Product.price = sm.SellPrice;// 售价:如果是拼购的,则是拼购价格;如果没有拼购,则是原价
this.Product.before_price = sm.BeforePrice;//原价
this.Product.num = (int)sm.SaleNum;//销量
this.Product.saleCount = (int)sm.SaleNum;//销量
this.Product.from_shop_name = sm.ShopName;//店铺名称
this.Product.discountPrice = sm.PinGouPrice;//折扣价格
this.Product.discount = sm.PinGouPrice / sm.BeforePrice;//折扣比例:= 折扣价格 / 原价
this.Product.onlinePrice = Product.discountPrice * Product.shopAddPercent / 100 + new Random(Guid.NewGuid().GetHashCode()).Next((int)(Product.shopAddPriceMin * 100), (int)(Product.shopAddPriceMax * 100)) / 100;
this.Product.state = sm.Province;//省份
this.Product.city = sm.City;//城市
this.Product.from_site_id = 4;//京喜,约定的
this.Product.from = "京喜";
this.Product.from_name = pName;
//this.Product.VideoId = sm.MainVideoId;//视频ID
this.Product.upShopId = sm.ShopId;//上家ID
this.Product.Prop = sm.Prop;//详情属性
//现货:33
//有货:39 or 40
//预定,采购中:36
//无货:其他
if (sm.StockState == 36)
this.Product.logisticsTime = "预售";//发货时间
//this.Product.main_cat_name = "";
//Content:正文:包含正文图片:针对img的集合
//item_size =“”
//item_weight = 1
if (sm.Categorys.Count > 0)
this.Product.cat1 = sm.Categorys[0];
if (sm.Categorys.Count > 1)
this.Product.cat2 = sm.Categorys[1];
if (sm.Categorys.Count > 2)
this.Product.cat3 = sm.Categorys[2];
if (sm.Categorys.Count > 3)
this.Product.cat4 = sm.Categorys[3];
if (sm.Categorys.Count > 0)
{
this.Product.main_cid = sm.Categorys[0];
this.Product.cat_id = sm.Categorys[sm.Categorys.Count - 1];
this.Product.from_cat_id = sm.Categorys[sm.Categorys.Count - 1];
}
this.Product.Props = sm.Props;
//Sku
this.Product.SkuMaps.Clear();
foreach (var x in sm.SkuDetailList)
{
SkuInfo sku = null;
if (x.skuId == sm.SkuId)//已经获取过了,不必重新获取
sku = sm;
else
sku = GetSkuInfo(x.skuId);
if (sku.msg.Contains("spider_check.shtml"))
{
JingXiCollect.VerifyCodeUrl = sku.msg;//通知前端,当前端收到此信息后,可以弹出验证界面,获取cookie--后续继续验证
return;
}
this.Product.SkuMaps.Add(new SkuMapBase()
{
name = sku.SkuNameExt,
//nameLite = "",//此处不需要赋值,自动从name进行赋值
//price = sku.PinGouPrice,//经确认,拼团价为基础价格 2020.6.15
price = sku.SellPrice,//经确认,拼团价为基础价格 2020.6.15
number = (sku.StockStateName == "无货" ? 0 : sku.StockNumber), //new Random(Guid.NewGuid().GetHashCode()).Next(100, 1000),//库存
before_price = sku.BeforePrice,
sale_count = (int)sku.SaleNum,
//online_price = (int)sku.BeforePrice,//单买价
//new_price = (int)sku.PinGouPrice,//团购价
prop_image = sku.Image
});
}
///拼多多只支持2级属性,所以,要将多余2级的属性转换到2级
///参考:淘宝上拼多多的方式:做减法
if (this.Product.Props.Count > 2)//2级以内属性
{
//处理Props:参考淘宝的做法,取属性个数最多的两个Prop
this.Product.Props = sm.Props.OrderByDescending(u => u.Values.Count).ToList();
this.Product.Props.RemoveRange(2, this.Product.Props.Count - 2);
//将多余的SkuMaps删除
List skuMaps = new List(this.Product.SkuMaps);
this.Product.SkuMaps.Clear();
for (int i = 0; i < skuMaps.Count; i++)
{
SkuMapBase sku = skuMaps[i];
List listName = new List();
string[] arrsku = sku.name.Split(new string[] { ";" }, StringSplitOptions.RemoveEmptyEntries);
foreach (var str in arrsku)
{
string propNames = str.Split(':')[0];
if (this.Product.Props.Exists(o => o.name == propNames))
listName.Add(str);
}
//修改name:将蝶羽白;全网通(6GB 128GB);官方标配 ==>蝶羽白;全网通(6GB 128GB)
sku.name = string.Join(";", listName);
if (!this.Product.SkuMaps.Exists(o => o.name == sku.name))
this.Product.SkuMaps.Add(sku);
}
}
foreach (var p in Product.Props)
{
if (sm.Props.Any(pr => pr.name == "颜色"))
{
if (p.name == "颜色")
{
foreach (var v in p.Values)
{
var sku = Product.SkuMaps.FirstOrDefault(s => (s.name + ";").Contains(":" + v.name + ";"));
if (sku != null)
{
v.image = sku.prop_image;
}
}
}
else
continue;
}
else
{
foreach (var v in p.Values)
{
var sku = Product.SkuMaps.FirstOrDefault(s => (s.name + ";").Contains(":" + v.name + ";"));
if (sku != null)
{
v.image = sku.prop_image;
}
}
break;
}
}
//采集历史缓存集合
if (TaobaoMobileCollect.ProductTemp.Count > 1000)//删除最早的一条记录
{
var v = TaobaoMobileCollect.ProductTemp.First();
TaobaoMobileCollect.ProductTemp.Remove(v.Key);
}
if (TaobaoMobileCollect.ProductTemp.ContainsKey(this.Product.from_id))
TaobaoMobileCollect.ProductTemp.Remove(this.Product.from_id);
TaobaoMobileCollect.ProductTemp.Add(this.Product.from_id, this.Product);
//所有采集完毕,标识商品有货,可用
this.GoodsStatus = GoodsStatusEnum.Exist;
}
public static string requestJDCom(string url, string refere, bool isUtf8, string data, string agentIp, string sCookies = "")
{
try
{
string domain = GetHtml.GetDomain(url);
string mainDomain = GetHtml.GetMainDomain(domain);
string cookies = sCookies;
if (sCookies.Length == 0)
{
if (BaseClass.CookiesAllString.ContainsKey(mainDomain))
cookies = BaseClass.CookiesAllString[mainDomain];
else if (BaseClass.CookiesAllString.ContainsKey(domain))
cookies = BaseClass.CookiesAllString[domain];
}
string userAgent = BaseClass.ChromeUserAgent;
userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36";
AllBase.WebClientx wb = new AllBase.WebClientx();
wb.Timeout = 30;
wb.AllowAutoRedirect = true;
wb.Headers.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8");
//wb.Headers.Add("X-Requested-With", "XMLHttpRequest");
wb.Headers.Add("Accept-Encoding", "gzip,deflate");
wb.Headers.Add("Accept-Language", "zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3");
wb.Headers.Add("User-Agent", userAgent);
if (!string.IsNullOrEmpty(refere))
wb.Headers.Add("Referer", refere);
if (!string.IsNullOrEmpty(cookies))
wb.Headers.Add("Cookie", cookies);
wb.Proxy = null;
if (!string.IsNullOrEmpty(agentIp))
{
WebProxy proxy = new WebProxy();
proxy.Address = new Uri(string.Format("http://{0}:{1}", agentIp.Split(':')[0], agentIp.Split(':')[1]));
wb.Proxy = proxy;
}
string rehead = wb.Headers.ToString();
var encode = isUtf8 ? Encoding.UTF8 : Encoding.GetEncoding("gbk");
byte[] b, postData = data == null ? new byte[0] : encode.GetBytes(data);
string html, head;
try
{
if (string.IsNullOrEmpty(data))
{
b = wb.DownloadData(url);
}
else
{
wb.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
wb.Headers.Add("ContentLength", postData.Length.ToString());
b = wb.UploadData(url, "POST", postData);
}
html = encode.GetString(b);
string c = BaseRegex.GetMatchRegexString(wb.ResponseHeaders["Content-Type"], "charset\\s*=\\s*(\\S+)");
if (!string.IsNullOrEmpty(c))
{
c = c.Trim().ToLower().Replace("utf8", "utf-8");
}
if (string.IsNullOrEmpty(c))
c = BaseRegex.GetMatchRegexString(html, @"]*?charset=[""']*([\w-]+)[""']*");
if (!string.IsNullOrEmpty(c))
{
if (c.IndexOf("'") > -1)
c = c.Substring(0, c.IndexOf("'"));
if (c.IndexOf("\"") > -1)
c = c.Substring(0, c.IndexOf("\""));
if (c.IndexOf(" ") > -1)
c = c.Substring(0, c.IndexOf(" "));
if (c.IndexOf(">") > -1)
c = c.Substring(0, c.IndexOf(">"));
if (!string.IsNullOrEmpty(c))
html = Encoding.GetEncoding(c).GetString(b);
}
head = wb.ResponseHeaders.ToString();
}
catch (Exception ee)
{
html = "提交错误:" + ee.Message;
head = "";
}
return GetHtml.Decode(html);
}
catch (Exception e)
{
LogSave.Add("访问网址错误:" + url + " " + e.Message);
return "";
}
}
private string getSkuHtml(long skuid, ref bool canUse)
{
///获取html数据,获取途径:
///1,服务器缓存html
///2,直接获取html
canUse = false;
string html = "";
if (JingXiCollect.UseServerCache)
html = ServerTemp.Get(5, skuid.ToString(), out canUse);
string url = "https://item.m.jd.com/item/mview2?datatype=1&callback=skuInfoCBC&cgi_source=mitem&sku=" + skuid;
string refer = "https://item.m.jd.com/product/" + skuid + ".html";
refer = "";
if (!canUse)
{
html = "";
//html = AllBase.GetHtml.GetUtf8(url, AllBase.BaseClass.ChromeUserAgent);
if (!IsUseProxy)
{
html = Work.GetPostTaobaoHtml.GetUrl(url, refer, false, "");
System.Threading.Thread.Sleep(Randomx.GetId(1000, 2000));
}
string redirect_Url = AllBase.BaseRegex.GetStringJson(ref html, "redirectUrl");
if (redirect_Url != null && redirect_Url.Length > 0 && !IsUseProxy)
{
refer = "https://wqs.jd.com/";
refer = "";
url = "https://m.jingxi.com/item/view?_fd=jdm&sku=" + skuid + "&mitemdomain=item.m.jd.com&datatype=1&callback=skuInfoCBC&cgi_source=mitem";
var htmlx = Work.GetPostTaobaoHtml.GetUrl(url, refer, false, "");
System.Threading.Thread.Sleep(Randomx.GetId(1000, 2000));
var htmlData = BaseRegex.GetMatchMaxRegexString(ref htmlx, "window._itemInfo = \\(([\\s\\S]+?)");
if (!string.IsNullOrEmpty(htmlData) && htmlData.Contains("\"skuId\":\"" + skuid + "\""))
{
html = "skuInfoCBC(" + htmlData.Trim(' ', '\n', '\r', ';', 'r') + ")";
}
else
{
//html = "获取京喜商品详情失败";
this.IsVerify = true;
}
}
}
string skuInfoCBC = "" + BaseRegex.GetMatchRegexString(ref html, "skuInfoCBC\\((\\{[\\w\\W]*\\})\\)");
//redirectUrl: "//m.jd.com/404.htm?errcode=10001"
string redirectUrl = "" + AllBase.BaseRegex.GetStringJson(ref skuInfoCBC, "redirectUrl");
string errCode = "" + AllBase.BaseRegex.GetStringJson(ref skuInfoCBC, "errCode");
if ((string.IsNullOrEmpty(html) || !string.IsNullOrWhiteSpace(redirectUrl) || errCode == "20001") && IsUseProxy) // 请求出现验证的时候 并且使用代理
{
if (listIp != null && listIp.Count > IpListCount && listIp[IpListCount] != null)
{
html = requestJDCom(url, refer, false, "", listIp[IpListCount]);
skuInfoCBC = BaseRegex.GetMatchRegexString(ref html, "skuInfoCBC\\((\\{[\\w\\W]*\\})\\)");
redirectUrl = AllBase.BaseRegex.GetStringJson(ref skuInfoCBC, "redirectUrl");
if (string.IsNullOrEmpty(redirectUrl) && html.Contains("提交错误"))
{
//LogHelper.WriteWithTime(" 代理ip:" + listIp[IpListCount] + "请求失败" + html);
System.Windows.Forms.MessageBox.Show(" 代理ip:" + listIp[IpListCount] + "请求失败" + html);
}
else
{
//LogHelper.WriteWithTime(" 代理ip:" + listIp[IpListCount] + "redirectUrl参数:" + redirectUrl);
System.Windows.Forms.MessageBox.Show(" 代理ip:" + listIp[IpListCount] + "redirectUrl参数:" + redirectUrl);
}
}
}
return html;
}
///
/// 根据获取到的html 读取sku
///
///
///
private SkuInfo GetSkuInfo(long skuid)
{
int getHtmlCount = 0;
reGetHtml:
SkuInfo sku = new SkuInfo();
if ((listIp == null || listIp.Count == 0) && IsUseProxy)
{
bool bo = false;
listIp = BLL.Collect.PddSameScreeningBLL.InitIp(GetProxyHtml.txtUrl, out bo);
if (bo)
{
IsIpOver = true;
sku.msg = "请检查ip套餐是否过期";
}
}
bool canUse = false;
var html = getSkuHtml(skuid, ref canUse);
if (html == "获取京喜商品详情失败")
{
sku.msg = "获取京喜商品详情失败";
}
sku.SkuId = skuid;
string skuInfoCBC = "" + BaseRegex.GetMatchRegexString(ref html, "skuInfoCBC\\((\\{[\\w\\W]*\\})\\)");
//redirectUrl: "//m.jd.com/404.htm?errcode=10001"
if (string.IsNullOrEmpty(skuInfoCBC) && html.Contains("window._itemInfo = "))
{
var htmlData = BaseRegex.GetMatchMaxRegexString(ref html, "window._itemInfo = \\(([\\s\\S]+?)");
if (!string.IsNullOrEmpty(htmlData) && htmlData.Contains("\"skuId\":\"" + skuid + "\""))
{
skuInfoCBC = "skuInfoCBC(" + htmlData.Trim(' ', '\n', '\r', ';', 'r') + ")";
}
}
string redirectUrl = "" + AllBase.BaseRegex.GetStringJson(ref skuInfoCBC, "redirectUrl");
if (string.IsNullOrEmpty(sku.msg) && !string.IsNullOrEmpty(redirectUrl))
sku.msg = redirectUrl;
if (html.Contains("提交错误") && getHtmlCount <= 10)
{
getHtmlCount++;
if (listIp.Count > IpListCount)
listIp.RemoveAt(IpListCount);
goto reGetHtml;
}
if (html.Contains("该商品已下架"))
{
sku.msg = "404";
return sku;
}
if (sku.msg.Length > 0 && IsUseProxy && getHtmlCount <= 10)//取不到值 并且是代理的情况下
{
getHtmlCount++;
if (listIp.Count > IpListCount)
listIp.RemoveAt(IpListCount);
goto reGetHtml;
}
if (sku.msg.Length > 0)
return sku;
sku.SkuName = AllBase.BaseRegex.GetStringJson(ref skuInfoCBC, "skuName");
sku.PName = AllBase.BaseRegex.GetStringJson(ref skuInfoCBC, "pName");
sku.Image = AllBase.BaseRegex.GetStringJson(ref skuInfoCBC, "image")?.Replace("\\x2F", "/").Replace("!q80.dpg.webp", "");
if (string.IsNullOrEmpty(sku.Image))
{
var img = BaseRegex.GetMatchRegexString(ref skuInfoCBC, "\"image\":\\[([\\s\\S]+?)\\],");
if (!string.IsNullOrEmpty(img))
img = img.Split(',')[0].Trim('"');
sku.Image = "//m.360buyimg.com/mobilecms/s750x750_" + img;
}
sku.BrandName = AllBase.BaseRegex.GetStringJson(ref skuInfoCBC, "brandName");
sku.BrandId = AllBase.BaseRegex.GetStringJson(ref skuInfoCBC, "brandId");
sku.PromiseMark = AllBase.BaseRegex.GetStringJson(ref skuInfoCBC, "promiseMark");
sku.StockState = AllBase.BaseRegex.GetIntJson(ref skuInfoCBC, "StockState");
sku.StockStateName = AllBase.BaseRegex.GetStringJson(ref skuInfoCBC, "StockStateName");
sku.StockNumber = AllBase.BaseRegex.GetIntJson(ref skuInfoCBC, "eb");
sku.ShopName = AllBase.BaseRegex.GetStringJson(ref html, "vender");
sku.ShopId = AllBase.BaseRegex.GetMatchMaxRegexString(ref html, "\"deliver\":\".+?\",\"id\":(\\d+)").ParseToLong();
sku.Deliver = AllBase.BaseRegex.GetStringJson(ref html, "deliver");
sku.DeliverAddress = AllBase.BaseRegex.GetStringJson(ref html, "df"); //
sku.MainVideoId = AllBase.BaseRegex.GetStringJson(ref skuInfoCBC, "mainVideoId"); //208594505
sku.ExpressPrice = AllBase.BaseRegex.GetIntJson(ref html, "dcash"); //0
sku.Prop = GetSpecification(skuid); //0
string description = AllBase.BaseRegex.GetStringJson(ref html, "description"); //d14676910654
sku.DetailImageList = GetDetailImageList(skuid, description);
sku.DetailImageList.ForEach(s =>
{
sku.DetailImageListHTML += "
";
});
KeyValueBase city = GetProvince_City(sku.DeliverAddress);
sku.Province = city.Value;//省份
sku.City = city.Key;//城市
//sku.ImageList
string skuInfoCBC_image = AllBase.BaseRegex.GetMatchRegexString(skuInfoCBC, "\\\"image\\\":\\[([\\w\\W]+?)]"); //"jfs/t1/112057/35/11816/136894/5f02c690Ef42f3746/f0c2d6365e028db7.jpg","jfs/t1/148525/31/2184/264063/5f02c685E427bd5c4/1f68bac7953fb631.jpg","jfs/t1/119092/12/11639/206907/5f02c685Ea46ebbfb/10c636358954a177.jpg","jfs/t1/121822/14/6363/214792/5f02c686Ea06c2de9/4f93b4878596a225.jpg","jfs/t1/117172/7/11523/199385/5f02c686E9e1163d4/eada4b07f5fa2759.jpg","jfs/t1/116907/29/11607/208292/5f02c687Ef7079f1b/dc24acfd8b6fd2fc.jpg","jfs/t1/121655/30/6391/182266/5f02c687E7219652e/c18b7cb772e87d7c.jpg","jfs/t1/118719/11/11664/194853/5f02c687Eceeb21a7/910afece15570ce9.jpg","jfs/t1/143578/32/2242/221134/5f02c688E1830c8e9/7c399c424fe58509.jpg","jfs/t1/116031/38/11700/152479/5f02c689Ec4f9cdd6/9d949560bd3788aa.jpg"
if (skuInfoCBC_image != null)
{
new List(skuInfoCBC_image.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries)).ForEach(s =>
{
sku.ImageList.Add("https://m.360buyimg.com/ceco/" + s.Replace("\"", ""));
});
}
//sku.SkuDetailList
var skuInfoCBC_newColorSize = AllBase.BaseRegex.GetMatchRegex(html, "\\{(\\\"dim\\\":[\\s\\S]+?)\\}");// 出现
if (skuInfoCBC_newColorSize.Count == 0)
skuInfoCBC_newColorSize = BaseRegex.GetMatchRegex(html, "\\{(\\\"sequenceNo2\\\":[\\s\\S]+?)\\}");
foreach (Match m in skuInfoCBC_newColorSize)
{
string item = m.Value;
SkuInfo.SkuInfoDetail detail = new SkuInfo.SkuInfoDetail() //{"dim":3,"sequenceNo1":"12","sequenceNo2":"1","sequenceNo3":"0","1":"小款变形手表(绿巨人)","2":"均码","3":"","SpecName":"","skuId":"71389595614"}
{
skuId = AllBase.BaseRegex.GetLongJson(ref item, "skuId"), //"小款变形手表(绿巨人)"
Prop1 = AllBase.BaseRegex.GetStringJson(ref item, "1"), //"均码"
Prop2 = AllBase.BaseRegex.GetStringJson(ref item, "2"), //""
Prop3 = AllBase.BaseRegex.GetStringJson(ref item, "3") //71389595614
};
sku.SkuDetailList.Add(detail);
}
// 获取价格(因原接口无法获取拼购价,需要使用sku列表获取单独的拼购价格,将价格获取放到sku列表获取后)
sku.BeforePrice = BaseRegex.GetDecimalJson(ref skuInfoCBC, "op");//原价
sku.PinGouPrice = BaseRegex.GetDecimalJson(ref skuInfoCBC, "bp");//拼购价
// 获取所有sku的拼购价格
if (sku.PinGouPrice == 0 && dicPinGouPrice.Keys.Count == 0)
{
if (BaseClass.UserName == "18355183710")
FileBase.WriteAllText("pingou_html.txt", "pingou_info: ");
//var shops = GlobalConfig.JDShopLoginList.Where(s => s.LoginStatus == "登录成功").ToList();
//var shop = shops.Count > 0 ? shops[Randomx.GetId(shops.Count)] : new LittleCow.Model.Result.JDShopLoginInfo()
//{
// Cookies = @"1BAE23EC9D9791A1474EC42D7F7F8C83B7231A71F615C334906B0C3758FA60CABDE9502205933B0331B61610000AF0F9D0125204144AA5AB85D21A72BD6584849C2900A7B54574A9DC4A0DB96997B6C6909A236512E657BF74EA85E8CD750D055C6EACA03A7A45A03A801C2AB8EC11C78BB83B2E1736FF837978DA5B46D1DC999478FBA07B98566A44F74DBD9974339C",
//};
var Cookies = @"1BAE23EC9D9791A1474EC42D7F7F8C83B7231A71F615C334906B0C3758FA60CABDE9502205933B0331B61610000AF0F9D0125204144AA5AB85D21A72BD6584849C2900A7B54574A9DC4A0DB96997B6C6909A236512E657BF74EA85E8CD750D055C6EACA03A7A45A03A801C2AB8EC11C78BB83B2E1736FF837978DA5B46D1DC999478FBA07B98566A44F74DBD9974339C";
string skuIdStr = "";
for (int i = 0; i < sku.SkuDetailList.Count; i++)
{
skuIdStr += sku.SkuDetailList[i].skuId + ",";
if ((i + 1) % 20 == 0 || i == sku.SkuDetailList.Count - 1)
{
//var cookie = shop.Cookies;
var cookie = Cookies;
string url = "https://m.jingxi.com/pingou_api/getskusprice?skuids=" + skuIdStr.TrimEnd(',');
string refer = "";
var pingouHtml = GetPostTaobaoHtml.GetUrl(url, refer, false, "", cookie);
if (BaseClass.UserName == "18355183710")
FileBase.AppendAllText("pingou_html.txt", pingouHtml);
System.Threading.Thread.Sleep(Randomx.GetId(500, 1500));
if (string.IsNullOrEmpty(pingouHtml) || !pingouHtml.Contains("\"bp\"") || !pingouHtml.Contains("\"op\"") || !pingouHtml.Contains("\"id\""))
pingouHtml = GetPostTaobaoHtml.GetUrl(url, refer, false, "", cookie);
System.Threading.Thread.Sleep(Randomx.GetId(500, 1500));
if (!string.IsNullOrEmpty(pingouHtml))
{
var pingouArr = pingouHtml.Split('{');
foreach (var txt in pingouArr)
{
var t = txt;
if (txt.Contains("\"bp\"") && txt.Contains("\"op\"") && txt.Contains("\"id\""))
{
var pingou_id = BaseRegex.GetStringJson(ref t, "id");
var pingou_bp = BaseRegex.GetStringJson(ref t, "bp");
this.dicPinGouPrice[pingou_id] = pingou_bp;
}
}
}
skuIdStr = "";
}
}
}
if (sku.PinGouPrice == 0 && dicPinGouPrice.ContainsKey(sku.SkuId.ToString()))
{
sku.PinGouPrice = dicPinGouPrice[sku.SkuId.ToString()].ParseToDecimal();
if (sku.PinGouPrice > 0 && !html.Contains("\"bp\"") && html.Contains("\"op\""))
{
//canUse = false;
html = html.Replace("\"op\"", "\"bp\":\"" + dicPinGouPrice[sku.SkuId.ToString()] + "\",\"op\"");
}
}
if (sku.PinGouPrice > 0)//有拼购,销售价格为拼购价格
{
sku.SellPrice = sku.PinGouPrice;
sku.SaleNum = this.GetPinTuanCount(sku.SkuId);//获取拼团的销量
//string pingou_member_count = AllBase.BaseRegex.GetStringJson(ref skuInfoCBC, "pingou_member_count");
//sku.SaleNum = this.Unit_Conversion(pingou_member_count);
}
else//没有拼购,则销售价格为市场价格
{
sku.SellPrice = AllBase.BaseRegex.GetDecimalJson(ref skuInfoCBC, "p");//市场价
sku.SaleNum = this.GetGoodCount(sku.SkuId);//获取单购的销量
}
//sku.Categorys
string category = AllBase.BaseRegex.GetMatchRegexString(ref skuInfoCBC, "category\":\\[(.+?)\\]"); //"1672","2599","5266"
if (!category.IsNullOrEmpty())
{
new List(category.Split(new string[] { ",", "\"" }, StringSplitOptions.RemoveEmptyEntries)).ForEach(s =>
{
sku.Categorys.Add(s.ParseToInt());
});
}
//sku.Props
string saleProp = AllBase.BaseRegex.GetMatchRegexString(ref skuInfoCBC, "saleProp\":\\{(.+?)\\}").Replace("\"", ""); //"1:颜色,2:款式,3:"
new List(saleProp.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries)).ForEach(s =>
{
int propId = s.Split(':')[0].ParseToInt();
string propName = s.Split(':')[1];
if (!string.IsNullOrEmpty(propName))
{
sku.Props.Add(new PropBase() { id = propId, name = propName, sort = propId });
}
});
//sku.Props.Values
string salePropSeq = AllBase.BaseRegex.GetMatchRegexString(ref skuInfoCBC, "salePropSeq\":\\{(.+?)\\}"); //"1":["蓝色奥特曼(可变形可投影)","蜘蛛侠(可变形可投影)","钢铁侠(可变形可投影)","蝙蝠侠(可变形可投影)","绿巨人(可变形可投影)","美国队长(可变形可投影)","冰雪奇缘(可变形可投影)","变形金刚(可变形可投影)","小款变形手表(宝石蓝)没投影","小款变形手表(火焰红)没投影","小款变形手表(没投影)","小款变形手表(绿巨人)"],"2":["均码"],"3":[""]
var mm = AllBase.BaseRegex.GetMatchRegex(salePropSeq, "\"(\\d+)\":\\[(.*?)\\]");
var imgMatchList = new List();
try
{
var imgMatchStr = BaseRegex.GetMatchRegexString(ref skuInfoCBC, "\"pingou\":([\\s\\S]+?)\"daojia\"");
var imgMatch = BaseRegex.GetMatchRegex(ref imgMatchStr, "\"imagePath\":\"([\\s\\S]*?)\"select\"");
imgMatchList.AddRange(imgMatch.Cast().Select(m => m.ToString()).ToList());
}
catch
{
}
foreach (Match v in mm)
{
int v1 = v.Groups[1].Value.ParseToInt();
var p = sku.Props.Find(o => o.id == v1);
if (p == null)
continue;
string[] v2 = v.Groups[2].Value.Replace("\"", "").Replace("[", "").Replace("]", "").Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries);
for (int i = 0; i < v2.Length; i++)
{
var pv = new PropValueBase() { id = i.ToString(), value = v2[i], name = v2[i] };
var image = imgMatchList.FirstOrDefault(im => im.Contains("\"" + pv.name + "\""));
image = BaseRegex.GetStringJson(ref image, "imagePath");
//m.360buyimg.com/mobilecms/s800x800_jfs/t1/120893/26/6529/254083/5f03e2bdE25f7e708/3539b3d189167c32.jpg!q80.dpg
if (!string.IsNullOrEmpty(image))
{
image = "http://m.360buyimg.com/mobilecms/s800x800_" + image;
pv.image = image;
pv.image_from_url = image;
}
p.Values.Add(pv);
//pr.value = v;
//pr.name = mm[j].Groups[2].Value;
//pr.number = new Random(Guid.NewGuid().GetHashCode()).Next(100, 1000);
//pr.image = image;
//pr.image_from_url = image;
}
}
//去除sku.Props.Values为空的Props
sku.Props = sku.Props.Where(o => o.Values.Count > 0).ToList();
sku.SkuNameExt = this.GetSkuNameEx(sku);
//缓存html
if (JingXiCollect.UseServerCache)
{
if (!canUse)
//ServerTemp.Set(5, skuid.ToString(), html);
IdFessionTaobao.ConcurrentQueueHtmlSaveServer.Enqueue(new Work.SaveServerParm() { SaveType = 5, ProuctId = skuid.ToString(), SaveHtml = html });
}
return sku;
}
private string GetSkuNameEx(SkuInfo sku)
{
SkuInfo.SkuInfoDetail skuDetail = sku.SkuDetailList.Find(o => o.skuId == sku.SkuId);
if (skuDetail == null)
skuDetail = sku.SkuDetailList.Find(o => sku.SkuName.EndsWith(o.Prop1 + " " + o.Prop2 + " " + o.Prop3));
if (skuDetail == null)
skuDetail = sku.SkuDetailList.Find(o => sku.SkuName.EndsWith(o.Prop1 + " " + o.Prop2));
Dictionary dicSkuName = new Dictionary();
//方法:根据skuDetail.Prop1模糊查找类别
foreach (var prop in sku.Props)
{
foreach (var v1 in prop.Values)
{
if (v1.name == skuDetail.Prop1 || v1.name == skuDetail.Prop2 || v1.name == skuDetail.Prop3)
{
dicSkuName.Add(prop.name, v1.name);
break;//退出当前循环
}
}
}
//另一种方式(备用):根据skuDetail.Prop1的索引,来获取:Prop1为sku.Props[0].name,Prop1为sku.Props[1].name。这种方式应该可行。暂时用第一种方法
List listSkuNameExt = new List();
foreach (var kv in dicSkuName)
listSkuNameExt.Add(kv.Key + ":" + kv.Value);
return string.Join(";", listSkuNameExt);
}
private KeyValueBase GetProvince_City(string address)
{
string strProvince = "";
string strCity = "";
string[] provice =
"上海,北京,天津,重庆,黑龙江,辽宁,内蒙古,吉林,河北,河南,山西,山东,陕西,青海,宁夏,甘肃,新疆,西藏,四川,云南,贵州,广西,湖南,湖北,安徽,江苏,浙江,广东,福建,海南,台湾,香港,澳门".Split(',');
string[] city =
"上海,北京,天津,重庆,哈尔滨,沈阳,呼和浩特,长春,石家庄,郑州,太原,济南,西安,西宁,银川,兰州,乌鲁木齐,拉萨,成都,昆明,贵阳,南宁,长沙,武汉,合肥,南京,杭州,广州,福州,海口,台北,香港,澳门".Split(',');
if (!string.IsNullOrEmpty(address))
{
for (int i = 0; i < provice.Length; i++)
{
if (address.Contains(provice[i]))
{
strProvince = provice[i];
if (address.Length < 4) //直辖市 获取到的长度小于4 直辖市的省和市都是一样的
strCity = city[i];
else
strCity = address.Replace(provice[i], ""); //现改成实际地址
break;
}
}
}
return new KeyValueBase(strCity, strProvince);
}
private List GetSpecification(long skuid)
{
#region
// https://wq.jd.com/commodity/itembranch/getspecification?callback=commParamCallBackA&skuid=68021431223&t=0.3812012434945995
// commParamCallBackA({
// "errcode":"0",
// "msg":"",
// "data":{ "productSkuId":68021431223,"wReadMe":"","propGroups":[{"groupName":"主体","atts":[{"attName":"充电时间","categoryGroupAttId":"109107","attRemark":"","vals":["60-120分钟"],"sort":6}],"sort":1}]}
//})
#endregion
List list = new List();
//list.Add(new KeyValueBase("商品编号", skuid.ToString()));
string url = "https://wq.jd.com/commodity/itembranch/getspecification?callback=commParamCallBackA&skuid=" + skuid;
string html = AllBase.GetHtml.GetUtf8(url, AllBase.BaseClass.ChromeUserAgent);
var atts = BaseRegex.GetMatchRegex(ref html, "\\{\\\"attName\\\".*?\\}");
foreach (Match m in atts)
{
string att = m.Value;
string attName = BaseRegex.GetStringJson(ref att, "attName");
string vals = BaseRegex.GetMatchRegexString(ref att, "\"vals\":\\[\"(.+?)\"\\]");
list.Add(new KeyValueBase(attName, vals));
}
return list;
}
private List GetDetailImageList(long skuid, string description)
{
#region
//
// { "content":"












","plus":false,"isMobileDesc":true,"msg":"","success":"1"}
#endregion
List list = new List();
string url = "https://wqsitem.jd.com/detail/" + skuid + "_" + description + "_normal.html";
string html = AllBase.GetHtml.GetUtf8(url, AllBase.BaseClass.ChromeUserAgent);
html = AllBase.BaseRegex.Relpace(html, "[\\w\\W]*", "");//过滤掉推荐的商品
//详情图-格式1
Dictionary> dic = new Dictionary>();
MatchCollection atts1 = BaseRegex.GetMatchRegex(ref html, "image:url\\((.+?)\\)");
MatchCollection atts = atts1;
if (atts.Count == 0)
{
//详情图-格式2
MatchCollection atts2 = BaseRegex.GetMatchRegex(ref html, "src=[\"|'](.+?)[\"|']");
if (atts2.Count > atts.Count)
atts = atts2;
}
if (atts.Count == 0)
{
//详情图-格式2
MatchCollection atts2 = BaseRegex.GetMatchRegex(ref html, "src=[\\\\\"|'](.+?)[\\\\\"|']");
if (atts2.Count > atts.Count)
atts = atts2;
}
foreach (Match m in atts)
{
list.Add(m.Groups[1].Value.Trim('\'').Trim('"').Replace("http://img", "//img"));
}
return list;
}
///
/// 获取拼团的销量
///
///
///
private decimal GetPinTuanCount(long skuid)
{
string url = "https://wq.jd.com/pingou_api/GetBatTuanNum?callback=pgSearchNumCbB&skuids=" + skuid;
string responseString = AllBase.GetHtml.GetUtf8(url, AllBase.BaseClass.ChromeUserAgent);
decimal saleNum = 0;
decimal.TryParse(AllBase.BaseRegex.GetStringJson(ref responseString, "tuancount"), out saleNum);
return saleNum;
}
///
/// 获取单购的销量
///
///
///
private decimal GetGoodCount(long skuid)
{
string url = "https://wq.jd.com/commodity/comment/getcommentlist?callback=skuJDEvalA&version=v2&sceneval=2&score=0&sku=" + skuid + "&sorttype=5";
string refere = "https://item.m.jd.com/product/2490601.html?sku=" + skuid;
string html = Work.GetPostTaobaoHtml.GetUrl(url, refere, false, "");
decimal saleNum = 0;
decimal.TryParse(AllBase.BaseRegex.GetStringJson(ref html, "GoodCount"), out saleNum);
return saleNum;
}
private class SkuInfo
{
///
/// 商品编号
///
public long SkuId;
///
/// 商品名称
///
public string SkuName;
///
/// 简短的商品名称,不带SKU标题
///
public string PName;
///
/// 商品名称扩展,格式为:颜色:黑色;尺寸:20寸
/// 用途:拼多多上货用,为了迎合平多多现有的代码风格,不然要写很多代码;
/// 填写该字段,拼多多上传代码风格就不需要改变
///
public string SkuNameExt;
///
/// 主图第一张轮播图
///
public string Image;
///
/// 品牌ID
///
public string BrandId;
///
/// 品牌
///
public string BrandName;
///
/// 轮播图
///
public List ImageList = new List();
///
/// Sku明细
///
public List SkuDetailList = new List();
///
/// 拼购价格
///
public decimal PinGouPrice;
///
/// 原价
///
public decimal BeforePrice;
///
/// 售价:如果是拼购的,则是拼购价格;如果没有拼购,则是原价
///
public decimal SellPrice;
///
/// 库存状态ID
///
public int StockState;
///
/// 库存状态名称
///
public string StockStateName;
///
/// 运费
///
public decimal ExpressPrice;
///
/// 店铺ID
///
public long ShopId;
///
/// 店铺名称
///
public string ShopName;
///
/// 发货人
///
public string Deliver;
///
/// 发货地址
///
public string DeliverAddress;
///
/// 主视频ID
///
public string MainVideoId;
///
/// 销量
///
public decimal SaleNum;
///
/// 省份
///
public string Province;
///
/// 城市
///
public string City;
///
/// 类目集合
///
public List Categorys = new List();
///
/// 详情属性集合
///
public List Prop = new List();
///
/// Sku属性集合
///
public List Props = new List();
///
/// 详情图集合
///
public List DetailImageList = new List();
///
/// 详情图集合的html
///
public string DetailImageListHTML = "";
///
/// 库存数量
///
public int StockNumber;
///
/// 支持7天无理由退货(使用后不支持)
///
public string PromiseMark;
///
/// 发货时间
///
//public string LogisticsTime;
///
/// 采集的结果,空值代表OK
///
public string msg = "";
public class SkuInfoDetail
{
public long skuId;
public string Prop1 = "";
public string Prop2 = "";
public string Prop3 = "";
}
}
public enum GoodsStatusEnum
{
///
/// 无货
///
NotExist,
///
/// 有货
///
Exist
}
}
}