Obtenir par programme une capture d’écran d’une page

J’écris un robot et un parsingur spécialisés pour un usage interne, et j’ai besoin de la possibilité de prendre une capture d’écran d’une page Web afin de vérifier quelles couleurs sont utilisées. Le programme prendra en charge une dizaine d’adresses Web et les enregistrera sous forme d’image bitmap.

A partir de là, je prévois d’utiliser LockBits pour créer une liste des cinq couleurs les plus utilisées dans l’image. À ma connaissance, c’est le moyen le plus simple d’obtenir les couleurs utilisées dans une page Web, mais s’il existe un moyen plus simple de le faire, veuillez répondre à vos suggestions.

Quoi qu’il en soit, j’allais utiliser le contrôle ActiveX ACA WebThumb jusqu’à ce que je voie le prix. Je suis aussi assez nouveau en C #, ne l’ayant utilisé que depuis quelques mois. Existe-t-il une solution à mon problème consistant à prendre une capture d’écran d’une page Web afin d’extraire le schéma de couleurs?

https://www.url2png.com/docs est un bon exemple. Ils ont un niveau gratuit.

Vous devrez utiliser HttpWebRequest pour télécharger le binary de l’image. Voici un exemple:

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... 

Pour générer l’URL …

 public static ssortingng url2png(ssortingng UrlToSite) { ssortingng url2pngAPIKey = "PXXX"; ssortingng url2pngPrivateKey = "SXXX"; ssortingng url = HttpUtility.UrlEncode(UrlToSite); ssortingng getssortingng = "fullpage=true&url=" + url; ssortingng SecurityHash_url2png = Md5HashPHPCompliant(url2pngPrivateKey + "+" + getssortingng).ToLower(); var url2pngLink = "http://api.url2png.com/v6/" + url2pngAPIKey + "/" + SecurityHash_url2png + "/" + "png/?" + getssortingng; return url2pngLink; } public static ssortingng Md5HashPHPCompliant(ssortingng pass) { System.Security.Cryptography.MD5CryptoServiceProvider md5 = new System.Security.Cryptography.MD5CryptoServiceProvider(); byte[] dataMd5 = md5.ComputeHash(Encoding.UTF8.GetBytes(pass)); SsortingngBuilder sb = new SsortingngBuilder(); for (int i = 0; i <= dataMd5.Length - 1; i++) { sb.AppendFormat("{0:x2}", dataMd5[i]); } return sb.ToString(); } 

Un moyen rapide et sale consisterait à utiliser le contrôle WinForms WebBrowser et à le dessiner sur un bitmap. Faire cela dans une application de console autonome est légèrement compliqué car vous devez être conscient des implications de l’hébergement d’un contrôle STAThread tout en utilisant un modèle de programmation fondamentalement asynchrone. Mais voici une preuve de concept de travail qui capture une page Web dans un fichier BMP 800×600:

 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(); } } } 

Pour comstackr cela, créez une nouvelle application console et assurez-vous d’append des références d’assembly pour System.Drawing et System.Windows.Forms .

MISE À JOUR: J’ai réécrit le code pour ne pas avoir à utiliser le modèle WaitOne / DoEvents. Ce code devrait être plus proche des meilleures pratiques à suivre.

MISE À JOUR 2: Vous indiquez que vous souhaitez utiliser cela dans une application Windows Forms. Dans ce cas, oubliez la création dynamic du contrôle WebBrowser . Ce que vous voulez, c’est créer une instance masquée (Visible = false) d’un WebBrowser sur votre formulaire et l’utiliser de la même manière que ci-dessus. Voici un autre exemple qui montre la partie de code utilisateur d’un formulaire avec une zone de texte ( webAddressTextBox ), un bouton ( generateScreenshotButton ) et un navigateur caché ( webBrowser ). Pendant que je travaillais là-dessus, j’ai découvert une particularité que je ne maîsortingsais pas auparavant: l’événement DocumentCompleted peut en fait être déclenché plusieurs fois en fonction de la nature de la page. Cet exemple devrait fonctionner en général, et vous pouvez l’étendre pour faire ce que vous voulez:

 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; ssortingng webAddressSsortingng = this.webAddressTextBox.Text; Uri webAddress; if (Uri.TryCreate(webAddressSsortingng, 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 ssortingng 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(ssortingng 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); } } } } 

Cette question est ancienne, mais vous pouvez également utiliser nuget package Freezer . C’est gratuit, il utilise un navigateur Web Gecko récent (compatible HTML5 et CSS3) et ne contient qu’une seule DLL.

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

Il existe un excellent navigateur basé sur Webkit, PhantomJS, qui permet d’exécuter tout code JavaScript à partir de la ligne de commande.

Installez-le à partir de http://phantomjs.org/download.html et exécutez l’exemple de script suivant à partir de la ligne de commande:

 ./phantomjs ../examples/rasterize.js http://soffr.miximages.com/c%23/76188108 test.jpg 

Il va créer une capture d’écran de la page donnée dans le fichier JPEG. L’avantage de cette approche réside dans le fait que vous ne dépendez d’aucun fournisseur externe et que vous pouvez facilement automatiser les captures d’écran en grande quantité.

Vérifiez ceci . Cela semble faire ce que vous vouliez et techniquement, il aborde le problème de manière très similaire grâce au contrôle du navigateur Web. Il semble avoir pris en compte une gamme de parameters à transmettre et une bonne gestion des erreurs. Le seul inconvénient est que c’est un processus externe (exe) que vous générez et qu’il crée un fichier physique que vous allez lire plus tard. D’après votre description, vous considérez même les services Web, donc je ne pense pas que ce soit un problème.

En résolvant votre dernier commentaire sur la manière de traiter plusieurs d’entre eux simultanément, cela sera parfait. Vous pouvez générer un parallèle de 3, 4, 5 processus ou plus à la fois ou faire parsingr le bit de couleur en tant que thread pendant qu’un autre processus de capture est en cours.

Pour le traitement de l’image, j’ai récemment rencontré Emgu , je ne l’ ai pas utilisé moi-même, mais cela semble fascinant. Il se veut rapide et supporte beaucoup l’parsing graphique, y compris la lecture de la couleur des pixels. Si j’ai un projet de traitement graphique en main, je vais essayer.

Vous pouvez également consulter QT jambi http://qt.nokia.com/doc/qtjambi-4.4/html/com/trolltech/qt/qtjambi-index.html

ils ont une belle implémentation java basée sur un webkit pour un navigateur où vous pouvez faire une capture d’écran simplement en faisant ce qui suit:

  QPixmap pixmap; pixmap = QPixmap.grabWidget(browser); pixmap.save(writeTo, "png"); 

Jetez un oeil sur les échantillons – ils ont une belle démonstration de navigateur Web.

J’ai utilisé WebBrowser et cela ne fonctionne pas parfaitement pour moi, en particulier lorsqu’il faut attendre que le rendu JavaScript soit complet. J’ai essayé quelques Api (s) et trouvé Selenium , la chose la plus importante à propos de Selenium est, il ne nécessite pas STAThread et pourrait fonctionner dans une application console simple ainsi que des services.

Essaie :

 class Program { static void Main() { var driver = new FirefoxDriver(); driver.Navigate() .GoToUrl("http://soffr.miximages.com/c%23/); driver.GetScreenshot() .SaveAsFile(stackoverflow.jpg", ImageFormat.Jpeg); driver.Quit(); } }