Данная статья предназначена для C# кодеров, но если вы с легкостью можете транслировать код с одного языка на другой, то добро пожаловать. JavaScript - Неотъемлемая часть всех сайтов. Многие сайты использует защиту именно с помощью JavaScript. Примеры, которые вы могли бы или можете встретить: Please enable JavaScript - В данном случае наши библиотеки(HttpWebRequest,XNet,Leaf.XNet) исполняющие запросы к сайту не могут обрабатывать JavaScript - это проблема, но она исправляема ручной обработкой. На этом проблемы не ограничиваются при Incapsula, CloudFlare на сайте вам тоже прийдется работать с JavaScript перечислять можно много различных методов защиты. Для примера я возьму один из сайтов: https://luxsocks.ru/login(Не реклама) Использовать буду последнюю версию Node.JS. В качестве библиотеки для отправки запросов используется: XNet(Обычный) Конфигурация решения проекта: Debug Тип проекта: CMD(Командная строка) Использованный браузер: Yandex Browser(Использовать можно будет любой, но для таких целей лучше подойдет Firefox for Developers) Работать с Node.JS будем через командную строку Windows. Ниже идет полное пояснение и код, если вы не знаете, как работать с XNet и прочими библиотеками или почему у вас появляются ошибки в коде и далеки от этого не пробуйте, пока не изучите данные вещи и не набьете руку. Для начала нужно проанализировать сайт на имеющиеся проблемы следующим образом: отправим запрос на страницу входа в личный кабинет сайта using (HttpRequest Request = new HttpRequest()) { Request.Cookies = new CookieDictionary(); Request.KeepAlive = true; Request.EnableEncodingContent = true; Request.AllowAutoRedirect = false; Request.AddHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3"); Request.AddHeader("Accept-Language", "ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7"); Request.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36"; string Answer = Request.Get("https://luxsocks.ru/login").ToString(); Console.WriteLine(Answer); Console.ReadKey(); } Code using (HttpRequest Request = new HttpRequest()) { Request.Cookies = new CookieDictionary(); Request.KeepAlive = true; Request.EnableEncodingContent = true; Request.AllowAutoRedirect = false; Request.AddHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3"); Request.AddHeader("Accept-Language", "ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7"); Request.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36"; string Answer = Request.Get("https://luxsocks.ru/login").ToString(); Console.WriteLine(Answer); Console.ReadKey(); } После запуска в окне нашего приложения выведется полученный ответ от сервера сайта. Итак, Вы нашли первую проблему, а именно сайт просит нас включить JavaScript - это обуславливается тем, что в нашем случае XNet не может обработать код. Итак, почему же нас не пускает на сайт? Если нас не пускают на сайт, значит сервер сайта каким-то магическим образом проверяет нахождение какого-то значения либо в Cookies, либо в Headers. Чтобы это понять нужно зайти в любой браузер и открыть панель для разработчиков или же инспектор(F12), после открытия перейти на вкладку Network и переместиться на наш сайт: https://luxsocks.ru/login. Сделав действия выше вы увидите такую картину: Анализируем увиденную информацию 1-й запрос(Выделен на изоображение): в Headers нет ничего особого, но сразу же заметен ключ TCKE в Cookies и значением c3119b97d5fcbfd073fad1dd38cb232f, уже интересней. 2-й запрос: выполнение JS скрипта под именем aes.min.js 3-й запрос: https://luxsocks.ru/login?protection=1 со статус кодом 302 Moved Temporarily А теперь давайте внимательно приглядимся в куки и вспомним куки от первого запроса: Сейчас: TCKE=1af926eb3abff98fc9afd4b4e4ba2178 Было: TCKE=c3119b97d5fcbfd073fad1dd38cb232f Если хорошенько подумать головой, то можно увидеть изменения и понять, что JS скрипт под именем aes.min.js изменил нам значение в куках под ключом: TCKE. Пока это нам не дает полного решения, но мы уже смогли найти половину решение и исключить поиск причины возникновения события "Please Enable JavaScript". Дальше снова запускаем сделанное приложение и внимательно присматриваясь в полученный ответ одновременно ищем ключ TCKE. Итак мы удостоверились, что там присутствует JS код, который выставляет куку TCKE. Создаем рядом с приложением файл: index.js Копируем из ответ начиная от тэга: <script> и заканчивая </script> И вставляем скопированное в наш файл index.js Дальше прийдется применить небольшие знания JavaScript, а именно обычные основы, если вы знаете C#, то проблем с этим не составит синтаксис похож. Получится в одну строку, если вы делаете редактирование через обычный текстовик, прийдется отрихтовать тем самым приведя код в читаемый вид. После рихтования получится следующие: Выглядит все понятно, но работать это в Node.JS не будет, исправляем. Получаем следующие: Если такое запустить, то все еще работать не будет, скрипт будет жаловаться на slowAES. Вот тут нам и пригодится тот самый скрипт aes.min.js, после которого у нас и появлялось новое значение в куке TCKE. Узнаем ссылку на него и переходим по ней: https://luxsocks.ru/aes.min.js Просто копируем весь код и вставляем в самое начало в наш файл index.js На этом скрипт закончен. Переходим к стадии взаимодействия C# с Node.JS. Если у вас не установлен Node.JS, то его нужно будет установить. по следующей ссылке: https://www.sendspace.com/file/7nk8pn. После как скачаете архив, разархивируйте в папке с вашим приложением. Изменяем код нашего приложения на следующий и запускаем: using (HttpRequest Request = new HttpRequest()) { Request.Cookies = new CookieDictionary(); Request.KeepAlive = true; Request.EnableEncodingContent = true; Request.AllowAutoRedirect = false; Request.AddHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3"); Request.AddHeader("Accept-Language", "ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7"); Request.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36"; string Answer = Request.Get("https://luxsocks.ru/login").ToString(); string A = IFunctions.GetValue(Answer, "a=toNumbers(\"", "\"", 0); string B = IFunctions.GetValue(Answer, "b=toNumbers(\"", "\"", 0); string C = IFunctions.GetValue(Answer, "c=toNumbers(\"", "\"", 0); Process process = new Process(); process.StartInfo.FileName = "cmd.exe"; process.StartInfo.Arguments = "/c " + Environment.CurrentDirectory + "\\nodejs\\node.exe " + Environment.CurrentDirectory + "\\index.js " + A + " " + B + " " + C; process.StartInfo.UseShellExecute = false; process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden; process.StartInfo.CreateNoWindow = false; process.StartInfo.RedirectStandardOutput = true; process.Start(); process.WaitForExit(); string AllOut = process.StandardOutput.ReadToEnd(); string Key = AllOut.Split('=')[0].Trim(); string Value = AllOut.Split('=')[1].Trim(); Request.Cookies.Add(Key, Value); Request.AddHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3"); Request.AddHeader("Accept-Language", "ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7"); Request.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36"; Answer = Request.Get("https://luxsocks.ru/login").ToString(); Console.WriteLine(Answer); Console.ReadKey(); } Code using (HttpRequest Request = new HttpRequest()) { Request.Cookies = new CookieDictionary(); Request.KeepAlive = true; Request.EnableEncodingContent = true; Request.AllowAutoRedirect = false; Request.AddHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3"); Request.AddHeader("Accept-Language", "ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7"); Request.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36"; string Answer = Request.Get("https://luxsocks.ru/login").ToString(); string A = IFunctions.GetValue(Answer, "a=toNumbers(\"", "\"", 0); string B = IFunctions.GetValue(Answer, "b=toNumbers(\"", "\"", 0); string C = IFunctions.GetValue(Answer, "c=toNumbers(\"", "\"", 0); Process process = new Process(); process.StartInfo.FileName = "cmd.exe"; process.StartInfo.Arguments = "/c " + Environment.CurrentDirectory + "\\nodejs\\node.exe " + Environment.CurrentDirectory + "\\index.js " + A + " " + B + " " + C; process.StartInfo.UseShellExecute = false; process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden; process.StartInfo.CreateNoWindow = false; process.StartInfo.RedirectStandardOutput = true; process.Start(); process.WaitForExit(); string AllOut = process.StandardOutput.ReadToEnd(); string Key = AllOut.Split('=')[0].Trim(); string Value = AllOut.Split('=')[1].Trim(); Request.Cookies.Add(Key, Value); Request.AddHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3"); Request.AddHeader("Accept-Language", "ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7"); Request.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36"; Answer = Request.Get("https://luxsocks.ru/login").ToString(); Console.WriteLine(Answer); Console.ReadKey(); } Дальше запускаем приложение и видим результат проделанной работы: Сайт выдал нам полный доступ к HTML коду страницы входа в личный кабинет: https://luxsocks.ru/login Статья написана для получения знаний в гибридном использование нескольких языков с помощью кастылей. Если, что-то разжевал не понятно, задавайте вопросы.
Saind, Это довольно сложное решение, но по скорости лучше чем любой движок для интерпретации JS в C#. Одного разъяснения я думаю тут будет мало для начинающих, но опытные поймут смысл и разберутся.
Есть библиотека Jurassic для C#, она выполняет js спокойно, использовал ее, когда писал обход CloudFlare