{"id":304122,"date":"2020-05-23T21:00:20","date_gmt":"2020-05-23T21:00:20","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=304122"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=304122","title":{"rendered":"\u0417\u0430\u043f\u0438\u0441\u044c \u0432\u0438\u0434\u0435\u043e UI \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432, \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0449\u0438\u0445 \u0432 headless Chrome"},"content":{"rendered":"\n<div class=\"post__text post__text-html post__text_v1\" id=\"post-content-body\" data-io-article-url=\"https:\/\/habr.com\/ru\/post\/503476\/\">\u0412\u0441\u0435\u043c \u043f\u0440\u0438\u0432\u0435\u0442! <\/p>\n<p>  \u0412 \u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u0445\u043e\u0447\u0435\u0442\u0441\u044f \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u0430\u0442\u044c \u043e \u0442\u043e\u043c, \u043a\u0430\u043a \u0431\u044b\u043b\u0430 \u0440\u0435\u0448\u0435\u043d\u0430 \u0437\u0430\u0434\u0430\u0447\u0430 \u0437\u0430\u043f\u0438\u0441\u0438 \u0432\u0438\u0434\u0435\u043e \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432, \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0449\u0438\u0445 \u0432 <b>headless<\/b> Chrome (\u0441 \u0437\u0430\u043f\u0438\u0441\u044c\u044e \u0432 \u043d\u0435 headless \u0440\u0435\u0436\u0438\u043c\u0435 \u043f\u0440\u043e\u0431\u043b\u0435\u043c \u0431\u044b\u0442\u044c \u043d\u0435 \u0434\u043e\u043b\u0436\u043d\u043e). \u0411\u0443\u0434\u0435\u0442 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u043e \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0440\u0430\u0437\u043d\u044b\u0445 \u043f\u043e\u0434\u0445\u043e\u0434\u043e\u0432, \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u0430\u043d\u043e \u043f\u0440\u043e \u0442\u0440\u0443\u0434\u043d\u043e\u0441\u0442\u0438 \u0438 \u043f\u0443\u0442\u0438 \u0438\u0445 \u0440\u0435\u0448\u0435\u043d\u0438\u044f. <\/p>\n<p>  <b>\u041f\u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u0437\u0430\u0434\u0430\u0447\u0438<\/b><br \/>  1. \u0422\u0435\u0441\u0442\u044b \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u044e\u0442\u0441\u044f \u043f\u043e\u0434 Windows<br \/>  2. \u0422\u0435\u0441\u0442\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442 Selenium Web Driver + Headless Chrome<br \/>  3. \u0422\u0435\u0441\u0442\u044b \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u044e\u0442\u0441\u044f \u0432 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u0442\u043e\u043a\u043e\u0432<\/p>\n<p>  \u0414\u043b\u044f \u0443\u043f\u0430\u0432\u0448\u0438\u0445 \u0442\u0435\u0441\u0442\u043e\u0432 \u043d\u0443\u0436\u043d\u043e \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0432\u0438\u0434\u0435\u043e, \u043f\u0440\u0438 \u044d\u0442\u043e\u043c <br \/>  1. \u0412\u0440\u0435\u043c\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0434\u043e\u043b\u0436\u043d\u043e \u0432\u044b\u0440\u0430\u0441\u0442\u0438 \u043d\u0435 \u0431\u043e\u043b\u0435\u0435 \u0447\u0435\u043c \u043d\u0430 10%.<br \/>  2. \u041e\u0431\u043e\u0439\u0442\u0438\u0441\u044c \u043c\u0438\u043d\u0438\u043c\u0443\u043c\u043e\u043c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 \u0432 \u0442\u0435\u043a\u0443\u0449\u0435\u0439 \u0438\u043c\u043f\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438<\/p>\n<p>  \u0415\u0441\u043b\u0438 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e \u0440\u0435\u0448\u0435\u043d\u0438\u0435, \u0434\u043e\u0431\u0440\u043e \u043f\u043e\u0436\u0430\u043b\u043e\u0432\u0430\u0442\u044c \u043f\u043e\u0434 \u043a\u0430\u0442<br \/>  <a name=\"habracut\"><\/a><\/p>\n<h4>\u041d\u0430\u0438\u0432\u043d\u044b\u0439 \u043f\u043e\u0434\u0445\u043e\u0434. C\u043a\u0440\u0438\u043d\u0448\u043e\u0442\u044b<\/h4>\n<p>  \u0412 \u043d\u0430\u0448\u0435\u043c \u0442\u0435\u0441\u0442\u043e\u0432\u043e\u043c \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0435 \u0435\u0441\u0442\u044c \u043d\u0438\u0437\u043a\u043e\u0443\u0440\u043e\u0432\u043d\u0435\u0432\u0430\u044f \u043e\u0431\u0435\u0440\u0442\u043a\u0430 \u043d\u0430\u0434 Selenium. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u0435\u0440\u0432\u0430\u044f \u0438\u043c\u043f\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f \u0431\u044b\u043b\u0430 \u043e\u0447\u0435\u043d\u044c \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0438 \u043a\u0440\u0430\u0439\u043d\u0435 \u043d\u0430\u0438\u0432\u043d\u043e\u0439: \u0432\u043e \u0432\u0441\u0435 \u043c\u0435\u0441\u0442\u0430, \u0438\u0437\u043c\u0435\u043d\u044f\u044e\u0449\u0438\u0435 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 (Click, Set textbox, Navigate \u0438 \u0442.\u043f.) \u0431\u044b\u043b \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d \u043a\u043e\u0434, \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u044e\u0449\u0438\u0439 \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442 \u044d\u043a\u0440\u0430\u043d\u0430 \u0447\u0435\u0440\u0435\u0437 Selenium Web Driver  <\/p>\n<pre><code class=\"cs\">Driver.TakeScreenshot().SaveAsFile(screenshotPath); <\/code><\/pre>\n<p>  \u0412\u0440\u0435\u043c\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0442\u0435\u0441\u0442\u043e\u0432 \u0441 \u0442\u0430\u043a\u0438\u043c \u043f\u043e\u0434\u0445\u043e\u0434\u043e\u043c \u0432\u044b\u0440\u043e\u0441\u043b\u043e \u0432 \u0440\u0430\u0437\u044b. \u041f\u0440\u0438\u0447\u0438\u043d\u0430: \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442\u0430 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0441\u043e\u0432\u0441\u0435\u043c \u043d\u0435 \u0431\u044b\u0441\u0442\u0440\u043e \u2014 \u043e\u0442 0.5 \u0441\u0435\u043a\u0443\u043d\u0434\u044b \u0434\u043e \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u0441\u0435\u043a\u0443\u043d\u0434.<\/p>\n<h4>C\u043a\u0440\u0438\u043d\u0448\u043e\u0442\u044b \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u043c \u043f\u043e\u0442\u043e\u043a\u0435<\/h4>\n<p>  \u0412\u043c\u0435\u0441\u0442\u043e \u043a\u043e\u0434\u0430, \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u044e\u0449\u0435\u0433\u043e \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442\u044b \u0432\u043e \u0432\u0441\u0435\u0445 \u043c\u0435\u0441\u0442\u0430\u0445, \u0438\u0437\u043c\u0435\u043d\u044f\u044e\u0449\u0438\u0445 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 (Click, Set textbox, Navigate) \u0431\u044b\u043b \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d \u043a\u043e\u0434, \u043f\u043e\u0441\u0442\u043e\u044f\u043d\u043d\u043e \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u044e\u0449\u0438\u0439 \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442\u044b \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u043c \u043f\u043e\u0442\u043e\u043a\u0435  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">\u0421\u043a\u0440\u044b\u0442\u044b\u0439 \u0442\u0435\u043a\u0441\u0442<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"cs\">... var timeTillNextFrame = TimeSpan.Zero; while (!_stopThread.WaitOne(timeTillNextFrame)) {     var screenShotDriver = Driver as ITakesScreenshot;     if (screenShotDriver == null)     {         continue;     }      var screenShot = screenShotDriver.GetScreenshot();     ... } <\/code><\/pre>\n<p>  <\/div>\n<\/p><\/div>\n<p>  \u0412\u0440\u0435\u043c\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0442\u0435\u0441\u0442\u043e\u0432, \u043f\u043e-\u043f\u0440\u0435\u0436\u043d\u0435\u043c\u0443, \u0431\u044b\u043b\u043e \u043e\u0447\u0435\u043d\u044c \u0434\u043e\u043b\u0433\u0438\u043c. \u0421 \u043f\u0440\u0438\u0447\u0438\u043d\u043e\u0439 \u0437\u0430\u0434\u0435\u0440\u0436\u043a\u0438 \u044f \u043d\u0435 \u0441\u0442\u0430\u043b \u0440\u0430\u0437\u0431\u0438\u0440\u0430\u0442\u044c\u0441\u044f. \u0421\u043a\u043e\u0440\u0435\u0435 \u0432\u0441\u0435\u0433\u043e Selenium \u043e\u0442\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0447\u0442\u043e-\u0442\u043e \u0434\u0435\u043b\u0430\u0442\u044c, \u043f\u043e\u043a\u0430 \u0438\u0434\u0435\u0442 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442\u0430. \u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u043f\u043e\u043c\u043e\u0433 \u0431\u044b \u0435\u0449\u0435 \u043e\u0434\u0438\u043d \u0438\u043d\u0441\u0442\u0430\u043d\u0441 Selenium, \u0437\u0430\u043a\u043e\u043d\u043d\u0435\u043a\u0447\u0435\u043d\u043d\u044b\u0439 \u043a \u0442\u043e\u0439 \u0436\u0435 \u0441\u0435\u0441\u0441\u0438\u0438.<\/p>\n<h4>C\u043a\u0440\u0438\u043d\u0448\u043e\u0442\u044b \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u043c \u043f\u043e\u0442\u043e\u043a\u0435 \u0447\u0435\u0440\u0435\u0437 Puppeteer<\/h4>\n<p>  \u0414\u0435\u043b\u0430\u0442\u044c \u0434\u0432\u0430 \u0438\u043d\u0441\u0442\u0430\u043d\u0441\u0430 Selenium \u0431\u044b\u043b\u043e \u043d\u0435 \u043e\u0447\u0435\u043d\u044c \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e, \u0442\u0430\u043a \u043a\u0430\u043a \u044f \u0434\u0430\u0432\u043d\u043e \u0445\u043e\u0442\u0435\u043b \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u0442\u044c <a href=\"https:\/\/github.com\/hardkoded\/puppeteer-sharp\" rel=\"nofollow\">puppeteer-sharp<\/a> \u0432 \u0434\u0435\u043b\u0435 \u2014 \u0430 \u0442\u0443\u0442 \u043d\u0430\u0448\u043b\u0430\u0441\u044c \u043f\u043e\u0434\u0445\u043e\u0434\u044f\u0449\u0430\u044f \u043f\u0440\u0438\u0447\u0438\u043d\u0430. \u0421\u0431\u043e\u043a\u0443 \u043e\u0442 Selenium \u0431\u044b\u043b \u0441\u043e\u0437\u0434\u0430\u043d Puppeteer, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u0440\u0438\u043a\u043e\u043d\u043d\u0435\u043a\u0442\u0438\u043b\u0441\u044f \u043a Chrome, \u0443\u0436\u0435 \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u043e\u043c\u0443 \u0447\u0435\u0440\u0435\u0437 Selenium  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">\u0421\u043a\u0440\u044b\u0442\u044b\u0439 \u0442\u0435\u043a\u0441\u0442<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"cs\">var options = new ConnectOptions() {     BrowserURL = $&quot;http:\/\/127.0.0.1:{debugPort}&quot; };  _puppeteerBrowser = Puppeteer.ConnectAsync(options).GetAwaiter().GetResult(); <\/code><\/pre>\n<p>  <\/div>\n<\/p><\/div>\n<p>  \u0422\u0435\u0441\u0442 \u043f\u043e\u0448\u0435\u043b \u0441\u0432\u043e\u0435\u0439 \u0434\u043e\u0440\u043e\u0436\u043a\u043e\u0439 \u0447\u0435\u0440\u0435\u0437 Selenium, \u0430 \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442\u0430\u043c\u0438 \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u043c \u043f\u043e\u0442\u043e\u043a\u0435 \u0437\u0430\u043d\u044f\u043b\u0441\u044f Puppeteer  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">\u0421\u043a\u0440\u044b\u0442\u044b\u0439 \u0442\u0435\u043a\u0441\u0442<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"cs\">... var timeTillNextFrame = TimeSpan.Zero; while (!_stopThread.WaitOne(timeTillNextFrame)) {     var pages = _puppeteerBrowser.PagesAsync().GetAwaiter().GetResult();     if (pages.Length &lt;= 0)     {         continue;     }          var page = pages[0];          page.SetViewportAsync(new ViewPortOptions     {         Width = screenWidth,         Height = screenHeight     }).GetAwaiter().GetResult();          var screen = page.ScreenshotStreamAsync().GetAwaiter().GetResult();     ... } <\/code><\/pre>\n<p>  <\/div>\n<\/p><\/div>\n<p>  \u042d\u0442\u0430 \u0438\u043c\u043f\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f \u0434\u0430\u043b\u0430 \u043e\u0431\u043d\u0430\u0434\u0435\u0436\u0438\u0432\u0430\u044e\u0449\u0438\u0435 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b, \u0432\u0440\u0435\u043c\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u043b\u043e\u0441\u044c \u043d\u0430 \u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u044b\u0435 10%.<\/p>\n<p>  <b>\u041c\u0438\u043d\u0443\u0441\u044b<\/b><br \/>  1. \u0412\u0440\u0435\u043c\u044f \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442\u043e\u0432 \u0447\u0435\u0440\u0435\u0437 Puppeteer \u043d\u0435 \u043c\u0433\u043d\u043e\u0432\u0435\u043d\u043d\u043e\u0435, \u0447\u0430\u0441\u0442\u044c \u0444\u0440\u0435\u0439\u043c\u043e\u0432 \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u0442\u0435\u0440\u044f\u043d\u0430, \u0430 \u0432 \u043d\u0438\u0445 \u043c\u043e\u0436\u0435\u0442 \u043e\u043a\u0430\u0437\u0430\u0442\u044c\u0441\u044f, \u0447\u0442\u043e-\u0442\u043e \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e\u0435 \u0434\u043b\u044f \u0440\u0430\u0437\u0431\u043e\u0440\u0430.<br \/>  2. \u0415\u0441\u043b\u0438 Selenium \u043f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0430\u0435\u0442 \u0442\u0430\u0431\u044b, \u043d\u0443\u0436\u043d\u043e \u0443\u0432\u0435\u0434\u043e\u043c\u0438\u0442\u044c Puppeteer, \u0438\u043d\u0430\u0447\u0435 \u043e\u043d \u0431\u0443\u0434\u0435\u0442 \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442\u0438\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u0435\u0440\u0432\u044b\u0439 \u0442\u0430\u0431 \u0432 \u043a\u043e\u0434\u0435 \u0432\u044b\u0448\u0435 (\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u0435\u0441\u0442\u044c \u0441\u043f\u043e\u0441\u043e\u0431 \u043d\u0430\u0439\u0442\u0438 \u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0439 \u0442\u0430\u0431 \u2014 \u043d\u0430\u0434\u043e \u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c).<\/p>\n<p>  \u041f\u0435\u0440\u0432\u044b\u0439 \u043c\u0438\u043d\u0443\u0441 \u0434\u043b\u044f \u043c\u0435\u043d\u044f \u043e\u043a\u0430\u0437\u0430\u043b\u0441\u044f \u0431\u043b\u043e\u043a\u0438\u0440\u0443\u044e\u0449\u0438\u043c, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u043a \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u043c\u0443 \u0440\u0435\u0448\u0435\u043d\u0438\u044e.<\/p>\n<h4>Screencast<\/h4>\n<p>  \u0412 Chrome \u0435\u0441\u0442\u044c \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u0430\u044f \u0444\u0438\u0448\u043a\u0430 \u2014 <a href=\"https:\/\/chromedevtools.github.io\/devtools-protocol\/tot\/Page\/#method-startScreencast\" rel=\"nofollow\">Page.startScreencast<\/a>. \u041f\u043e \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044e \u2014 \u043e\u043d\u0430 \u043a\u0430\u043a \u0440\u0430\u0437 \u0434\u0435\u043b\u0430\u0435\u0442 \u0442\u043e, \u0447\u0442\u043e \u043d\u0430\u0434\u043e \u2014 \u043a\u0430\u0441\u0442\u0438\u0442 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u043d\u044b\u0435 \u0444\u0440\u0435\u0439\u043c\u044b, \u0447\u0442\u043e\u0431\u044b \u0436\u0435\u043b\u0430\u044e\u0449\u0438\u0435 \u043c\u043e\u0433\u043b\u0438 \u0438\u0445 \u043f\u0435\u0440\u0435\u0445\u0432\u0430\u0442\u0438\u0442\u044c \u0438 \u0447\u0442\u043e-\u043d\u0438\u0431\u0443\u0434\u044c \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e\u0435 \u0441 \u043d\u0438\u043c\u0438 \u0441\u0434\u0435\u043b\u0430\u0442\u044c. <\/p>\n<p>  \u0418 \u0432 Selenium, \u0438 \u0432 Puppeteer \u043c\u043e\u0436\u043d\u043e \u0441\u0442\u0430\u0440\u0442\u043e\u0432\u0430\u0442\u044c Page.startScreencast, \u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438 \u043d\u0435\u043b\u044c\u0437\u044f \u043d\u0438 \u0432 \u043e\u0434\u043d\u043e\u043c, \u043d\u0438 \u0432 \u0434\u0440\u0443\u0433\u043e\u043c. <a href=\"https:\/\/github.com\/puppeteer\/puppeteer\/issues\/478\" rel=\"nofollow\">\u0425\u043e\u0442\u0435\u043b\u043a\u0430<\/a> \u0442\u0430\u043a\u0430\u044f \u0443\u0436\u0435 \u043e\u0437\u0432\u0443\u0447\u0435\u043d\u0430 \u2014 \u0436\u0434\u0435\u043c \u0438\u043c\u043f\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044e.<\/p>\n<p>  \u042f \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u043b \u043f\u043e\u0434\u0440\u0443\u0436\u0438\u0442\u044c\u0441\u044f \u0441 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u0447\u043a\u043e\u0439 <a href=\"https:\/\/github.com\/MasterDevs\/ChromeDevTools\" rel=\"nofollow\">ChromeDevTools<\/a>. \u041a \u0441\u043e\u0436\u0430\u043b\u0435\u043d\u0438\u044e, \u0431\u044b\u0441\u0442\u0440\u043e \u043d\u0430\u043b\u0430\u0434\u0438\u0442\u044c \u0445\u043e\u0440\u043e\u0448\u0438\u0435 \u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u044f \u0443 \u043c\u0435\u043d\u044f \u0441 \u043d\u0435\u0439 \u043d\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c. \u041f\u043e\u0441\u043b\u0435 \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0438\u0445 \u043f\u043e\u0438\u0441\u043a\u043e\u0432 \u0431\u044b\u043b\u043e \u043d\u0430\u0439\u0434\u0435\u043d\u043e \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u0434\u043b\u044f ScreenCast \u0432 <a href=\"https:\/\/github.com\/mafredri\/cdp\/blob\/master\/example\/screencast\/main.go\" rel=\"nofollow\">mafredri\/cdp<\/a> \u0418\u0437 \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u0433\u043e \u043f\u0440\u0438\u043c\u0435\u0440\u0430 \u0431\u044b\u043b\u0430 \u0443\u0431\u0440\u0430\u043d\u0430 \u043d\u0435\u043d\u0443\u0436\u043d\u0430\u044f \u043d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u044f \u0438 \u0431\u044b\u043b\u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u044b \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u0432\u0445\u043e\u0434\u043d\u044b\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">\u0421\u043a\u0440\u044b\u0442\u044b\u0439 \u0442\u0435\u043a\u0441\u0442<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"go\">package main  import (     &quot;os&quot;     &quot;context&quot;     &quot;fmt&quot;     &quot;io\/ioutil&quot;     &quot;log&quot;     &quot;time&quot;     &quot;flag&quot;      &quot;github.com\/mafredri\/cdp&quot;     &quot;github.com\/mafredri\/cdp\/devtool&quot;     &quot;github.com\/mafredri\/cdp\/protocol\/page&quot;     &quot;github.com\/mafredri\/cdp\/rpcc&quot; )  func main() {      folderPtr := flag.String(&quot;folder&quot;, &quot;&quot;, &quot;folder path for screenshots: example c:\\\\temp\\\\screens\\\\&quot;)     chromePtr := flag.String(&quot;chrome&quot;, &quot;http:\/\/localhost:9222&quot;, &quot;chrome connection - example: http:\/\/localhost:9222&quot;)          widthPtr := flag.Int(&quot;width&quot;, 1280, &quot;screencast width&quot;)     heightPtr := flag.Int(&quot;height&quot;, 720, &quot;screencast height&quot;)     qualityPtr := flag.Int(&quot;quality&quot;, 100, &quot;screencast quality&quot;)          flag.Parse()      if err := run(*folderPtr, *chromePtr, *widthPtr, *heightPtr, *qualityPtr); err != nil {         panic(err)     } }  func run(folder string, chromeConnection string, width int, height int, quality int) error {     ctx, cancel := context.WithCancel(context.TODO())     defer cancel()          chromePath := chromeConnection     folderPath := folder      devt := devtool.New(chromePath)      pageTarget, err := devt.Get(ctx, devtool.Page)     if err != nil {         return err     }      conn, err := rpcc.DialContext(ctx, pageTarget.WebSocketDebuggerURL)     if err != nil {         return err     }     defer conn.Close()      c := cdp.NewClient(conn)      err = c.Page.Enable(ctx)     if err != nil {         return err     }      \/\/ Start listening to ScreencastFrame events.     screencastFrame, err := c.Page.ScreencastFrame(ctx)     if err != nil {         return err     }      go func() {         defer screencastFrame.Close()          for {             ev, err := screencastFrame.Recv()             if err != nil {                 log.Printf(&quot;Failed to receive ScreencastFrame: %v&quot;, err)                 os.Exit(0)             }             log.Printf(&quot;Got frame with sessionID: %d: %+v&quot;, ev.SessionID, ev.Metadata)              err = c.Page.ScreencastFrameAck(ctx, page.NewScreencastFrameAckArgs(ev.SessionID))             if err != nil {                 log.Printf(&quot;Failed to ack ScreencastFrame: %v&quot;, err)                 os.Exit(0)             }              \/\/ Write to screencast_frame-[timestamp].png.             name := fmt.Sprintf(&quot;screencast_frame-%d.png&quot;, ev.Metadata.Timestamp.Time().Unix())                          filePath := folderPath + name              \/\/ Write the frame to file (without blocking).             go func() {                 err = ioutil.WriteFile(filePath, ev.Data, 0644)                 if err != nil {                     log.Printf(&quot;Failed to write ScreencastFrame to %q: %v&quot;, name, err)                 }             }()         }     }()      screencastArgs := page.NewStartScreencastArgs().         SetQuality(quality).         SetMaxWidth(width).         SetMaxHeight(height).         SetEveryNthFrame(1).         SetFormat(&quot;png&quot;)     err = c.Page.StartScreencast(ctx, screencastArgs)     if err != nil {         return err     }      \/\/ Random delay for our screencast.     time.Sleep(600 * time.Second)      err = c.Page.StopScreencast(ctx)     if err != nil {         return err     }      return nil } <\/code><\/pre>\n<p>  <\/div>\n<\/p><\/div>\n<p>  \u0414\u0430\u043b\u0435\u0435 \u0434\u0430\u043d\u043d\u044b\u0439 \u0444\u0430\u0439\u043b\u0438\u043a \u0431\u044b\u043b \u0441\u043e\u0431\u0440\u0430\u043d \u043a\u043e\u043c\u0430\u043d\u0434\u043e\u0439<br \/>  <code>go build -o screencast.exe main.go<br \/>  <\/code><\/p>\n<p>  \u0418 \u044f \u0441\u043c\u043e\u0433 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u0432 C# solution \u0441 \u0442\u0435\u0441\u0442\u0430\u043c\u0438  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">\u0421\u043a\u0440\u044b\u0442\u044b\u0439 \u0442\u0435\u043a\u0441\u0442<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"cs\">var startInfo = new ProcessStartInfo(screenCastPath) {     WindowStyle = ProcessWindowStyle.Minimized,      Arguments = $&quot;-folder={_framesFolderPath} &quot; +                 $&quot;-chrome=http:\/\/localhost:{_debugPort} &quot; +                 &quot;-width=1024 &quot; +                 &quot;-height=576 &quot; +                 &quot;-quality=0&quot; };  Process.Start(startInfo); <\/code><\/pre>\n<p>  <\/div>\n<\/p><\/div>\n<p>  \u041e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u043f\u043e\u0442\u043e\u043a \u0434\u043b\u044f \u0437\u0430\u043f\u0438\u0441\u0438 \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442\u043e\u0432 \u0431\u044b\u043b \u0432\u044b\u043a\u0438\u043d\u0443\u0442 \u0437\u0430 \u043d\u0435\u043d\u0430\u0434\u043e\u0431\u043d\u043e\u0441\u0442\u044c\u044e. \u0410\u043b\u043e\u0433\u0440\u0438\u0442\u043c \u0440\u0430\u0431\u043e\u0442\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0441\u044f \u0442\u0430\u043a\u0438\u043c:<br \/>  1. \u0421\u0442\u0430\u0440\u0442\u0443\u0435\u043c Chrome \u0447\u0435\u0440\u0435\u0437 Selenium<br \/>  2. \u0421\u0442\u0430\u0440\u0442\u0443\u0435\u043c Screencast \u0447\u0435\u0440\u0435\u0437 \u0441\u043e\u0431\u0440\u0430\u043d\u043d\u044b\u0439 \u0431\u0438\u043d\u0430\u0440\u043d\u0438\u043a \u2014 \u043e\u043d \u043a\u043e\u043d\u043d\u0435\u043a\u0442\u0438\u0442\u0441\u044f \u043a Chrome \u0438 \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0442\u044c \u043f\u043e\u0442\u043e\u043a \u0444\u0440\u0435\u0439\u043c\u043e\u0432 \u0432 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u0443\u044e \u043d\u0430\u043c\u0438 \u043f\u0430\u043f\u043a\u0443<br \/>  3. \u041f\u043e \u043e\u043a\u043e\u043d\u0447\u0430\u043d\u0438\u0438 \u0442\u0435\u0441\u0442\u0430 \u0437\u0430\u043a\u0440\u044b\u0432\u0430\u0435\u043c Chrome \u2014 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u043e\u043c \u0437\u0430\u043a\u0440\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0431\u0438\u043d\u0430\u0440\u043d\u0438\u043a<br \/>  4. \u0415\u0441\u043b\u0438 \u0442\u0435\u0441\u0442 \u0443\u043f\u0430\u043b \u2014 \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u0432\u0438\u0434\u0435\u043e<br \/>  5. \u0417\u0430\u0447\u0438\u0449\u0430\u0435\u043c \u043f\u0430\u043f\u043a\u0443 \u0441 \u0444\u0440\u0435\u0439\u043c\u0430\u043c\u0438 <\/p>\n<p>  \u0414\u0430\u043d\u043d\u044b\u0439 \u043f\u043e\u0434\u0445\u043e\u0434 \u0434\u0430\u043b \u043b\u0443\u0447\u0448\u0438\u0439 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u043f\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f (\u0437\u0430\u0434\u0435\u0440\u0436\u0435\u043a \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043d\u0435\u0442). \u041f\u043b\u044e\u0441 \u043e\u043d \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u043b \u043c\u0430\u043a\u0441\u0438\u043c\u0443\u043c \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043f\u043e \u0442\u0435\u0441\u0442\u0443 (\u043f\u043e\u0442\u0435\u0440\u044f\u043d\u043d\u044b\u0445 \u0444\u0440\u0435\u0439\u043c\u043e\u0432 \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043d\u0435\u0442). <\/p>\n<p>  <b>\u041c\u0438\u043d\u0443\u0441\u044b<\/b><br \/>  1. \u041d\u0435\u0432\u044b\u0441\u043e\u043a\u043e\u0435 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u0434\u043b\u044f screencast. \u0415\u0441\u043b\u0438 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0442\u0435\u0441\u0442\u044b \u0432 \u043f\u0430\u0440\u0443 \u043f\u043e\u0442\u043e\u043a\u043e\u0432 \u0438 \u0432\u044b\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0435 2560*1440 \u0434\u043b\u044f Chrome \u2014 \u0442\u043e \u043f\u0440\u043e\u0438\u0437\u043e\u0439\u0434\u0435\u0442 <a href=\"https:\/\/groups.google.com\/a\/chromium.org\/forum\/#!topic\/chromium-discuss\/U5qyeX_ydBo\" rel=\"nofollow\">\u043f\u0435\u0440\u0435\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0431\u0443\u0444\u0435\u0440\u0430<\/a>, \u043e\u0442\u0432\u0435\u0434\u0435\u043d\u043d\u043e\u0433\u043e \u043f\u043e\u0434 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0443 \u0434\u0430\u043d\u043d\u044b\u0445. <\/p>\n<p>  2. C \u0440\u043e\u0441\u0442\u043e\u043c \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u044f, \u0432\u043e\u0437\u0440\u0430\u0441\u0442\u0430\u0435\u0442 \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u043d\u0430 CPU. <\/p>\n<p>  \u0412 \u0438\u0442\u043e\u0433\u0435, \u043f\u043e\u0434 screencast \u044f \u0432\u044b\u0431\u0440\u0430\u043b \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0435 1024*576 \u2014 \u043d\u0430 \u0442\u0430\u043a\u043e\u043c \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u0442\u0435\u0441\u0442\u044b \u043e\u0442\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u0438 \u043d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u043e \u0432 6 \u043f\u043e\u0442\u043e\u043a\u043e\u0432, \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440 \u0440\u0430\u0431\u043e\u0442\u0430\u043b \u0432 \u043a\u043e\u043c\u0444\u043e\u0440\u0442\u043d\u043e\u043c \u0440\u0435\u0436\u0438\u043c\u0435 (6-\u0442\u0438 \u044f\u0434\u0435\u0440\u043d\u0438\u043a i7-5820).<\/p>\n<h4>\u0421\u043e\u0431\u0438\u0440\u0430\u0435\u043c \u0432\u0438\u0434\u0435\u043e<\/h4>\n<p>  \u041e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u0441\u043e\u0431\u0440\u0430\u0442\u044c \u0444\u0440\u0435\u0439\u043c\u044b \u0432 \u0432\u0438\u0434\u0435\u043e. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u0447\u043a\u0443 <a href=\"https:\/\/github.com\/baSSiLL\/SharpAvi\" rel=\"nofollow\">SharpAvi<\/a>  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">\u0421\u043a\u0440\u044b\u0442\u044b\u0439 \u0442\u0435\u043a\u0441\u0442<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"cs\">private void GenerateVideoFromScreens(string videoPath) {     try     {         var videoWriter = new AviWriter(videoPath) { FramesPerSecond = 1, EmitIndex1 = true };          var videoStream = videoWriter.AddMotionJpegVideoStream(1024, 576);          var screens = new DirectoryInfo(_framesFolderPath).GetFiles().OrderBy(f =&gt; f.CreationTimeUtc.Ticks).ToList();         foreach (var screen in screens)         {             try             {                 using (var bmp = new Bitmap(screen.FullName))                 {                     var bits = bmp.LockBits(new Rectangle(0, 0, videoStream.Width, videoStream.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppRgb);                     var videoFrame = new byte[videoStream.Width * videoStream.Height * 4];                     Marshal.Copy(bits.Scan0, videoFrame, 0, videoFrame.Length);                     bmp.UnlockBits(bits);                      videoStream.WriteFrameAsync(                         true,                         videoFrame,                         0,                         videoFrame.Length).GetAwaiter().GetResult();                 }             }             catch(Exception ex)             {                 \/\/ ignore all video related errors per frame             }         }          videoWriter.Close();     }     catch     {         \/\/ ignore all video related errors per streams     } } <\/code><\/pre>\n<p>  <\/div>\n<\/p><\/div>\n<h4>Upscale \u043a\u0430\u0440\u0442\u0438\u043d\u043e\u043a<\/h4>\n<p>  \u0422\u0430\u043a \u043a\u0430\u043a \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0435 screencast \u0441\u043e\u0432\u0441\u0435\u043c \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0435 1024*576, \u043d\u0443\u0436\u043d\u043e \u0432\u044b\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0438 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0435 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u0441\u0430\u043c\u043e\u043c\u0443 Chrome, \u0438\u043d\u0430\u0447\u0435 \u0431\u0443\u0434\u0443\u0442 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u0441 \u043c\u0435\u043b\u043a\u0438\u043c \u0442\u0435\u043a\u0441\u0442\u043e\u043c.<\/p>\n<p>  Chrome 2560*1440 -&gt; screencast \u0432 1024*576 = \u043c\u0435\u043b\u043a\u0438\u0439 \u0442\u0435\u043a\u0441\u0442 \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043d\u0435\u0447\u0438\u0442\u0430\u0435\u043c<br \/>  Chrome 1920*1080 -&gt; screencast \u0432 1024*576 = \u043c\u0435\u043b\u043a\u0438\u0439 \u0442\u0435\u043a\u0441\u0442 \u0447\u0438\u0442\u0430\u0435\u0442\u0441\u044f \u0441 \u0442\u0440\u0443\u0434\u043e\u043c<br \/>  Chrome 1408*792 -&gt; screencast \u0432 1024*576 = \u043c\u0435\u043b\u043a\u0438\u0439 \u0442\u0435\u043a\u0441\u0442 \u0447\u0438\u0442\u0430\u0435\u0442\u0441\u044f \u0431\u0435\u0437 \u043f\u0440\u043e\u0431\u043b\u0435\u043c<\/p>\n<p>  \u041f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u043e\u0435 \u0432\u0438\u0434\u0435\u043e 1024*576 \u043c\u043e\u0436\u043d\u043e \u0443\u043b\u0443\u0447\u0448\u0438\u0442\u044c \u2014 \u0435\u0441\u043b\u0438 \u0444\u0440\u0435\u0439\u043c\u044b \u0437\u0430\u0430\u043f\u0441\u043a\u0435\u0439\u043b\u0438\u0442\u044c \u0434\u043e 1920*1080 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u0447\u043a\u0438 <a href=\"https:\/\/github.com\/saucecontrol\/PhotoSauce\" rel=\"nofollow\">PhotoSauce<\/a>  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">\u0421\u043a\u0440\u044b\u0442\u044b\u0439 \u0442\u0435\u043a\u0441\u0442<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"cs\">public Bitmap ResizeImage(Bitmap bitmap, int width) { \tusing (var inStream = new MemoryStream()) \t{ \t\tbitmap.Save(inStream, ImageFormat.Png); \t\tinStream.Position = 0; \t\tusing (MemoryStream outStream = new MemoryStream()) \t\t{ \t\t\tvar settings = new ProcessImageSettings { Width = width }; \t\t\tMagicImageProcessor.ProcessImage(inStream, outStream, settings); \t\t\treturn new Bitmap(outStream); \t\t} \t} } <\/code><\/pre>\n<p>  <\/div>\n<\/p><\/div>\n<p>  \u0412 \u0438\u0442\u043e\u0433\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0438\u0441\u044c \u0442\u0430\u043a\u0438\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b: Chrome \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0432 1408*792, ScreenCast \u0432 1024*576, \u0438\u0442\u043e\u0433\u043e\u0432\u043e\u0435 \u0432\u0438\u0434\u0435\u043e \u0434\u043b\u044f \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0430 \u0430\u043f\u0441\u043a\u0435\u0439\u043b\u0438\u0442\u0441\u044f \u0434\u043e 1920*1080. \u041f\u043e \u0441\u0441\u044b\u043b\u043a\u0435 \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c <a href=\"https:\/\/jirareportsstorage.blob.core.windows.net\/photo\/result.avi\" rel=\"nofollow\">\u043f\u0440\u0438\u043c\u0435\u0440<\/a> \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u043e\u0433\u043e \u0432\u0438\u0434\u0435\u043e.<\/p>\n<h4>\u0421\u043f\u0430\u0441\u0438\u0431\u043e<\/h4>\n<p>  \u0421\u043f\u0430\u0441\u0438\u0431\u043e, \u0432\u0441\u0435\u043c \u043a\u0442\u043e \u0434\u043e\u0447\u0438\u0442\u0430\u043b \u2014 \u0435\u0441\u043b\u0438 \u0435\u0441\u0442\u044c \u0431\u043e\u043b\u0435\u0435 \u043f\u0440\u043e\u0441\u0442\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u0439 \u0437\u0430\u0434\u0430\u0447\u043a\u0438, \u043d\u0430\u043f\u0438\u0448\u0438\u0442\u0435, \u043f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u0432 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0438. \u0422\u0430\u043a \u0436\u0435 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442\u0441\u044f \u043b\u044e\u0431\u0430\u044f \u043a\u0440\u0438\u0442\u0438\u043a\u0430, \u0432 \u0442\u043e\u043c \u0447\u0438\u0441\u043b\u0435 \u0437\u043b\u043e\u0431\u043d\u0430\u044f \u043f\u043e \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043d\u043e\u043c\u0443 \u0432\u044b\u0448\u0435.<\/p>\n<p>  \u0412\u0441\u0435\u043c \u0437\u0434\u043e\u0440\u043e\u0432\u044c\u044f \u0438 \u0441\u043a\u043e\u0440\u0435\u0439\u0448\u0435\u0433\u043e \u043e\u043a\u043e\u043d\u0447\u0430\u043d\u0438\u044f \u043a\u043e\u0432\u0438\u0434\u043d\u044b\u0445 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0439!<\/p><\/div>\n<p> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/post\/503476\/\"> https:\/\/habr.com\/ru\/post\/503476\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"\n<div class=\"post__text post__text-html post__text_v1\" id=\"post-content-body\" data-io-article-url=\"https:\/\/habr.com\/ru\/post\/503476\/\">\u0412\u0441\u0435\u043c \u043f\u0440\u0438\u0432\u0435\u0442! <\/p>\n<p>  \u0412 \u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u0445\u043e\u0447\u0435\u0442\u0441\u044f \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u0430\u0442\u044c \u043e \u0442\u043e\u043c, \u043a\u0430\u043a \u0431\u044b\u043b\u0430 \u0440\u0435\u0448\u0435\u043d\u0430 \u0437\u0430\u0434\u0430\u0447\u0430 \u0437\u0430\u043f\u0438\u0441\u0438 \u0432\u0438\u0434\u0435\u043e \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432, \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0449\u0438\u0445 \u0432 <b>headless<\/b> Chrome (\u0441 \u0437\u0430\u043f\u0438\u0441\u044c\u044e \u0432 \u043d\u0435 headless \u0440\u0435\u0436\u0438\u043c\u0435 \u043f\u0440\u043e\u0431\u043b\u0435\u043c \u0431\u044b\u0442\u044c \u043d\u0435 \u0434\u043e\u043b\u0436\u043d\u043e). \u0411\u0443\u0434\u0435\u0442 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u043e \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0440\u0430\u0437\u043d\u044b\u0445 \u043f\u043e\u0434\u0445\u043e\u0434\u043e\u0432, \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u0430\u043d\u043e \u043f\u0440\u043e \u0442\u0440\u0443\u0434\u043d\u043e\u0441\u0442\u0438 \u0438 \u043f\u0443\u0442\u0438 \u0438\u0445 \u0440\u0435\u0448\u0435\u043d\u0438\u044f. <\/p>\n<p>  <b>\u041f\u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u0437\u0430\u0434\u0430\u0447\u0438<\/b><br \/>  1. \u0422\u0435\u0441\u0442\u044b \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u044e\u0442\u0441\u044f \u043f\u043e\u0434 Windows<br \/>  2. \u0422\u0435\u0441\u0442\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442 Selenium Web Driver + Headless Chrome<br \/>  3. \u0422\u0435\u0441\u0442\u044b \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u044e\u0442\u0441\u044f \u0432 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u0442\u043e\u043a\u043e\u0432<\/p>\n<p>  \u0414\u043b\u044f \u0443\u043f\u0430\u0432\u0448\u0438\u0445 \u0442\u0435\u0441\u0442\u043e\u0432 \u043d\u0443\u0436\u043d\u043e \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0432\u0438\u0434\u0435\u043e, \u043f\u0440\u0438 \u044d\u0442\u043e\u043c <br \/>  1. \u0412\u0440\u0435\u043c\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0434\u043e\u043b\u0436\u043d\u043e \u0432\u044b\u0440\u0430\u0441\u0442\u0438 \u043d\u0435 \u0431\u043e\u043b\u0435\u0435 \u0447\u0435\u043c \u043d\u0430 10%.<br \/>  2. \u041e\u0431\u043e\u0439\u0442\u0438\u0441\u044c \u043c\u0438\u043d\u0438\u043c\u0443\u043c\u043e\u043c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 \u0432 \u0442\u0435\u043a\u0443\u0449\u0435\u0439 \u0438\u043c\u043f\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438<\/p>\n<p>  \u0415\u0441\u043b\u0438 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e \u0440\u0435\u0448\u0435\u043d\u0438\u0435, \u0434\u043e\u0431\u0440\u043e \u043f\u043e\u0436\u0430\u043b\u043e\u0432\u0430\u0442\u044c \u043f\u043e\u0434 \u043a\u0430\u0442  <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-304122","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/304122","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=304122"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/304122\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=304122"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=304122"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=304122"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}