using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; using Newtonsoft.Json; using OpenQA.Selenium; using OpenQA.Selenium.Firefox; using OpenQA.Selenium.Support.UI; namespace GtaVUsersInfo.Helpers { public class Car { public string Name { get; set; } public int Price { get; set; } public string Photo { get; set; } public string Manufacturer { get; set; } public string Class { get; set; } public string Model { get; set; } } public class CarParser : IDisposable { private IWebDriver driver; public CarParser() { var chromeOptions = new FirefoxOptions(); chromeOptions.AddArgument("--no-sandbox"); driver = new FirefoxDriver(chromeOptions); } public async Task> ParseCarsFromPages(int maxPages) { var cars = new List(); for (int page = 1; page <= maxPages; page++) { var url = $"https://gtacars.net/?page={page}"; var pageCars = await ParseCarsFromPage(url); cars.AddRange(pageCars); } return cars; } private async Task> ParseCarsFromPage(string url) { var cars = new List(); // Открываем страницу в браузере driver.Navigate().GoToUrl(url); // Ожидание, пока динамические элементы не подгрузятся var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(60)); // Ждём, пока появится хотя бы один элемент с ценой wait.Until(drv => drv.FindElements(By.CssSelector("span.v-popper--has-tooltip")).Any(e => e.Text.Contains("$"))); IJavaScriptExecutor js = (IJavaScriptExecutor)driver; Thread.Sleep(100); js.ExecuteScript("window.scrollTo(0, document.body.scrollHeight / 4);"); Thread.Sleep(100); js.ExecuteScript("window.scrollTo(0, document.body.scrollHeight / 3);"); Thread.Sleep(100); js.ExecuteScript("window.scrollTo(0, document.body.scrollHeight / 2);"); Thread.Sleep(100); js.ExecuteScript("window.scrollTo(0, document.body.scrollHeight);"); Thread.Sleep(500); wait.Until(drv => drv.FindElements(By.CssSelector("img[src*='data:image/gif']")).Count == 0); // После этого можно парсить элементы var carElements = driver.FindElements(By.CssSelector("div.relative.flex.flex-col")); foreach (var carElement in carElements) { var car = new Car(); // Имя автомобиля var nameElement = carElement.FindElement(By.CssSelector("span[title]")); car.Name = nameElement.Text; // Цена автомобиля var priceElement = carElement.FindElement(By.CssSelector("span.v-popper--has-tooltip")); var priceText = priceElement.Text; car.Price = ParsePrice(priceText); // Фото var photoElement = carElement.FindElement(By.CssSelector("img.w-full")); car.Photo = photoElement.GetAttribute("src"); // Производитель var manufacturerElement = carElement.FindElement(By.CssSelector("a[href*='filter_manufacturer']")); car.Manufacturer = manufacturerElement.Text; // Класс автомобиля var classElement = carElement.FindElement(By.CssSelector("a[href*='filter_class']")); car.Class = classElement.Text; // Модель (часть URL) var modelElement = carElement.FindElement(By.CssSelector("a[href]")); car.Model = modelElement.GetAttribute("href").Split('/').Last(); cars.Add(car); } return cars; } private int ParsePrice(string priceText) { if (string.IsNullOrWhiteSpace(priceText)) return 0; priceText = priceText.Replace("$", "").Replace(",", "").Replace(" ", ""); return int.TryParse(priceText, out int price) ? price : 0; } public void SaveToJson(List cars, string filePath) { var json = JsonConvert.SerializeObject(cars, Formatting.Indented); File.WriteAllText(filePath, json); } // Реализация метода Dispose public void Dispose() { if (driver != null) { driver.Quit(); driver.Dispose(); } } } class Program { static async Task Main(string[] args) { using (var parser = new CarParser()) { var cars = await parser.ParseCarsFromPages(25); parser.SaveToJson(cars, "cars.json"); Console.WriteLine("Data saved to cars.json"); } } } }