using Api.Framework.Tools; using Api.Framework.Utils; using CsharpHttpHelper; using Newtonsoft.Json; using System; using System.Collections; using System.Collections.Generic; using System.Drawing; using System.IO; using System.Linq; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; using TBAppraisalTools.Entitys; namespace TBAppraisalTools { /// /// 淘宝解析类 /// public class TbAnalysis { /// /// 获得淘宝的基础信息 /// /// 宝贝id /// 淘宝的cookies public TbBaseInfo FindTbBaseInfo(string itemId) { // 目标: 店铺名称,店铺头像,标题,主图,价格,月销 优惠券金额,有效期 - 自定义 try { var html = ""; //var item = TbTools.GetH5Result("mtop.taobao.detail.getdetail", new { itemNumId = itemId, exParams = new { id = itemId }, detail_v = "3.1.1", ttid = "2018@taobao_iphone_9.9.9", utdid = "123123123123123" }, out html); var item = TbTools.GetH5Result("mtop.taobao.detail.getdetail", new { itemNumId = itemId, exParams = new { id = itemId }, ttid = "2016@taobao_h5_2.0.0", isSec = "0", ecode = "0", AntiFlood = "true", AntiCreep = "true", H5Request = "true", type = "jsonp", dataType = "jsonp" }, out html); var _item = item["item"] as Dictionary; var sellerId = string.Empty; //这里可以通过图片的地址获取店铺的id if (_item.ContainsKey("images")) { var images = _item["images"] as ArrayList; if (images != null && images.Count != 0) { var reg = Regex.Match(images[0].ToString(), @"http://img.alicdn.com/imgextra/i\d/(?<店铺Id>\d+)/"); if (reg.Success) sellerId = reg.Groups["店铺Id"].Value; } } var price = string.Empty;//价格 var sellCount = string.Empty; var apiStack = item["apiStack"] as ArrayList; if (apiStack != null && apiStack.Count != 0) { var _apiStack = apiStack[0] as Dictionary; if (_apiStack.ContainsKey("value")) { var valueJsonStr = _apiStack["value"].ToString(); var valueJson = HttpExtend.JsonToDictionary(valueJsonStr); #region 获取销量 sellCount var itemTag = valueJson["item"] as Dictionary; if (itemTag.ContainsKey("sellCount")) sellCount = itemTag["sellCount"].ToString(); #endregion #region 获取价格 price var priceTag = valueJson["price"] as Dictionary; if (priceTag.ContainsKey("price")) { var priceSub = priceTag["price"] as Dictionary; if (priceSub.ContainsKey("priceText")) price = priceSub["priceText"].ToString(); } if (string.IsNullOrEmpty(price) && priceTag.ContainsKey("transmitPrice")) { var transmitPrice = priceTag["transmitPrice"] as Dictionary; if (transmitPrice.ContainsKey("priceText")) price = transmitPrice["priceText"].ToString(); } if (!string.IsNullOrEmpty(price) && price.Contains("-")) //TODO 这里可能还存在带问号的价格,目前不清楚是什么情况,先空着 price = price.Split('-')[0]; #endregion } } var _seller = item["seller"] as Dictionary; //店铺名称 var shopName = _seller["shopName"].ToString(); //店铺图片 string shopIcon = _seller["shopIcon"].ToString(); shopIcon = string.IsNullOrEmpty(shopIcon) ? "https://ss2.bdstatic.com/8_V1bjqh_Q23odCf/pacific/1659832877.jpg" : shopIcon.StartsWith("http") ? _seller["shopIcon"].ToString() : "http:" + _seller["shopIcon"].ToString(); if (string.IsNullOrEmpty(shopIcon) || shopName == "天猫超市") shopIcon = "https://ss2.bdstatic.com/8_V1bjqh_Q23odCf/pacific/1659832877.jpg"; var userId = _seller["userId"].ToString(); //主图图片 var item_image = string.Empty; if (_item.ContainsKey("images")) item_image = (_item["images"] as ArrayList)[0].ToString(); //商品标题 var item_title = _item["title"].ToString(); return new TbBaseInfo() { ItemId = itemId, ItemImage = item_image, ItemTitle = item_title, Price = price, SellCount = sellCount, ShopIcon = shopIcon, ShopName = shopName, UserId = userId, SellerId = sellerId }; } catch (Exception ex) { return null; } } private Random ra = new Random(); /// /// 生成优惠券图片 /// /// 宝贝的信息 /// 返回生成后优惠券的路径,异常直接报错 public string GenerateCouponImage(TbBaseInfo tb) { try { if (File.Exists(TbTools.TBCONFIGJSON))//存在优惠券模板的情况 { var objDic = JsonConvert.DeserializeObject>(File.ReadAllText(TbTools.TBCONFIGJSON)); if (objDic != null) { var panel = objDic.FirstOrDefault(f => f.Key.Contains("panel")); if (!default(KeyValuePair).Equals(panel)) { TbConfig tbConfig = objDic[panel.Key] as TbConfig; if (!File.Exists(TbTools.BACKICO)) throw new Exception("不存在优惠券背景图"); var backImage = Tools.RefreshFileAddress(TbTools.BACKICO, TbTools.BASEPATH + @"\", Util.MapPath(TbTools.BASEPATH)); using (var backIco = new Bitmap(Image.FromFile(backImage), tbConfig.C_Size)) { using (Graphics g = Graphics.FromImage(backIco)) { #region 计算优惠券价 discounts var srcPrice = float.Parse(tb.Price); var rates = Class1.Config.CouponDenomination.Split('-'); float min = 0.3f;//默认最小比例 float max = 0.6f;//默认最大比例 if (rates.Length == 2) { min = float.Parse(rates[0]) / 100f;//最小比例 max = float.Parse(rates[1]) / 100f;//最大比例 } var discounts = (ra.Next(int.Parse(Math.Ceiling(srcPrice * min).ToString()), int.Parse(Math.Ceiling(srcPrice * max).ToString()))); //默认选中取整 时 - 商品现价要是小于10的时候,将不会取整,其他的取十的倍数 if (Class1.Config.IsRounding == Api.Framework.Enums.SwitchType.开启) { if (discounts > 10 && discounts < srcPrice) { double xx = discounts / 10; discounts = int.Parse((Math.Round(xx) * 10).ToString()); } } #endregion foreach (KeyValuePair item in objDic) { var temp = item.Value; if (item.Key.Contains("label")) { var validityBegin = string.Empty;//优惠券有效期开始日期 var validityEnd = string.Empty;//优惠券有效期结局日期 #region 计算优惠券有效期区间 if (temp.T_Text.Contains("#开始时间") || temp.T_Text.Contains("#结束时间")) { var tempDate = DateTime.Now.AddDays(Class1.Config.ManufacturePlansAddDay); validityBegin = tempDate.ToString("yyyy.MM.dd"); validityEnd = tempDate.AddDays(Class1.Config.ExpirationDate).ToString("yyyy.MM.dd"); } #endregion var txt = temp.T_Text .Replace("#店铺名称", tb.ShopName) .Replace("#商品标题", tb.ItemTitle) .Replace("#商品现价", tb.Price) .Replace("#月销售量", tb.SellCount) .Replace("#优惠券价", discounts.ToString()) .Replace("#券后特价", (float.Parse(tb.Price) - discounts).ToString()) .Replace("#开始时间", validityBegin) .Replace("#结束时间", validityEnd); SizeF crSize = new SizeF(); crSize = g.MeasureString(txt, temp.T_Font); txt = Tools.RefreshTextFormat(tbConfig.C_Size.Width, temp.C_Point.X, txt, crSize.Width); g.DrawString(txt, temp.T_Font, new SolidBrush(temp.T_ForeColor), temp.C_Point); } else if (item.Key.Contains("picbox")) { var tagDic = CsharpHttpHelper.HttpExtend.JsonToDictionary(temp.C_Tag.ToString()); var imageInfo = new ImageInfo() { ImagePath = tagDic["ImagePath"].ToString(), Shape = tagDic["Shape"].ToString() == "false" ? false : true, Varible = tagDic["Varible"].ToString() }; Bitmap bitmap = null; if (imageInfo.Varible == "#店铺头像" || imageInfo.Varible == "#商品主图") { var cacheFile = TbTools.RandomFile(); Tools.DownloadImage(imageInfo.Varible == "#商品主图" ? tb.ItemImage : tb.ShopIcon, cacheFile); bitmap = new Bitmap(Tools.ReadImageFile(cacheFile), temp.C_Size); } else if (imageInfo.Varible == "#其他图片") { var otherImage = Tools.RefreshFileAddress(imageInfo.ImagePath, @"评价工具\其他图片\", TbTools.OTHERSICOPATH); bitmap = Tools.ReadImageFile(otherImage); } if (bitmap != null) { g.DrawImage(bitmap, temp.C_Point); bitmap.Dispose(); bitmap = null; } } } } var url = TbTools.RandomFile(); backIco.Save(url); return url; } } } } else throw new Exception("未找到优惠券模板配置文件"); } catch (Exception ex) { throw ex; } return string.Empty; } /// /// 通过宝贝id获取宝贝评价标签集合 /// /// 宝贝id /// 返回标签集合 public List FindTagsByItemId(string itemId) { try { var tags = TbTools.FindTagsByItemId(itemId); if (tags != null) tags = tags.Where(f => f.posi).ToList(); return tags; } catch (Exception ex) { throw ex; } } /// /// 获取PC端的评语信息 /// /// 宝贝Id /// 店铺Id /// 分析多少页 /// 标签的id /// public List FindPcCommentInfos(string itemId, string sellerId, int analyticPageNum, int tagid = 0) { try { try { var comments = new List(); for (int i = 1; i <= analyticPageNum; i++) { //int error = 0; // Next: string url = string.Format("https://rate.tmall.com/list_detail_rate.htm?itemId={0}&sellerId={1}&order=3¤tPage={2}&append=0&content=1&posi=1&picture=&callback=jsonp443&tagId={3}", itemId, sellerId, analyticPageNum, tagid); //var cookies = Tools.ReadTBCookies(); HttpHelper http = new HttpHelper(); var item = http.GetItem(url); item.Cookie = TbTools.RandomTbCookies(); item.Allowautoredirect = true; item.UserAgent = @"Mozilla/4.0 (compatible; MSIE 9.0; Windows NT6.1)"; item.ContentType = @"application/x-www-form-urlencoded"; var result = http.GetHtml(item); var html = result.Html.Trim(); //TbCookies = result.Cookie;//这个就不保存了,因为写了淘宝心跳 if (!html.StartsWith("jsonp443")) throw new Exception("评语解析不出:" + html); html = html.Replace("jsonp443(", "").Replace(")", ""); var json = HttpExtend.JsonToDictionary(html) as Dictionary; if (json != null && json.ContainsKey("rgv587_flag"))//登录过期 throw new Exception("淘宝已经掉线,请重新登录~!");//这里可能会是频率显示(歇息一下,喝口水什么的) if (json == null || !json.ContainsKey("rateDetail")) throw new Exception("未获得评价数据:" + html); json = json["rateDetail"] as Dictionary; if (!json.ContainsKey("rateList")) throw new Exception("该宝贝没有评论数据"); var list = json["rateList"] as ArrayList; foreach (Dictionary obj in list) { var pics = obj["pics"] as ArrayList; var comment = new Comment() { position = obj["position"].ToString(), rateContent = obj["rateContent"].ToString() }; if (pics != null) { foreach (var t in pics) { comment.pics.Add("http:" + t); } } comments.Add(comment); } if (json.ContainsKey("paginator"))//获取评论区的页数 { var paginator = json["paginator"] as Dictionary; var lastPage = int.Parse(paginator["lastPage"].ToString());//总页数 var page = int.Parse(paginator["page"].ToString());//当前页数 if (lastPage <= page) break; } } return comments; } catch (Exception ex) { throw ex; } //return new List(); } catch (Exception ex) { throw ex; } } /// /// 获取移动端的评语信息 /// /// 宝贝Id /// 店铺Id /// 分析多少页 /// 标签Id /// public List FindWebappCommentInfos(string itemId, int analyticPageNum) { try { List commentList = new List(); TaskTool tasks = new TaskTool(); for (int i = 1; i <= analyticPageNum; i++) { var _i = i; tasks.AddTask(delegate { try { //获取评价json数据 var json = string.Empty; var _url = @"https://rate.taobao.com/feedRateList.htm?auctionNumId=" + itemId + "&userNumId=" + new Random(Guid.NewGuid().GetHashCode()).Next(100000, 999999).ToString() + new Random(Guid.NewGuid().GetHashCode()).Next(10000, 99999) + "¤tPageNum=" + _i + "&pageSize=20&rateType=&orderType=sort_weight&attribute=&sku=&hasSku=false&folded=0&callback=jsonp_tbcrate_reviews_list"; HttpHelper http = new HttpHelper(); var temp = http.GetItem(_url); temp.Cookie = TbTools.RandomTbCookies(); temp.SetProxyipCDN(); temp.Allowautoredirect = true; temp.UserAgent = @"Mozilla/4.0 (compatible; MSIE 9.0; Windows NT6.1)"; temp.ContentType = @"application/x-www-form-urlencoded"; var rst = http.GetHtml(temp); //if (!string.IsNullOrEmpty(rst.Cookie)) rst.UpdateCookies(temp.Cookie);//更新cookies json = rst.Html.Replace("jsonp_tbcrate_reviews_list(", "").Trim(); json = json.Substring(0, json.Length - 1); //StringBuilder strb = new StringBuilder(); //StringBuilder strbPic = new StringBuilder(); var obj = HttpExtend.JsonToDictionary(json); #region 最大页数 var maxPageObj = obj["maxPage"]; var maxPage = -1; if (maxPageObj != null) maxPage = int.Parse(maxPageObj.ToString()); #endregion #region 获取评语和图片数据 var comments = obj["comments"] as ArrayList; if (comments != null && comments.Count != 0) { foreach (var _item in comments) { var pj = new Comment(); var item = _item as Dictionary; var photos = item["photos"] as ArrayList; if (photos != null && photos.Count != 0) { foreach (var _pic in photos) { var pic = _pic as Dictionary; var url = pic["url"].ToString();//图片 pj.pics.Add("http:" + url); } } var content = item["content"].ToString();//初评语 if (content != "此用户没有填写评价。") pj.rateContent = content; var appendList = item["appendList"] as ArrayList;//追评数量 if (appendList != null && appendList.Count != 0) { foreach (var _appendItem in appendList)//追评部分 { var appendItem = _appendItem as Dictionary; var appendPhotos = appendItem["photos"] as ArrayList; if (appendPhotos != null && appendPhotos.Count != 0) { foreach (var _appendPic in appendPhotos) { var appendPic = _appendPic as Dictionary; var appendUrl = appendPic["url"].ToString();//追加图片 pj.pics.Add("http:" + appendUrl); } } var appendContent = appendItem["content"].ToString();//追评语 if (content != "此用户没有填写评价。") pj.rateContent += appendContent; } } if (!string.IsNullOrEmpty(pj.rateContent)) commentList.Add(pj); } } #endregion } catch { } }); } tasks.Start(10, null); return commentList; } catch (Exception ex) { throw ex; } } /// /// 将图片集合转换成Gif图片 /// /// 图片集合 /// 最后一针图片(底图) /// /// 图片之间的间隔时间 /// 是否重复 public void FindGifsBySrcPic(List pics, string secondImage, string path, string itemId, int time = 0, bool repeat = false) { try { if (pics != null && pics.Count != 0) //判断是否图片集合为空 { //if (Directory.Exists(path)) //检测是否存在日期部分的目录 //{ // if (Directory.Exists($"{path}\\{itemId}")) //检测当天解析的宝贝一样时,删除之前解析的所有内容 // Tools.DelectDir(path); //} //else // throw new Exception("解析以后保存路径不存在,请先设置保存路径"); TaskTool tasks = new TaskTool(); //定义线程池 foreach (var pic in pics) //循环要遍历的图片 { tasks.AddTask(delegate () //添加线程任务 { try { var secondImg = Tools.ReadImageFile(secondImage); //获取优惠券bitmap var bitmap = Tools.ZoomPicture(Image.FromFile(pic), secondImg.Width, secondImg.Height);//评价图压缩成和优惠券图大小一致 Graphics g = null; if (File.Exists(TbTools.BUTTONICO)) //是否有按钮图标 { g = Graphics.FromImage(bitmap); //创建以底图为基础的画板 var bitmapLogo = Tools.ReadImageFile(TbTools.BUTTONICO); //按钮图片bitmap int size = 200; //按钮大小 float rate = 2.00f; //比例 bitmapLogo = new Bitmap(bitmapLogo, new Size(size, size)); //固定按钮的大小 var point = new PointF(secondImg.Width / rate - size / rate, secondImg.Height / rate - size / rate); //按钮的坐标 g.DrawImage(bitmapLogo, point); //将按钮画在底图中 } //000000000000 var saveImgPath = TbTools.RandomFile(); //带随机名字的缓存地址(临时图片) bitmap.Save(saveImgPath); //将评价图保存只缓存 if (g != null) //如果增加了按钮,则将画板释放 g.Dispose(); bitmap.Dispose(); //释放 if (Class1.Config.BondCommentPic == Api.Framework.Enums.SwitchType.开启) { var gifFile = Tools.PngsToGif(new string[] { saveImgPath, secondImage }, Util.MapFile(Guid.NewGuid().ToString() + ".png", path), time, repeat); //将处理好的图片保存在宝贝路径中 if (!string.IsNullOrEmpty(gifFile)) { if (File.Exists(saveImgPath)) try { File.Delete(saveImgPath); //删除临时图片 } catch (Exception ex) { } } } else { } } catch (Exception ex) { } }); } tasks.Start(8, null); //执行线程池 } } catch (Exception ex) { throw ex; } } } }