private static AllStockRoot CreateAllStock(FullCatalog fullCatalog, ShopCatalogRoot jsonCatalog) { AllStockRoot allstock = new AllStockRoot(); foreach (var jsonMarket in jsonCatalog.markets) { RootParsingObject market = Parsing.Model.RootParsingObject.ReadJsonMarketFromFtp(jsonMarket); if (market != null) { AddMarketToAllStock(market, fullCatalog, allstock, jsonMarket); } } allstock.update_time = DateTime.Now; return(allstock); }
private static AllStockOffer GetFirstActiveOffer(AllStockSize asSize, ShopCatalogRoot shopCatalog) { var bonanzaShops = shopCatalog.markets.FindAll(x => x.active_marketplace_list.Find(y => y == "bonanza") != null); //if (asSize.offers[0].currency != "RUB") //{ // return asSize.offers[0]; //} foreach (var offer in asSize.offers) { //if (offer.currency != "RUB") if (bonanzaShops.Find(x => x.name == offer.stock_name) != null) { return(offer); } } return(null); }
private static BonanzaRoot CreateBonanzaRecords(AllStockRoot allstock, FullCatalogRoot fullCatalog) { ShopCatalogRoot shopCatalog = ShopCatalogController.LoadShopCatalogFromFtp(); BonanzaRoot bonanza = new BonanzaRoot(); foreach (var asSneaker in allstock.sneakers) { foreach (var asSize in asSneaker.sizes) { Model.BonanzaModel.BonanzaRecord bRecord = GetBonanzaRecord(asSize, asSneaker, fullCatalog, shopCatalog); if (bRecord != null) { bonanza.Records.Add(bRecord); } } } return(bonanza); }
public static void ValidateAllShops() { //загружаем каталог магазинов var shopCatalog = ShopCatalogRoot.ReadFromFtp(); foreach (var shop in shopCatalog.markets) { RootParsingObject market = SneakerIcon.Classes.Parsing.Model.RootParsingObject.ReadJsonMarketFromFtp(shop); if (market != null) { var shopValidator = new ShopValidator(); shopValidator.ValidateShop(market, shopCatalog); } else { bool test = true; } } }
private void ValidateShop(RootParsingObject shopParser, ShopCatalogRoot shopCatalog, string folder = _folder) { var validatedShop = new RootParsingObject(); validatedShop.market_info = shopParser.market_info; //string br = "\n"; log = DateTime.Now.ToString() + br; foreach (var listing in shopParser.listings) { string listingLog = String.Empty; var ValidListing = ValidateListing(listing); if (ValidListing != null) { validatedShop.listings.Add(ValidListing); } } validatedShop.SaveLocalFile(folder); SaveLogShopValidate(this.log, validatedShop.market_info.name); //return validatedShop; }
public static AllStockRoot Run() { var jsonCatalog = ShopCatalogRoot.ReadFromFtp(); var fullCatalog = new FullCatalog(); AllStockRoot allstock = CreateAllStock(fullCatalog, jsonCatalog); //когда оллсток создан, нужно его прогнать и отсортировать все офферы, чтобы первым был с самой низкой ценой SortOffers(allstock); Program.Logger.Info("Артикулов в фулкаталог: " + fullCatalog.sneakers.Count); Program.Logger.Info("Артикулов в оллсток: " + allstock.sneakers.Count); Program.Logger.Info("Размеров в оллсток: " + allstock.GetCountSizes()); Program.Logger.Info("Офферов в оллсток: " + allstock.GetCountOffers()); //затем нужно прогнать весь оллсток и, там где нет юпс, добавить их из upcdb var folder = Config.GetConfig().DirectoryPathParsing + @"allstock\"; SaveJson(allstock, "allstock.json", folder); return(allstock); }
public ShopValidatorAllBrands() { ShopCatalog = ShopCatalogRoot.ReadFromFtp(); SizeChart = new SizeChartAllBrands(); SizeChart.LoadSizeChartFromFtp(); }
private static Model.BonanzaModel.BonanzaRecord GetBonanzaRecord(AllStockSize asSize, AllStockSneaker asSneaker, FullCatalogRoot fullCatalog, ShopCatalogRoot shopCatalog) { var fcSneaker = fullCatalog.records.Find(x => x.sku == asSneaker.sku); if (fcSneaker == null) { _logger.Warn("Артикул не найден в фулкаталоге. sku:" + asSneaker.sku); return(null); } var bRecord = new Model.BonanzaModel.BonanzaRecord(); //standart data bRecord.quantity = 5; bRecord.condition = "New with box"; bRecord.force_update = "true"; bRecord.brand = fcSneaker.brand; //shipping bRecord.shipping_price = 29; bRecord.shipping_type = "flat"; bRecord.shipping_carrier = "usps"; bRecord.shipping_service = "EconomyShipping"; bRecord.shipping_package = "normal"; //bRecord.worldwide_shipping_type = "flat"; //bRecord.worldwide_shipping_price = 29; bRecord.id = asSize.sku2; bRecord.description = GetBonanzaRecordDescription(asSize, asSneaker, fullCatalog); if (bRecord.description == null) { _logger.Warn("Пустое описание. sku2:" + bRecord.id); return(null); } bRecord.category = GetBonanzaCategory(asSneaker.category, fcSneaker.sex); bRecord.width = GetBonanzaWidth(asSneaker.category); bRecord.title = GetTitle(asSneaker.brand, asSize.us, asSneaker.sku, asSneaker.title); //price var offer = GetFirstActiveOffer(asSize, shopCatalog); //var offer = GetNonRussianOffer(asSize); //отфильтруем русские магазы if (offer == null) { return(null); } bRecord.price = GetPrice(offer); //double priceWithMargin = offer.price_usd_with_delivery_to_usa_and_minus_vat + MARGIN_USD; //double priceWithFeeMinusBonanzaDelivery = (priceWithMargin * 1.18) - 29; //priceWithFeeMinusBonanzaDelivery = Math.Round(priceWithFeeMinusBonanzaDelivery, 2); //bRecord.price = priceWithFeeMinusBonanzaDelivery.ToString("F", System.Globalization.CultureInfo.CreateSpecificCulture("en-US")); //images if (fcSneaker.images.Count == 0) { _logger.Warn("Нет изображений. sku2:" + bRecord.id); return(null); } bRecord.image1 = fcSneaker.images[0]; if (fcSneaker.images.Count > 1) { bRecord.image2 = fcSneaker.images[1]; } if (fcSneaker.images.Count > 2) { bRecord.image3 = fcSneaker.images[2]; } if (fcSneaker.images.Count > 3) { bRecord.image4 = fcSneaker.images[3]; } bRecord.size = asSize.us; bRecord.traits = "[[US Size:" + asSize.us + "]] "; bRecord.upc = asSize.upc; bRecord.MPN = fcSneaker.sku; //это вроде не работает bRecord.traits += "[[MPN:" + fcSneaker.sku + "]] "; return(bRecord); }
private static List <string> ChangeImageLinksFromShopToImagesFromOurServer(List <string> images, RootParsingObject shop, ShopCatalogRoot shopCatalog, Listing shopRecord) { var imagesFromOurServer = new List <string>(); string host = "http://img.sneaker-icon.ru"; int shopNumber = shopCatalog.markets.Find(x => x.name == shop.market_info.name).number; for (int i = 1; i < images.Count + 1; i++) { string url = host + "/shops/" + shopNumber + "/images/" + shopRecord.sku + "-" + i + ".jpg"; if (NetworkUtils.UrlExists(url)) { imagesFromOurServer.Add(url); } } //ver2.0 var imagesFromOurServer2 = new List <string>(); var ftphost = "ftp://" + Config.GetConfig().FtpHostContabo; var user = Config.GetConfig().FtpUserContabo; var pass = Config.GetConfig().FtpPassContabo; var folder = "shops/" + shopNumber + "/images"; var folderImages = Helper.GetFileListFromDirectory(folder, ftphost, user, pass).ToList(); var skuImages = folderImages.FindAll(x => x.Contains(shopRecord.sku)); foreach (var image in skuImages) { var imageUrl = host + "/" + folder + "/" + image; imagesFromOurServer2.Add(imageUrl); } if (imagesFromOurServer.Count != imagesFromOurServer2.Count) { bool test = true; } return(imagesFromOurServer); }
private static void UpdateFromOneMarket(Model.FullCatalog.FullCatalogRoot fullCatalogJson, Parsing.Model.RootParsingObject jsonMarket, ShopCatalogRoot shopCatalog, out int addedCount) { addedCount = 0; foreach (var listing in jsonMarket.listings) { var fcSneaker = fullCatalogJson.records.Find(x => x.sku.ToUpper() == listing.sku.ToUpper()); if (fcSneaker == null) { //если фулкаталогсникер нул, значит этого кроссовка еще нет в фулкаталоге и надо его добавить var fcRecord = CreateFullCatalogRecordFromListing(listing, jsonMarket, shopCatalog); if (fcRecord != null) { fullCatalogJson.records.Add(fcRecord); addedCount++; } else { //значит ошибка какая-то bool test = true; } } else { //если кросс уже существуюет то смотрим что есть в листинге, если есть данные для обновления то обновляем их в кроссовке. //проверить, сохранятся ли данные обновления в фулкаталоге, потому что передаю просто листинг а не весь каталог UpdateSneaker(fcSneaker, listing); } } }
/// <summary> /// метод ищет изображения для fullCatalogRecord во всех магазинах /// </summary> /// <param name="fcRecord">FullCatalogRecord</param> /// <param name="shops">Магазины с листингами в json</param> /// <param name="shopCatalog"></param> /// <returns>возвращает список ссылок на изображения с нашего сервера</returns> private static List <string> GetImages(FullCatalogRecord fcRecord, List <RootParsingObject> shops, ShopCatalogRoot shopCatalog) { /* Как лучше всего сделать изображения? Какие варианты? * - пройтись по всем магазинам, найти магазин где фоток больше всего и взять оттуда * - пройтись по всем магазинам и взять все фотки * - пройтись по магазам и взять там где 4 фотки в первую очередь (хорошо для бонанзы) * - сделать список магазинов по приоритетам откуда брать фотки (в первую очередь оттуда где белый фон) * - добавлять стайловые фотки в конце * - оттуда где первый кроссовок влево смотрит * - отсортировать магазы по кол-ву артикулов. брать в первую очередь оттуда, где артикулов больше (чтобы больше кроссовок были в едином стиле) * бля, вариантов куча, у каждого свои преимущества... что же делать как же быть... * - точно нужно отсеивать магазины с водяными знаками. сто пудов. например оверкилл * - можно в конец добавлять стайловые фотки если их больше 4 (тогда на бонанзу только норм фотки, а на сайт sneaker-icon.ru только качественные фотки * - можно еще правило что с русских сайтов берем фотки в последнюю очередь */ var imagesFromOurServer = new List <string>(); foreach (var shop in shops) { var shopRecord = shop.listings.Find(x => x.sku == fcRecord.sku); if (shopRecord != null) { if (shopRecord.images.Count > 0) { //меняем ссылки с сайта на ссылки с нашего сервера (если они там есть), если нет ищем дальше imagesFromOurServer = ChangeImageLinksFromShopToImagesFromOurServer(shopRecord.images, shop, shopCatalog, shopRecord); if (imagesFromOurServer.Count == shopRecord.images.Count) { return(imagesFromOurServer); } } } } return(imagesFromOurServer); }
/// <summary> /// метод обновляет принудительно все фотки в фулкаталоге на фотки из магазинов. Эти фотки берутся с нашего сервака для фоток /// метод проходит по всем магазинам и ищет там фотки для артикула, если они есть то загружает их. /// магазины отсортированы в порядке приоритета фотографи. /// если в магазинах нет фоток, то фотки берутся из папки для фоток, загруженных вручную /// </summary> public static void UpdateFullCatalogImages() { /* * Алгоритм обновления изображений: * берем фулкаталог * берем список магазинов * берем только магазины без водяных знаков * желательно чтобы кроссовки были на белом фоне (или на сером, но не стайловые), * стайловые можно в конце добавить. потом опять пройтись по всем магазам и в конец добавить стайловых фоток. * чтобы у кросса например было 4 обычных фотки и потом стайловые дальше шли * также можно сделать приоритет по направлению первого кроссовка * например чтобы в первую очередь брать фотки кросс у которых влево смотрит) * Если нигде кросс не найден, то искать фотки в папке images * туда типа вручную фотки загружаем, например для кроссовок из дисконта */ var fullCatalog = LoadFullCatalogFromFtp(); var shopCatalog = ShopCatalogRoot.ReadFromFtp(); var shops = new List <RootParsingObject>(); var startTime = DateTime.Now; //очищаем левые фотки foreach (var record in fullCatalog.records) { if (record.images.Count == 1 && string.IsNullOrWhiteSpace(record.images[0])) { record.images = new List <string>(); } } Program.Logger.Info("Старт. Артикулов без фотографий: " + fullCatalog.records.FindAll(x => x.images.Count == 0).Count); //подгружаем json всех магазинов foreach (var market in shopCatalog.markets) { var shop = RootParsingObject.ReadJsonMarketFromFtp(market); if (shop != null) { shops.Add(shop); } } //отсортировали список магазинов по убыванию количества листингов shops.Sort(delegate(RootParsingObject shop1, RootParsingObject shop2) { return(shop2.listings.Count.CompareTo(shop1.listings.Count)); }); //делаем первый эшелон магазинов с самыми классными фотками var titolo = shops.Find(x => x.market_info.name == "titolo.ch"); var chmielna = shops.Find(x => x.market_info.name == "chmielna20.pl"); var asfaltgold = shops.Find(x => x.market_info.name == "asphaltgold.de"); var hhv = shops.Find(x => x.market_info.name == "hhv.de"); var streetBeat = shops.Find(x => x.market_info.name == "street-beat.ru"); var firstEshelon = new List <RootParsingObject>() { titolo, chmielna, asfaltgold, hhv, streetBeat }; //очищаем все артикулы от фоток //foreach (var fcRecord in fullCatalog.records) //{ // fcRecord.images = new List<string>(); //} //Program.logger.Info("Очистили от фоток. Артикулов без фотографий: " + fullCatalog.records.FindAll(x => x.images.Count == 0).Count); /*Теперь делаем самое главное: * проходимся по всему списку артикулов * каждый артикул проверяем на наличие в магазине * если он в магазине есть, смотрим, есть ли для него фотки * если есть то заполняем */ //первый проход делаем по первому эшелону магазинов int i = 0; int addedPhotos = 0; int updatedPhotos = 0; int status1 = 1; int status2 = 1; Program.Logger.Info("Start FirstEshelon. Всего артикулов:" + fullCatalog.records.Count + " Артикулов без фотографий: " + fullCatalog.records.FindAll(x => x.images.Count == 0).Count); foreach (var fcRecord in fullCatalog.records) { if (fcRecord.sku == "724821-100") { bool test = true; } //пропускаем артикул, если для него уже были взяты фотки с одного из сайтов эшелонов List <string> images = new List <string>(); if (fcRecord.images == null) { images = GetImages(fcRecord, firstEshelon, shopCatalog); } else if (fcRecord.images.Count == 0) { images = GetImages(fcRecord, firstEshelon, shopCatalog); } else if (!fcRecord.images[0].Contains("img.sneaker-icon.ru")) { images = GetImages(fcRecord, firstEshelon, shopCatalog); } else { //если уже с нашего сервака фотка, то проверяем, с сайта эшелона или нет var image = fcRecord.images[0]; bool isEshelonPhotos = false; foreach (var shop in firstEshelon) { int shopNumber = shopCatalog.markets.Find(x => x.name == shop.market_info.name).number; if (image.Contains("/shops/" + shopNumber + "/images/")) { isEshelonPhotos = true; break; } } if (!isEshelonPhotos) { images = GetImages(fcRecord, firstEshelon, shopCatalog); } } if (images.Count > 0) { fcRecord.images = images; if (fcRecord.images == null) { addedPhotos++; } else if (fcRecord.images.Count == 0) { addedPhotos++; } else { updatedPhotos++; } } i++; if (i > 100 * status1) { status1++; } if (status1 > status2) { var time = DateTime.Now - startTime; Program.Logger.Debug("Пройдено:" + i + " Добавлено:" + addedPhotos + " Обновлено:" + updatedPhotos + " time:" + time.Minutes); status2 = status1; } } Program.Logger.Info("Finish FirstEshelon. Всего артикулов:" + fullCatalog.records.Count + " Артикулов без фотографий: " + fullCatalog.records.FindAll(x => x.images.Count == 0).Count); Program.Logger.Info("Добавлено артикулов:" + addedPhotos + " Обновлено артикулов:" + updatedPhotos); //теперь проходимся по всем магазинам (можно конечно первый эшелон удалить, но чет лень, всё равно фотки с изображениями пропускаем) Program.Logger.Info("Start AllShops. Всего артикулов:" + fullCatalog.records.Count + " Артикулов без фотографий: " + fullCatalog.records.FindAll(x => x.images.Count == 0).Count); i = 0; status1 = 1; status2 = 1; foreach (var fcRecord in fullCatalog.records) { //пропускаем фотки у которых в имени файла уже содержится img.sneaker-icon.ru, т.е. значит что они уже были добавлены из первого эшелона или про прошлом проходе UpdateFullCatalogImages. по сути нам нужно взять только те артикулы, у которых нет фоток или у которых фотки с сайта а не с нашего сервака List <string> images = new List <string>(); if (fcRecord.images == null) { images = GetImages(fcRecord, shops, shopCatalog); } else if (fcRecord.images.Count == 0) { images = GetImages(fcRecord, shops, shopCatalog); } else if (!fcRecord.images[0].Contains("img.sneaker-icon.ru/shops/")) { images = GetImages(fcRecord, shops, shopCatalog); } if (images.Count > 0) { fcRecord.images = images; if (fcRecord.images == null) { addedPhotos++; } else if (fcRecord.images.Count == 0) { addedPhotos++; } else { updatedPhotos++; } } i++; if (i > 100 * status1) { status1++; } if (status1 > status2) { var time = DateTime.Now - startTime; Program.Logger.Debug("Пройдено:" + i + " Добавлено:" + addedPhotos + " Обновлено:" + updatedPhotos + " time:" + time.Minutes); status2 = status1; } } Program.Logger.Info("Finish AllShops. Всего артикулов:" + fullCatalog.records.Count + " Артикулов без фотографий: " + fullCatalog.records.FindAll(x => x.images.Count == 0).Count); Program.Logger.Info("Добавлено артикулов:" + addedPhotos + " Обновлено артикулов:" + updatedPhotos); SaveFullCatalogToFtp(fullCatalog); }
private static FullCatalogRecord CreateFullCatalogRecordFromListing(Listing listing, RootParsingObject jsonMarket, ShopCatalogRoot shopCatalog) { //если нет категории то посмотреть есть ли размеры разных сеток, если есть, то определить категорию по разным размерам. FullCatalogRecord fcRecord = new FullCatalogRecord(); //brand if (Validator.ValidateBrand(listing.brand)) { fcRecord.brand = listing.brand; } else { Program.Logger.Warn("wrong brand. sku: " + listing.sku + " market: " + jsonMarket.market_info.name); return(null); } //sku var sku = listing.sku.ToUpper(); //Aa1234-001 to AA1234-001 nike sku if (Validator.ValidateSku(sku, listing.brand)) { fcRecord.sku = sku; } else { Program.Logger.Warn("wrong sku: " + listing.sku + " market: " + jsonMarket.market_info.name); return(null); } //category if (String.IsNullOrWhiteSpace(listing.category)) { //пытаемся определить категорию по размерным сеткам listing.GetCategory(); } if (!String.IsNullOrWhiteSpace(listing.category)) { if (Validator.ValidateCategory(listing.category)) { fcRecord.category = listing.category; fcRecord.sex = Helper.GetEngSexFromEngCategory(fcRecord.category); } else { Program.Logger.Warn("FullCatalog2.CreateFullCatalogRecordFromListing. Invalid listing.category:" + listing.category + " shop:" + jsonMarket.market_info.name + " sku:" + listing.sku); } } //добавить валидации на эти позиции fcRecord.title = listing.title; fcRecord.color = listing.colorbrand; fcRecord.collection = listing.collection; fcRecord.link = listing.url; //дописать смену изображений на изображения с сервера //fcRecord.images = listing.images; fcRecord.images = ChangeImageLinksFromShopToImagesFromOurServer(listing.images, jsonMarket, shopCatalog, listing); if (fcRecord.images.Count < listing.images.Count) { fcRecord.images = listing.images; Program.Logger.Warn("Wrong our Server Images. shop:" + jsonMarket.market_info.name + " sku:" + listing.sku); } else { bool test = true; } fcRecord.add_time = DateTime.Now; return(fcRecord); }
public DbController() { log = String.Empty; ShopCatalog = ShopCatalogController.LoadShopCatalogFromFtp(); }