Files
KJD/Work/CollectClass/JingXiCollect.cs
T

996 lines
49 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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;
/// <summary>
/// 已经下架的商品集合
/// </summary>
public static List<long> DeleteIds = new List<long>();
public static bool IsIpOver = false;
public static List<string> listIp = null;
/// <summary>
/// 验证码URL,如果有值,代表需要用户输入验证码,进行验证。
/// </summary>
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;
/// <summary>
/// 是否使用服务器缓存
/// </summary>
private static bool UseServerCache = true; // 开发专用,当缓存服务器出故障时,设置为false,调试代码专用
private int IpListCount = 0;
/// <summary>
/// 拼购商品拼购价格字典(商品详情中已无拼购价格信息)
/// </summary>
private Dictionary<string, string> dicPinGouPrice = new Dictionary<string, string>();
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<SkuMapBase> skuMaps = new List<SkuMapBase>(this.Product.SkuMaps);
this.Product.SkuMaps.Clear();
for (int i = 0; i < skuMaps.Count; i++)
{
SkuMapBase sku = skuMaps[i];
List<string> listName = new List<string>();
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, @"<meta [^>]*?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]+?)</script>");
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;
}
/// <summary>
/// 根据获取到的html 读取sku
/// </summary>
/// <param name="skuid"></param>
/// <returns></returns>
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]+?)</script>");
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 += "<img src='" + s + "'>";
});
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<string>(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<string>(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<string>(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<string>();
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<Match>().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<string, string> dicSkuName = new Dictionary<string, string>();
//方法:根据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<string> listSkuNameExt = new List<string>();
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<KeyValueBase> 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<KeyValueBase> list = new List<KeyValueBase>();
//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<string> GetDetailImageList(long skuid, string description)
{
#region
//
// { "content":"<p><img src=\"http://img30.360buyimg.com/popWareDetail/jfs/t1/106784/4/19721/152751/5ea14516E50bb01d1/f136b21cce9e62d8.jpg\"><img src=\"//img10.360buyimg.com/imgzone/jfs/t1/101055/24/18598/163020/5e957063E616b6e61/eef8053df4bf5f12.jpg\"><img src=\"//img10.360buyimg.com/imgzone/jfs/t1/116647/30/1137/181417/5e957063Ec3e2bd21/6b93d6b01e24412e.jpg\"><img src=\"//img10.360buyimg.com/imgzone/jfs/t1/109297/6/12411/163541/5e957064Eb2c1e3f3/e2eb1354e76c6b74.jpg\"><img src=\"//img10.360buyimg.com/imgzone/jfs/t1/97529/1/18600/170168/5e957064E3f067cf8/01f3155103d3bb85.jpg\"><img src=\"//img10.360buyimg.com/imgzone/jfs/t1/98019/8/18708/167835/5e957065E5ee2265e/bf539b786ac88216.jpg\"><img src=\"//img10.360buyimg.com/imgzone/jfs/t1/107920/36/12469/103897/5e957068E072195e7/fd5967af0236ab5d.jpg\"><img src=\"//img10.360buyimg.com/imgzone/jfs/t1/107916/40/12398/66013/5e957065E759c3fba/7d8221c777f60a98.jpg\"><img src=\"//img10.360buyimg.com/imgzone/jfs/t1/101249/3/18625/120447/5e957065Ee5d26194/27f1e899858b7d2a.jpg\"><img src=\"//img10.360buyimg.com/imgzone/jfs/t1/101072/40/18571/143111/5e957065E3f270cf9/6d16738aa9365858.jpg\"><img src=\"//img10.360buyimg.com/imgzone/jfs/t1/94118/2/18522/163003/5e957066Eea34c311/53039077add05274.jpg\"><img src=\"//img10.360buyimg.com/imgzone/jfs/t1/105973/3/18358/190612/5e957066Efca99a4e/9b86601b42226bf3.jpg\"><img src=\"//img10.360buyimg.com/imgzone/jfs/t1/117369/7/1161/153200/5e957066Ea679c2f4/86c5cc6ddf9ac55c.jpg\"><br></p><p><br></p>","plus":false,"isMobileDesc":true,"msg":"","success":"1"}
#endregion
List<string> list = new List<string>();
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, "<li>[\\w\\W]*</li>", "");//过滤掉推荐的商品
//详情图-格式1
Dictionary<string, List<string>> dic = new Dictionary<string, List<string>>();
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;
}
/// <summary>
/// 获取拼团的销量
/// </summary>
/// <param name="skuid"></param>
/// <returns></returns>
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;
}
/// <summary>
/// 获取单购的销量
/// </summary>
/// <param name="skuid"></param>
/// <returns></returns>
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
{
/// <summary>
/// 商品编号
/// </summary>
public long SkuId;
/// <summary>
/// 商品名称
/// </summary>
public string SkuName;
/// <summary>
/// 简短的商品名称,不带SKU标题
/// </summary>
public string PName;
/// <summary>
/// 商品名称扩展,格式为:颜色:黑色;尺寸:20寸
/// 用途:拼多多上货用,为了迎合平多多现有的代码风格,不然要写很多代码;
/// 填写该字段,拼多多上传代码风格就不需要改变
/// </summary>
public string SkuNameExt;
/// <summary>
/// 主图第一张轮播图
/// </summary>
public string Image;
/// <summary>
/// 品牌ID
/// </summary>
public string BrandId;
/// <summary>
/// 品牌
/// </summary>
public string BrandName;
/// <summary>
/// 轮播图
/// </summary>
public List<string> ImageList = new List<string>();
/// <summary>
/// Sku明细
/// </summary>
public List<SkuInfoDetail> SkuDetailList = new List<SkuInfoDetail>();
/// <summary>
/// 拼购价格
/// </summary>
public decimal PinGouPrice;
/// <summary>
/// 原价
/// </summary>
public decimal BeforePrice;
/// <summary>
/// 售价:如果是拼购的,则是拼购价格;如果没有拼购,则是原价
/// </summary>
public decimal SellPrice;
/// <summary>
/// 库存状态ID
/// </summary>
public int StockState;
/// <summary>
/// 库存状态名称
/// </summary>
public string StockStateName;
/// <summary>
/// 运费
/// </summary>
public decimal ExpressPrice;
/// <summary>
/// 店铺ID
/// </summary>
public long ShopId;
/// <summary>
/// 店铺名称
/// </summary>
public string ShopName;
/// <summary>
/// 发货人
/// </summary>
public string Deliver;
/// <summary>
/// 发货地址
/// </summary>
public string DeliverAddress;
/// <summary>
/// 主视频ID
/// </summary>
public string MainVideoId;
/// <summary>
/// 销量
/// </summary>
public decimal SaleNum;
/// <summary>
/// 省份
/// </summary>
public string Province;
/// <summary>
/// 城市
/// </summary>
public string City;
/// <summary>
/// 类目集合
/// </summary>
public List<int> Categorys = new List<int>();
/// <summary>
/// 详情属性集合
/// </summary>
public List<KeyValueBase> Prop = new List<KeyValueBase>();
/// <summary>
/// Sku属性集合
/// </summary>
public List<PropBase> Props = new List<PropBase>();
/// <summary>
/// 详情图集合
/// </summary>
public List<string> DetailImageList = new List<string>();
/// <summary>
/// 详情图集合的html
/// </summary>
public string DetailImageListHTML = "";
/// <summary>
/// 库存数量
/// </summary>
public int StockNumber;
/// <summary>
/// 支持7天无理由退货(使用后不支持)
/// </summary>
public string PromiseMark;
/// <summary>
/// 发货时间
/// </summary>
//public string LogisticsTime;
/// <summary>
/// 采集的结果,空值代表OK
/// </summary>
public string msg = "";
public class SkuInfoDetail
{
public long skuId;
public string Prop1 = "";
public string Prop2 = "";
public string Prop3 = "";
}
}
public enum GoodsStatusEnum
{
/// <summary>
/// 无货
/// </summary>
NotExist,
/// <summary>
/// 有货
/// </summary>
Exist
}
}
}