Example #1
0
        static void Main(string[] args)
        {
            int ImageNo = VehicleDBManager.InsertImageFromFile(@"C:\Users\geoff\Pictures\Da Boys.jpg", "image/jpeg");

            Console.WriteLine($"Inserted Image #{ImageNo}");
            Console.ReadLine();
        }
        private static List <int> GetandStoreVehicleImages(string URL)
        {
            List <int>    ImageNumbers = new List <int>();
            List <string> FileList     = new List <string>();

            RetrieveVehicleDetail(URL);
            HtmlDocument       DetailPage = VehicleDetail;
            HtmlNodeCollection DetailDiv  = DetailPage.DocumentNode.SelectNodes($"//div[@id='photos']/ul/li");

            Console.Write("Downloading pics ");
            foreach (HtmlNode a in DetailDiv)
            {
                if (!a.InnerHtml.Contains("ref"))
                {
                    continue;
                }
                HtmlNode HRef   = a.SelectSingleNode("a");
                string   PicUrl = "http:" + HRef.GetAttributeValue("href", "none");

                if (PicUrl != "none")
                {
                    Uri    picURI      = new Uri(PicUrl);
                    string picFileName = picURI.Segments[picURI.Segments.Count() - 1].ToString();
                    FileList.Add(picFileName);
                    using (var client = new WebClient())
                    {
                        client.DownloadFile(PicUrl, $@"c:\temp\{picFileName}");
                        int ImageNo = VehicleDBManager.InsertImageFromFile($@"c:\temp\{picFileName}", "image/jpg");
                        ImageNumbers.Add(ImageNo);
                        Console.Write(".");
                    }
                }
            }

            foreach (string filename in FileList)
            {
                (new FileInfo(filename)).Delete();
            }

            return(ImageNumbers);
        }
        private static void ProcessVehicleListOnPage(HtmlNodeCollection vehicleListItems, string DealerName, ref List <VEHICLE> PreviouslyFoundVehicles, string Market)
        {
            if (vehicleListItems == null)
            {
                return;
            }

            char[] killcomma = { ',' };
            foreach (HtmlNode vehicle in vehicleListItems)
            {
                HtmlNode VehicleNode      = vehicle.SelectSingleNode("div[@data-vin]");
                string   VehicleVIN       = VehicleNode.Attributes["data-vin"].Value.ToString();
                string   VehicleBodyStyle = VehicleNode.Attributes["data-bodyStyle"].Value.ToString();
                string   VehicleMake      = VehicleNode.Attributes["data-make"].Value.ToString();
                string   VehicleYear      = VehicleNode.Attributes["data-year"].Value.ToString();
                string   VehicleModel     = VehicleNode.Attributes["data-model"].Value.ToString();
                string   VehicleTrim      = VehicleNode.Attributes["data-trim"].Value.ToString();
                string   VehicleExtColor  = VehicleNode.Attributes["data-exteriorcolor"].Value.ToString();

                VEHICLE ExistingVehicle = VehicleDBManager.GetVehicleByVIN(VehicleVIN);
                List <VehiclePriceHistory> PriceHistory = null;
                bool Existing = false;

                // Check this vehicle against the list of previously found vehicles.
                // If it is found, remove it from the list, which ultimately removes it
                // from the "sold vehicle" list.
                if (ExistingVehicle != null && PreviouslyFoundVehicles != null)
                {
                    Existing     = true;
                    PriceHistory = RetrieveHistory(ExistingVehicle.VEHICLE_HISTORY);
                    var FoundThisOne = (from v in PreviouslyFoundVehicles
                                        where v.VIN == VehicleVIN
                                        select v).SingleOrDefault <VEHICLE>();
                    if (!ReferenceEquals(null, FoundThisOne))
                    {
                        PreviouslyFoundVehicles.Remove((VEHICLE)FoundThisOne);
                    }
                }
                else
                {
                    PriceHistory = new List <VehiclePriceHistory>();
                }

                HtmlNodeCollection VehicleNodeChildren = vehicle.ChildNodes;

                HtmlNode LinkNode    = VehicleNodeChildren[1].SelectSingleNode("div/div[@class='media']/a[@href]");
                string   VehicleLink = BaseURI + LinkNode.Attributes["href"].Value.ToString();

                HtmlNode           DescriptionNode  = VehicleNodeChildren[1].SelectSingleNode("div/div[@class='description']");
                HtmlNodeCollection DescriptionLists = VehicleNodeChildren[1].SelectNodes("div/div[@class='description']/dl");

                string VehicleEngine    = string.Empty;
                string VehicleTrans     = string.Empty;
                string IntColor         = string.Empty;
                string Mileage          = string.Empty;
                string StockNumber      = string.Empty;
                string ModelCode        = string.Empty;
                string VehicleDriveType = string.Empty;

                foreach (HtmlNode DList in DescriptionLists)
                {
                    string ItemType = string.Empty;
                    foreach (HtmlNode Item in DList.ChildNodes)
                    {
                        string Data = string.Empty;

                        if (Item.Name == "dt")
                        {
                            ItemType = Item.InnerText;
                            continue;
                        }
                        else if (Item.Name == "dd")
                        {
                            Data = Item.InnerText.Trim(killcomma);
                        }
                        else
                        {
                            continue;
                        }

                        switch (ItemType)
                        {
                        case "Engine:":
                            VehicleEngine = Data;
                            break;

                        case "Transmission:":
                            if (VehicleTrans.Length <= Data.Length)
                            {
                                VehicleTrans = Data;
                            }
                            break;

                        case "Exterior Color:":
                            if (Data != VehicleBodyStyle)
                            {
                                VehicleExtColor = Data;
                            }
                            break;

                        case "Interior Color:":
                            IntColor = Data;
                            break;

                        case "Stock #:":
                            StockNumber = Data;
                            break;

                        case "Mileage:":
                            Mileage = Data.Trim();
                            Mileage = Mileage.Replace(",", "");
                            Mileage = Mileage.Replace("miles", "");
                            if (Mileage.Length == 0 || Mileage == null || Mileage == " ")
                            {
                                Mileage = "0";
                            }
                            break;

                        case "Model Code:":
                            ModelCode = Data;
                            break;

                        case "Drive Line:":
                            VehicleDriveType = Data;
                            break;
                        }

                        ItemType = string.Empty;
                    }
                }

                // Stuff we might have to go to vehicle detail pages to retrieve: Mileage, Drive type, price

                // Mileage not on search page? (Snethkamp)
                if (Mileage == string.Empty || Mileage == "UNKNOWN" || Mileage == "0")
                {
                    Mileage = GetVehicleDetail(VehicleLink, "ddc-span6", "Mileage", "UNKNOWN");
                    Mileage = Mileage.Trim();
                    Mileage = Mileage.Replace(",", "");
                    Mileage = Mileage.Replace("miles", "");
                    Mileage = Mileage.Replace(@"\n", "");
                }

                // Vehicle Drive Type not on search page?
                if (VehicleDriveType == string.Empty || VehicleDriveType == "UNKNOWN")
                {
                    VehicleDriveType = GetVehicleDetail(VehicleLink, "item powertrain", "Drive type", "UNKNOWN");
                }
                if (VehicleDriveType == string.Empty || VehicleDriveType == "UNKNOWN")
                {
                    VehicleDriveType = GetVehicleDetail(VehicleLink, "powertrain", "Drive type", "UNKNOWN");
                }

                // Wheel Size
                string WheelSizeInches = GetVehicleDetail(VehicleLink, "item suspension-handling", "Wheel size", "UNKNOWN");
                if (WheelSizeInches == "UNKNOWN")
                {
                    WheelSizeInches = GetVehicleDetail(VehicleLink, "suspension-handling", "Wheel size", "UNKNOWN");
                }
                if (WheelSizeInches == "UNKNOWN")
                {
                    WheelSizeInches = GetVehicleDetail(VehicleLink, "standard-features", "Wheel Diameter", "UNKNOWN");
                }

                // Vehicle Price
                string   Price     = string.Empty;
                HtmlNode PriceNode = VehicleNodeChildren[1].SelectSingleNode("div/div[@class='pricing-area has-buttons']");
                HtmlNode ValueNode = PriceNode.SelectSingleNode("ul/li/span/span[@class='value']");
                if (ValueNode != null)
                {
                    Price = PriceNode.SelectSingleNode("ul/li/span/span[@class='value']").InnerText;
                    Price = Price.Replace("$", "");
                    Price = Price.Replace(",", "");
                    if (Price.Contains("/mo") || Price.Contains("month"))
                    {
                        Price = "0.00";
                    }
                }
                VehiclePriceHistory vph = new VehiclePriceHistory();
                vph.VIN           = VehicleVIN;
                vph.Date_Recorded = DateTime.Now.ToLocalTime();
                vph.Price         = Price;
                PriceHistory.Add(vph);

                // Carfax
                string   CarfaxURL  = string.Empty;
                HtmlNode CarfaxNode = DescriptionNode.SelectSingleNode("div[@class='calloutDetails']/ul/li[@class='carfax']");
                if (CarfaxNode != null)
                {
                    CarfaxURL = CarfaxNode.SelectSingleNode("a").Attributes["href"].Value.ToString();
                }

                // Images
                // List<int> ImageIds = GetandStoreVehicleImages(VehicleLink);

                //var strImageIdListcsv = string.Join(", ", ImageIds);
                // Console.WriteLine(strImageIdListcsv);

                if (ExistingVehicle != null)
                {
                    ExistingVehicle.VEHICLE_HISTORY   = SaveHistory(PriceHistory);
                    ExistingVehicle.BODY_STYLE        = VehicleBodyStyle;
                    ExistingVehicle.CARFAX_URL        = CarfaxURL;
                    ExistingVehicle.COLOR_EXTERIOR    = VehicleExtColor;
                    ExistingVehicle.COLOR_INTERIOR    = IntColor;
                    ExistingVehicle.CURRENT_PRICE     = Price;
                    ExistingVehicle.DATE_LAST_SEEN    = DateTime.Now;
                    ExistingVehicle.DEALERSHIP_NAME   = DealerName;
                    ExistingVehicle.DEALER_DETAIL_URL = VehicleDetailURL;
                    ExistingVehicle.DRIVE_TRAIN       = VehicleDriveType;
                    ExistingVehicle.ENGINE            = VehicleEngine;
                    ExistingVehicle.MAKE   = VehicleMake;
                    ExistingVehicle.MARKET = Market;
                    //ExistingVehicle.IMAGEIDCSV = strImageIdListcsv;
                    ExistingVehicle.MILEAGE         = Mileage;
                    ExistingVehicle.MODEL           = VehicleModel;
                    ExistingVehicle.MODEL_CODE      = ModelCode;
                    ExistingVehicle.STOCK_NUMBER    = StockNumber;
                    ExistingVehicle.TRANSMISSION    = VehicleTrans;
                    ExistingVehicle.TRIM            = VehicleTrim;
                    ExistingVehicle.VEHICLE_HISTORY = SaveHistory(PriceHistory);
                    ExistingVehicle.VIN             = VehicleVIN;
                    ExistingVehicle.WHEEL_SIZE      = WheelSizeInches;
                    ExistingVehicle.YEAR            = VehicleYear;
                    VehicleDBManager.UpdateVehicleRecord(ExistingVehicle);
                }
                else
                {
                    VEHICLE foundvehicle = new VEHICLE();
                    foundvehicle.BODY_STYLE        = VehicleBodyStyle;
                    foundvehicle.CARFAX_URL        = CarfaxURL;
                    foundvehicle.COLOR_EXTERIOR    = VehicleExtColor;
                    foundvehicle.COLOR_INTERIOR    = IntColor;
                    foundvehicle.CURRENT_PRICE     = Price;
                    foundvehicle.DATE_LAST_SEEN    = DateTime.Now;
                    foundvehicle.DEALERSHIP_NAME   = DealerName;
                    foundvehicle.DEALER_DETAIL_URL = VehicleDetailURL;
                    foundvehicle.DRIVE_TRAIN       = VehicleDriveType;
                    foundvehicle.ENGINE            = VehicleEngine;
                    foundvehicle.MAKE   = VehicleMake;
                    foundvehicle.MARKET = Market;
                    //foundvehicle.IMAGEIDCSV = strImageIdListcsv;
                    foundvehicle.MILEAGE         = Mileage;
                    foundvehicle.MODEL           = VehicleModel;
                    foundvehicle.MODEL_CODE      = ModelCode;
                    foundvehicle.STOCK_NUMBER    = StockNumber;
                    foundvehicle.TRANSMISSION    = VehicleTrans;
                    foundvehicle.TRIM            = VehicleTrim;
                    foundvehicle.VEHICLE_HISTORY = SaveHistory(PriceHistory);
                    foundvehicle.VIN             = VehicleVIN;
                    foundvehicle.WHEEL_SIZE      = WheelSizeInches;
                    foundvehicle.YEAR            = VehicleYear;
                    VehicleDBManager.InsertVehicle(foundvehicle);
                }

                Console.WriteLine($@"
        VIN : {VehicleVIN}  Found Previously? {Existing}
            {VehicleYear} {VehicleMake} {VehicleModel} {VehicleTrim} ({VehicleBodyStyle})
            Drivetrain: Engine: {VehicleEngine} | Transmission: {VehicleTrans} 
                        Drive type: {VehicleDriveType} | Wheel size: {WheelSizeInches}
            Color:      Exterior: {VehicleExtColor} | Interior: {IntColor} 
            Mileage:    {Mileage}
            Price:      {Price}
                        Stock #: {StockNumber} | Model Code: {ModelCode}  
            Direct URL: {VehicleLink}
            Carfax URL: {CarfaxURL}");

                VehicleVIN               = StockNumber = VehicleYear = VehicleMake = VehicleModel = ModelCode =
                    VehicleTrim          = VehicleEngine = VehicleTrans = VehicleDriveType = WheelSizeInches =
                        VehicleBodyStyle = VehicleExtColor = Mileage = IntColor = Price = CarfaxURL = VehicleLink = string.Empty;
            }
        }
        public static void ProcessAllDealers()
        {
            WebClient client = new System.Net.WebClient();
            HtmlWeb   webGet = new HtmlWeb();

            List <DEALERSHIP> dealers = VehicleDBManager.GetDealerships("Dealer.Com");

            if (dealers == null)
            {
                return;
            }

            foreach (DEALERSHIP dealer in dealers)
            {
                string DealerName = dealer.DEALER_NAME;
                string MainUrl    = dealer.DEALER_URL;
                Console.WriteLine($"************\r\n*** Processing Dealer: {DealerName}\r\n************");
                HtmlDocument mainpage       = webGet.Load(MainUrl);
                bool         KeepProcessing = (mainpage != null);
                int          PageCount      = 0;

                BaseURI = new Uri(MainUrl).GetLeftPart(UriPartial.Authority);
                Console.WriteLine($"Base URL for dealership: {BaseURI}");
                List <VEHICLE> PreviouslyFoundAtDealer = VehicleDBManager.GetAllUnsoldVehiclesForDealer(DealerName);

                while (KeepProcessing)
                {
                    Console.WriteLine($"\r\n\r\bRetrieving page #{++PageCount} of vehicles for dealer {DealerName} in the {dealer.MARKET_AREA_NAME} Market Area\r\n");

                    // Note: if the items are "shared", then they are listings from affiliated dealerships.
                    HtmlNodeCollection VehicleListItems = mainpage.DocumentNode.SelectNodes("//li[substring(@class, 1, 14)='item notshared']");
                    ProcessVehicleListOnPage(VehicleListItems, DealerName, ref PreviouslyFoundAtDealer, dealer.MARKET_AREA_NAME);

                    HtmlNode NextLink = mainpage.DocumentNode.SelectSingleNode("//a[@class='ddc-btn ddc-btn-link ddc-btn-xsmall'][@rel='next']");
                    string   Next     = string.Empty;
                    if (NextLink != null)
                    {
                        Next = NextLink.Attributes["href"].Value.ToString();
                        string NextURL = MainUrl + Next;
                        mainpage       = webGet.Load(NextURL);
                        KeepProcessing = (mainpage != null);
                    }
                    else
                    {
                        KeepProcessing = false;
                    }
                }

                if (!KeepProcessing && PreviouslyFoundAtDealer != null)
                {
                    // All the vehicles currently at this dealer have been screen-scraped.
                    // Now go through the complete list of "STILL_FOR_SALE" vehicles from the previous run
                    // and update any that have disappeared from their website as being sold or auctioned.

                    Console.WriteLine($"Found {PreviouslyFoundAtDealer.Count} vehicle(s) removed from dealer inventory since last run.");
                    foreach (VEHICLE SoldOrAuctionedVehicle in PreviouslyFoundAtDealer)
                    {
                        SoldOrAuctionedVehicle.STILL_FOR_SALE = "NO";
                        List <VehiclePriceHistory> PriceHistory = RetrieveHistory(SoldOrAuctionedVehicle.VEHICLE_HISTORY);
                        var MinDate           = (from pricehistories in PriceHistory select pricehistories.Date_Recorded).Min();
                        var MaxDate           = (from pricehistories in PriceHistory select pricehistories.Date_Recorded).Max();
                        var DaysOnMarket      = MaxDate - MinDate;
                        var FinalPriceHistory = (from pricehistories in PriceHistory
                                                 where pricehistories.Date_Recorded == MaxDate
                                                 select pricehistories).SingleOrDefault <VehiclePriceHistory>();
                        FinalPriceHistory.WasFinalPrice        = "YES";
                        SoldOrAuctionedVehicle.VEHICLE_HISTORY = SaveHistory(PriceHistory);
                        Console.WriteLine($@"Updating VIN {SoldOrAuctionedVehicle.VIN} : {SoldOrAuctionedVehicle.YEAR} {SoldOrAuctionedVehicle.MAKE} {SoldOrAuctionedVehicle.MODEL} (Stock number {SoldOrAuctionedVehicle.STOCK_NUMBER}) as sold.  Final price was {FinalPriceHistory.Price}, Mileage was {SoldOrAuctionedVehicle.MILEAGE}, Days on market was {DaysOnMarket.Days}");
                        VehicleDBManager.UpdateVehicleRecord(SoldOrAuctionedVehicle);
                    }
                }
            }
        }