2009-12-30 2 views
43

Я пишу специализированный искатель и парсер для внутреннего использования, и мне нужна возможность сделать снимок экрана веб-страницы, чтобы проверить, какие цвета используются повсюду. Программа займет около десяти веб-адресов и сохранит их в виде растрового изображения.Программно сделайте снимок экрана с страницы

Оттуда я планирую использовать LockBits, чтобы создать список из пяти наиболее используемых цветов внутри изображения. Насколько мне известно, это самый простой способ получить цвета, используемые на веб-странице, но если есть более простой способ сделать это, пожалуйста, включите свои предложения.

В любом случае, я собирался использовать ACA WebThumb ActiveX Control пока не увидел цену. Я также довольно новичок в C#, но использовал его всего несколько месяцев. Есть ли решение моей проблемы сделать снимок экрана веб-страницы, чтобы извлечь цветовую схему?

+0

Не пробовал (почему это комментарий, а не ответ), но (http://www.dreamincode.net/code/snippet2539.htm) кажется C# решение, чтобы сохранить веб-страницу в виде растрового изображения. –

+0

Сколько страниц вы ползаете в месяц? – jjxtra

+0

Не так много, я использую только изображения для извлечения данных, поэтому если один или два сбой, то это не большая проблема. До сих пор у меня не было никаких проблем с этим, кроме того, что ему нужно использовать Application.Run() для перемещения вперед. –

ответ

19

https://www.url2png.com/docs является хорошим. У них есть свободный уровень.

Чтобы загрузить двоичный файл изображения, вам нужно использовать HttpWebRequest. Вот пример:

HttpWebRequest request = HttpWebRequest.Create("https://api.url2png.com/v6/[API_KEY]/[API_TOKEN]/png/?url=[URL]") as HttpWebRequest; 
Bitmap bitmap; 
using (Stream stream = request.GetResponse().GetResponseStream()) 
{ 
    bitmap = new Bitmap(stream); 
} 
// now that you have a bitmap, you can do what you need to do... 

Для создания URL ...

public static string url2png(string UrlToSite) 
{ 
    string url2pngAPIKey = "PXXX"; 
    string url2pngPrivateKey = "SXXX"; 

    string url = HttpUtility.UrlEncode(UrlToSite); 

    string getstring = "fullpage=true&url=" + url; 

    string SecurityHash_url2png = Md5HashPHPCompliant(url2pngPrivateKey + "+" + getstring).ToLower(); 

    var url2pngLink = "http://api.url2png.com/v6/" + url2pngAPIKey + "/" + SecurityHash_url2png + "/" + "png/?" + getstring; 

    return url2pngLink; 
} 

public static string Md5HashPHPCompliant(string pass) 
{ 
    System.Security.Cryptography.MD5CryptoServiceProvider md5 = new System.Security.Cryptography.MD5CryptoServiceProvider(); 

    byte[] dataMd5 = md5.ComputeHash(Encoding.UTF8.GetBytes(pass)); 
    StringBuilder sb = new StringBuilder(); 

    for (int i = 0; i <= dataMd5.Length - 1; i++) 
    { 
     sb.AppendFormat("{0:x2}", dataMd5[i]); 
    } 

    return sb.ToString(); 
} 
+0

Я попробую этот метод и посмотрю, как он влияет на аспект извлечения данных. –

+0

@MikeB как добавить к нему код активации: | – confusedMind

+0

@PsychoDad, у моего потока больше 65,535 пикселей. Что я делаю?? – FabianoLothor

25

Быстро и грязно использовать WinForms WebBrowser и рисовать его в растровое изображение. Выполнение этого в автономном консольном приложении несколько сложно, потому что вы должны знать о последствиях размещения элемента управления STAThread при использовании принципиально асинхронного шаблона программирования. Но вот работает доказательство концепции, которая захватывает веб-страницы в файл 800х600 BMP:

namespace WebBrowserScreenshotSample 
{ 
    using System; 
    using System.Drawing; 
    using System.Drawing.Imaging; 
    using System.Threading; 
    using System.Windows.Forms; 

    class Program 
    { 
     [STAThread] 
     static void Main() 
     { 
      int width = 800; 
      int height = 600; 

      using (WebBrowser browser = new WebBrowser()) 
      { 
       browser.Width = width; 
       browser.Height = height; 
       browser.ScrollBarsEnabled = true; 

       // This will be called when the page finishes loading 
       browser.DocumentCompleted += Program.OnDocumentCompleted; 

       browser.Navigate("https://stackoverflow.com/"); 

       // This prevents the application from exiting until 
       // Application.Exit is called 
       Application.Run(); 
      } 
     } 

     static void OnDocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e) 
     { 
      // Now that the page is loaded, save it to a bitmap 
      WebBrowser browser = (WebBrowser)sender; 

      using (Graphics graphics = browser.CreateGraphics()) 
      using (Bitmap bitmap = new Bitmap(browser.Width, browser.Height, graphics)) 
      { 
       Rectangle bounds = new Rectangle(0, 0, bitmap.Width, bitmap.Height); 
       browser.DrawToBitmap(bitmap, bounds); 
       bitmap.Save("screenshot.bmp", ImageFormat.Bmp); 
      } 

      // Instruct the application to exit 
      Application.Exit(); 
     } 
    } 
} 

Для компиляции этого создайте новое консольное приложение и убедитесь, чтобы добавить ссылки на сборки для System.Drawing и System.Windows.Forms.

ОБНОВЛЕНИЕ: Я переписал код, чтобы избежать использования шаблона WaitOne/DoEvents для хакерского опроса. Этот код должен быть ближе к следующим рекомендациям.

UPDATE 2: Вы указываете, что хотите использовать это в приложении Windows Forms. В этом случае забудьте о динамическом создании элемента управления WebBrowser. Вы хотите создать скрытый (Visible = false) экземпляр WebBrowser на вашей форме и использовать его так же, как показано выше. Вот еще один пример, который показывает часть кода пользователя формы с текстовым полем (webAddressTextBox), кнопкой (generateScreenshotButton) и скрытым браузером (webBrowser). Хотя я работал над этим, я обнаружил особенность, с которой я раньше не справлялся - событие DocumentCompleted может быть поднято несколько раз в зависимости от характера страницы. Этот образец должен работать в целом, и вы можете продлить его делать то, что вы хотите:

namespace WebBrowserScreenshotFormsSample 
{ 
    using System; 
    using System.Drawing; 
    using System.Drawing.Imaging; 
    using System.IO; 
    using System.Windows.Forms; 

    public partial class MainForm : Form 
    { 
     public MainForm() 
     { 
      this.InitializeComponent(); 

      // Register for this event; we'll save the screenshot when it fires 
      this.webBrowser.DocumentCompleted += 
       new WebBrowserDocumentCompletedEventHandler(this.OnDocumentCompleted); 
     } 

     private void OnClickGenerateScreenshot(object sender, EventArgs e) 
     { 
      // Disable button to prevent multiple concurrent operations 
      this.generateScreenshotButton.Enabled = false; 

      string webAddressString = this.webAddressTextBox.Text; 

      Uri webAddress; 
      if (Uri.TryCreate(webAddressString, UriKind.Absolute, out webAddress)) 
      { 
       this.webBrowser.Navigate(webAddress); 
      } 
      else 
      { 
       MessageBox.Show(
        "Please enter a valid URI.", 
        "WebBrowser Screenshot Forms Sample", 
        MessageBoxButtons.OK, 
        MessageBoxIcon.Exclamation); 

       // Re-enable button on error before returning 
       this.generateScreenshotButton.Enabled = true; 
      } 
     } 

     private void OnDocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e) 
     { 
      // This event can be raised multiple times depending on how much of the 
      // document has loaded, if there are multiple frames, etc. 
      // We only want the final page result, so we do the following check: 
      if (this.webBrowser.ReadyState == WebBrowserReadyState.Complete && 
       e.Url == this.webBrowser.Url) 
      { 
       // Generate the file name here 
       string screenshotFileName = Path.GetFullPath(
        "screenshot_" + DateTime.Now.Ticks + ".png"); 

       this.SaveScreenshot(screenshotFileName); 
       MessageBox.Show(
        "Screenshot saved to '" + screenshotFileName + "'.", 
        "WebBrowser Screenshot Forms Sample", 
        MessageBoxButtons.OK, 
        MessageBoxIcon.Information); 

       // Re-enable button before returning 
       this.generateScreenshotButton.Enabled = true; 
      } 
     } 

     private void SaveScreenshot(string fileName) 
     { 
      int width = this.webBrowser.Width; 
      int height = this.webBrowser.Height; 
      using (Graphics graphics = this.webBrowser.CreateGraphics()) 
      using (Bitmap bitmap = new Bitmap(width, height, graphics)) 
      { 
       Rectangle bounds = new Rectangle(0, 0, width, height); 
       this.webBrowser.DrawToBitmap(bitmap, bounds); 
       bitmap.Save(fileName, ImageFormat.Png); 
      } 
     } 
    } 
} 
+0

Извините за огромную задержку, кажется, что код работает хорошо, но я боюсь использовать его в той форме, которую у меня есть. Я, наверное, делаю что-то глупое, но если бы вы могли дать мне руку, это было бы очень признательно. –

+0

DrawToBitmap не поддерживается и иногда будет терпеть неудачу, оставив пустую черную или пустую белую растровую карту. – jjxtra

+0

@bobbymcr. У вас есть хоть какая-то идея, почему страница, обработанная браузером браузера IE, имеет некорректные стили. –

1

Проверить this вне. Это, похоже, делает то, что вы хотели, и технически оно подходит к проблеме аналогичным образом через управление веб-браузером. Похоже, что он обслуживал ряд параметров, которые должны быть переданы, а также встроенная в него хорошая обработка ошибок. Единственным недостатком является то, что вы создаете внешний процесс (exe) и создаете физический файл, который вы прочтете позже. Из вашего описания вы даже рассматриваете веб-службы, поэтому я не думаю, что это проблема.

В решении вашего последнего комментария о том, как обрабатывать несколько из них одновременно, это будет идеально. Вы можете запускать параллель 3, 4, 5 или более процессов в любой момент времени или анализировать бит цвета, выполняемый как поток, в то время как другой процесс захвата происходит.

Для обработки изображений, я недавно встретил Emgu, havent использовал его сам, но он кажется увлекательным. Он утверждает, что он работает быстро и имеет большую поддержку графического анализа, включая считывание цвета пикселей. Если у меня сейчас есть проект графической обработки, я попробую.

1

вы также можете посмотреть на Qt Jambi http://qt.nokia.com/doc/qtjambi-4.4/html/com/trolltech/qt/qtjambi-index.html

они имеют хороший WebKit на основе реализации Java для браузера, где вы можете сделать скриншот, просто делая н как:

QPixmap pixmap; 
    pixmap = QPixmap.grabWidget(browser); 

    pixmap.save(writeTo, "png"); 

Have посмотрите на образцы - у них есть хорошая демонстрация веб-браузера.

13

Существует отличный браузер Webkit PhantomJS, который позволяет выполнять любой JavaScript из командной строки.

Установите его из http://phantomjs.org/download.html и выполнить следующий пример сценария из командной строки:

./phantomjs ../examples/rasterize.js http://www.panoramio.com/photo/76188108 test.jpg 

Это создаст скриншот данной страницы в файле JPEG. Потенциал этого подхода заключается в том, что вы не полагаетесь на какого-либо внешнего поставщика и можете легко автоматизировать съемку снимков в больших количествах.

+0

+1 Также, будучи Webkit, вы знаете, что это хорошо показывает современные веб-страницы. –

+0

Довольно замечательный инструмент, но он не отображает мою страницу очень хорошо, у нее много jquery и slickgrid. –

+0

Хммм. аналогично тому, что вы получаете с любым другим браузером Webkit –

1

Я использовал WebBrowser, и он не работает идеально для меня, особенно когда нужно ждать завершения JavaScript. Я пробовал некоторые Api (ы) и нашел Selenium, самое главное в Selenium, это не требует STAThread и может работать в простом консольном приложении, а также в сервисах.

дать ему попробовать:

class Program 
{ 
    static void Main() 
    { 
     var driver = new FirefoxDriver(); 

     driver.Navigate() 
      .GoToUrl("http://stackoverflow.com/"); 

     driver.GetScreenshot() 
      .SaveAsFile("stackoverflow.jpg", ImageFormat.Jpeg); 

     driver.Quit(); 
    } 
} 
+0

Расширение WebDriver должно быть установлено, тогда только он будет работать. – jkyadav

11

Этот вопрос стар, но, в качестве альтернативы, вы можете использовать NuGet пакет Freezer. Это бесплатно, использует недавний веб-браузер Gecko (поддерживает HTML5 и CSS3) и стоит только в одной DLL.

var screenshotJob = ScreenshotJobBuilder.Create("https://google.com") 
       .SetBrowserSize(1366, 768) 
       .SetCaptureZone(CaptureZone.FullPage) 
       .SetTrigger(new WindowLoadTrigger()); 

System.Drawing.Image screenshot = screenshotJob.Freeze(); 
+0

Может ли он работать с сервисом Windows для сохранения – Silver

+0

Это лучшее решение! –

+0

Работало отлично для меня! –