Cómo extraer datos de sitios web en C#

por Ahmed Aboelmagd

IronWebscraper es una librería .NET para web scraping, extracción de datos web y análisis de contenido web. Se trata de una biblioteca fácil de usar que puede añadirse a los proyectos de Microsoft Visual Studio para su uso en desarrollo y producción.

IronWebscraper tiene un montón de características únicas y capacidades tales como el control de páginas permitidas y prohibidas, objetos, medios de comunicación, etc. También permite la gestión de múltiples identidades, caché web, y un montón de otras características que vamos a cubrir en este tutorial.

Público destinatario

Este tutorial está dirigido a desarrolladores de software con conocimientos básicos o avanzados de programación, que deseen construir e implementar soluciones para capacidades avanzadas de scraping (raspado de sitios web, recopilación y extracción de datos de sitios web, análisis sintáctico de contenidos de sitios web, recolección de datos de sitios web).

Webscraping nunca ha sido una tarea sencilla, sin frameworks dominantes para su uso en entornos de programación C# o .NET. Iron Web Scraper fue creado para cambiar esto

Competencias requeridas

  1. Fundamentos básicos de programación con conocimientos de uno de los lenguajes de programación de Microsoft, como C# o VB.NET.
  2. Conocimientos básicos de tecnologías web (HTML, JavaScript, JQuery, CSS, etc.) y cómo funcionan
  3. Conocimientos básicos de DOM, XPath, HTML y selectores CSS

Herramientas

  1. Microsoft Visual Studio 2010 o superior
  2. Extensiones de desarrollador web para navegadores como web inspector para Chrome o Firebug para Firefox

¿Por qué rascar?

(Razones y conceptos)

Si quiere crear un producto o una solución que tenga la capacidad de:

  1. Extraer datos del sitio web
  2. Compare contenidos, precios, características, etc. de varios sitios web
  3. Escaneado y almacenamiento en caché del contenido de los sitios web

    Si usted tiene una o más razones de las anteriores, entonces IronWebscraper es una gran biblioteca para satisfacer sus necesidades

¿Cómo instalar IronWebScraper?

Biblioteca NuGet C# para

Instalar con NuGet

Install-Package IronWebScraper
o
Java PDF JAR

Descargar DLL

Descargar DLL

Instalar manualmente en su proyecto

Después de crear un nuevo proyecto (Véase el Apéndice A) puedes añadir la librería IronWebScraper a tu proyecto insertando automáticamente la librería usando NuGet o instalando manualmente la DLL.

Instalación con NuGet

Para añadir la librería IronWebScraper a nuestro proyecto usando NuGet podemos hacerlo usando la interfaz visual (Gestor de paquetes NuGet) o por comando utilizando la Consola del Gestor de Paquetes.

Uso del gestor de paquetes NuGet

  1. Con el ratón -> click derecho sobre el nombre del proyecto -> Seleccionar gestionar paquete NuGet

  2. Desde la pestaña Examinar -> busque IronWebScraper -> Instalar

  3. Haga clic en Ok

  4. Y hemos terminado

Uso de la consola de paquetes NuGet

  1. Desde herramientas -> Gestor de paquetes NuGet -> Consola del Gestor de paquetes

  2. Seleccione el proyecto de biblioteca de clases como proyecto por defecto
  3. Ejecutar comando -> Install-Package IronWebScraper

Instalación manual

  1. Ir a ironsoftware.com
  2. Haga clic en IronWebScraper o visite su página directamente utilizando la URL https://ironsoftware.com/csharp/webscraper
  3. Haga clic en Descargar DLL.
  4. Extraer el archivo comprimido descargado
  5. En visual studio click derecho en proyecto -> añadir -> referencia -> examinar

  6. Vaya a la carpeta extraída -> netstandard2.0 -> y seleccione Todos los archivos .dll.

  7. Y está hecho!

HelloScraper - Nuestra primera muestra de IronWebScraper

Como de costumbre, comenzaremos implementando la App Hello Scraper para dar nuestro primer paso utilizando IronWebScraper.

  • Hemos creado una nueva aplicación de consola con el nombre "IronWebScraperSample".

    Pasos para crear IronWebScraper Sample

  1. Cree una carpeta y nómbrela "HelloScraperSample".
  2. A continuación, una nueva clase y el nombre "HelloScraper"

  3. Añada este fragmento de código a HelloScraper
public class HelloScraper : WebScraper
{
        /// <summary>
        /// Anula este método para inicializar tu web-scraper.
        /// Tareas importantes serán Solicitar al menos una url de inicio... y establecer patrones de dominios o urls permitidos/prohibidos.
        /// </summary>
        public override void Init()
        {
            License.LicenseKey = "LicenseKey"; //  Escribir clave de licencia
            this.LoggingLevel = WebScraper.LogLevel.All; //  Todos los eventos se registran
            this.Request("https://blog.scrapinghub.com", Parse);
        }

        /// <summary>
        /// Sustituya este método para crear el manejador de respuesta predeterminado para su raspador web.
        /// Si tiene varios tipos de página, puede añadir métodos similares adicionales.
        /// </summary>
        /// <param name="response">The http Response object to parse</param>
        public override void Parse(Response response)
        {
            //  establecer el directorio de trabajo para el proyecto
            this.WorkingDirectory = AppSetting.GetAppRoot()+ @"\HelloScraperSample\Output\";
            //  Bucle en todos los enlaces
            foreach (var title_link in response.Css("h2.entry-title a"))
            {
                //  Leer el texto del enlace
                string strTitle = title_link.TextContentClean;
                //  Guardar resultado en archivo
                Scrape(new ScrapedData() { { "Title", strTitle } }, "HelloScraper.json");
            }
            //  Bucle en todos los enlaces
            if (response.CssExists("div.prev-post > a [href]"))
            {
                //  Obtener URL del enlace
                var next_page = response.Css("div.prev-post > a [href]")[0].Attributes ["href"];
                //  Raspar URL siguiente
                this.Request(next_page, Parse);
            }
        }
}
public class HelloScraper : WebScraper
{
        /// <summary>
        /// Anula este método para inicializar tu web-scraper.
        /// Tareas importantes serán Solicitar al menos una url de inicio... y establecer patrones de dominios o urls permitidos/prohibidos.
        /// </summary>
        public override void Init()
        {
            License.LicenseKey = "LicenseKey"; //  Escribir clave de licencia
            this.LoggingLevel = WebScraper.LogLevel.All; //  Todos los eventos se registran
            this.Request("https://blog.scrapinghub.com", Parse);
        }

        /// <summary>
        /// Sustituya este método para crear el manejador de respuesta predeterminado para su raspador web.
        /// Si tiene varios tipos de página, puede añadir métodos similares adicionales.
        /// </summary>
        /// <param name="response">The http Response object to parse</param>
        public override void Parse(Response response)
        {
            //  establecer el directorio de trabajo para el proyecto
            this.WorkingDirectory = AppSetting.GetAppRoot()+ @"\HelloScraperSample\Output\";
            //  Bucle en todos los enlaces
            foreach (var title_link in response.Css("h2.entry-title a"))
            {
                //  Leer el texto del enlace
                string strTitle = title_link.TextContentClean;
                //  Guardar resultado en archivo
                Scrape(new ScrapedData() { { "Title", strTitle } }, "HelloScraper.json");
            }
            //  Bucle en todos los enlaces
            if (response.CssExists("div.prev-post > a [href]"))
            {
                //  Obtener URL del enlace
                var next_page = response.Css("div.prev-post > a [href]")[0].Attributes ["href"];
                //  Raspar URL siguiente
                this.Request(next_page, Parse);
            }
        }
}
Public Class HelloScraper
	Inherits WebScraper

		''' <summary>
		''' Anula este método para inicializar tu web-scraper.
		''' Tareas importantes serán Solicitar al menos una url de inicio... y establecer patrones de dominios o urls permitidos/prohibidos.
		''' </summary>
		Public Overrides Sub Init()
			License.LicenseKey = "LicenseKey" '  Escribir clave de licencia
			Me.LoggingLevel = WebScraper.LogLevel.All '  Todos los eventos se registran
			Me.Request("https://blog.scrapinghub.com", AddressOf Parse)
		End Sub

		''' <summary>
		''' Sustituya este método para crear el manejador de respuesta predeterminado para su raspador web.
		''' Si tiene varios tipos de página, puede añadir métodos similares adicionales.
		''' </summary>
		''' <param name="response">The http Response object to parse</param>
		Public Overrides Sub Parse(ByVal response As Response)
			'  establecer el directorio de trabajo para el proyecto
			Me.WorkingDirectory = AppSetting.GetAppRoot() & "\HelloScraperSample\Output\"
			'  Bucle en todos los enlaces
			For Each title_link In response.Css("h2.entry-title a")
				'  Leer el texto del enlace
				Dim strTitle As String = title_link.TextContentClean
				'  Guardar resultado en archivo
				Scrape(New ScrapedData() From {
					{ "Title", strTitle }
				},
				"HelloScraper.json")
			Next title_link
			'  Bucle en todos los enlaces
			If response.CssExists("div.prev-post > a [href]") Then
				'  Obtener URL del enlace
				Dim next_page = response.Css("div.prev-post > a [href]")(0).Attributes ("href")
				'  Raspar URL siguiente
				Me.Request(next_page, AddressOf Parse)
			End If
		End Sub
End Class
VB   C#
  1. Ahora para empezar Scrape Añadir este fragmento de código a la principal
static void Main(string [] args)
{
        //  Crear objeto a partir de la clase Hello Scrape
        HelloScraperSample.HelloScraper scrape = new HelloScraperSample.HelloScraper();
            //  Empezar a raspar
            scrape.Start();
}
static void Main(string [] args)
{
        //  Crear objeto a partir de la clase Hello Scrape
        HelloScraperSample.HelloScraper scrape = new HelloScraperSample.HelloScraper();
            //  Empezar a raspar
            scrape.Start();
}
Shared Sub Main(ByVal args() As String)
		'  Crear objeto a partir de la clase Hello Scrape
		Dim scrape As New HelloScraperSample.HelloScraper()
			'  Empezar a raspar
			scrape.Start()
End Sub
VB   C#
  1. El resultado se guardará en un archivo con el formato WebSraper.WorkingDirecty/nombreclase.Json

Visión general del código

Scrape.Start() => dispara la lógica de raspado como sigue:

  1. Llamar al Init() Método primero para iniciar las variables, propiedades de raspado y atributos de comportamiento.,
  2. Como podemos ver, establece la página de inicio en Request("https://blog.scrapinghub.com", Parse) y Parse (Respuesta) definido para ser el proceso que se utiliza para analizar la respuesta.
  3. Webscraper gestiona en paralelo: http e hilos... manteniendo todo su código fácil de depurar y síncrono.
  4. Inicio del método Parse después de Init() para analizar la página.
    1. Puede encontrar elementos utilizando (selectores Css, Js DOM, XPath)

    2. Los elementos seleccionados se asignan a la clase ScrapedData, puede asignarlos a cualquier clase personalizada (Producto, Empleado, Noticias, etc.).

    3. Los objetos guardados en un archivo con formato Json en el directorio ("bin/Scrape/"). O puede establecer la ruta del archivo como un parámetro como veremos más adelante en otros ejemplos.

Funciones y opciones de la biblioteca IronWebScraper

Puede encontrar documentación actualizada dentro del archivo zip que se descargó con el método de instalación manual (Archivo IronWebScraper Documentation.chm)

O puede consultar la Documentación en línea para conocer la última actualización de la biblioteca en https://ironsoftware.com/csharp/webscraper/object-reference/

Para empezar a utilizar IronWebscraper en su proyecto debe heredar de (IronWebScraper.WebScraper) que amplía su biblioteca de clases y le añade la funcionalidad de scraping.

También debe aplicar {Init()Parse(Respuesta)} métodos.

namespace IronWebScraperEngine
{
    public class NewsScraper : IronWebScraper.WebScraper
    {
        public override void Init()
        {
            throw new NotImplementedException();
        }

        public override void Parse(Response response)
        {
            throw new NotImplementedException();
        }
    }
}
namespace IronWebScraperEngine
{
    public class NewsScraper : IronWebScraper.WebScraper
    {
        public override void Init()
        {
            throw new NotImplementedException();
        }

        public override void Parse(Response response)
        {
            throw new NotImplementedException();
        }
    }
}
Namespace IronWebScraperEngine
	Public Class NewsScraper
		Inherits IronWebScraper.WebScraper

		Public Overrides Sub Init()
			Throw New NotImplementedException()
		End Sub

		Public Overrides Sub Parse(ByVal response As Response)
			Throw New NotImplementedException()
		End Sub
	End Class
End Namespace
VB   C#
Propiedades \ funcionesTipoDescripción
Init ()Métodoutilizado para configurar el rascador
Parse (Respuesta respuesta)MétodoSe utiliza para implementar la lógica que utilizará el scraper y cómo la procesará.
La siguiente tabla contiene una lista de métodos y propiedades que proporciona la librería IronWebScraper
NOTA : Puede implementar múltiples métodos para diferentes comportamientos o estructuras de páginas
  • BannedUrls
  • AllowedUrls
  • BannedDomains
ColeccionesSe utiliza para prohibir/permitir/ URLs Y/O Dominios
Ej: BannedUrls.Add ("*.zip", "*.exe", "*.gz", "*.pdf");
Nota:
  • Puede utilizar comodines ( * y/o ? )
  • Puede utilizar cadenas y expresiones regulares
  • URLsProhibidas, URLsPermitidas, DominiosProhibidos, DominiosPermitidos
  • BannedUrls.Add ("*.zip", "*.exe", "*.gz", "*.pdf");
  • *Comodines de venta glob
  • cadenas y expresiones regulares
  • puede sobrescribir este comportamiento sobrescribiendo el método: public virtual bool AcceptUrl (string url)
ObeyRobotsDotTxtBooleanooSe utiliza para activar o desactivar leer y seguir robots.txt su directiva o no
public override bool ObeyRobotsDotTxtForHost (string Host)MétodoSe utiliza para activar o desactivar leer y seguir robots.txt su directiva o no for certain domain
RasparMétodo
RasparUniqueMétodo
ThrottleModeEnumeración
ActivarWebCache ()Método
EnableWebCache (TimeSpan cacheDuration)Método
MaxHttpConnectionLimitInt
RateLimitPerHostTimeSpan
OpenConnectionLimitPerHostInt
ObeyRobotsDotTxtBooleanoo
ThrottleModeEnumOpciones Enum:
  • Dirección IP
  • ByDomainHostName
SetSiteSpecificCrawlRateLimit (cadena hostName, TimeSpan crawlRate)Método
IdentidadesColeccionesUna lista de HttpIdentity () que se utilizarán para obtener recursos web.

Cada identidad puede tener una dirección IP proxy, un agente de usuario, encabezados http, cookies persistentes, nombre de usuario y contraseña diferentes.
Best practice is to create Identidades in your WebScraper.Init Método and Add Them to this WebScraper.Identidades List.
DirectorioDeTrabajocadenaEstablecer el directorio de trabajo que se utilizará para todos los datos relacionados con scrape se almacenará en el disco.


Ejemplos y prácticas del mundo real

Raspado de un sitio web de películas en línea

Empecemos con otro ejemplo de un sitio web del mundo real. Vamos a elegir para raspar un sitio web de películas.

Añadamos una nueva clase y llamémosla "MovieScraper":

Ahora vamos a echar un vistazo en el sitio que vamos a raspar:

Esto forma parte del HTML de la página de inicio que vemos en el sitio web:

<div id="movie-featured" class="movies-list movies-list-full tab-pane in fade active">
    <div data-movie-id="20746" class="ml-item">
        <a href="https://website.com/film/king-arthur-legend-of-the-sword-20746/">
            <span class="mli-quality">CAM</span>
            <img data-original="https://img.gocdn.online/2017/05/16/poster/2116d6719c710eabe83b377463230fbe-king-arthur-legend-of-the-sword.jpg" 
                 class="lazy thumb mli-thumb" alt="King Arthur: Legend of the Sword"
                  src="https://img.gocdn.online/2017/05/16/poster/2116d6719c710eabe83b377463230fbe-king-arthur-legend-of-the-sword.jpg" 
                 style="display: inline-block;">
            <span class="mli-info"><h2>King Arthur: Legend of the Sword</h2></span>
        </a>
    </div>
    <div data-movie-id="20724" class="ml-item">
        <a href="https://website.com/film/snatched-20724/" >
            <span class="mli-quality">CAM</span>
            <img data-original="https://img.gocdn.online/2017/05/16/poster/5ef66403dc331009bdb5aa37cfe819ba-snatched.jpg" 
                 class="lazy thumb mli-thumb" alt="Snatched" 
                 src="https://img.gocdn.online/2017/05/16/poster/5ef66403dc331009bdb5aa37cfe819ba-snatched.jpg" 
                 style="display: inline-block;">
            <span class="mli-info"><h2>Snatched</h2></span>
        </a>
    </div>
</div>
<div id="movie-featured" class="movies-list movies-list-full tab-pane in fade active">
    <div data-movie-id="20746" class="ml-item">
        <a href="https://website.com/film/king-arthur-legend-of-the-sword-20746/">
            <span class="mli-quality">CAM</span>
            <img data-original="https://img.gocdn.online/2017/05/16/poster/2116d6719c710eabe83b377463230fbe-king-arthur-legend-of-the-sword.jpg" 
                 class="lazy thumb mli-thumb" alt="King Arthur: Legend of the Sword"
                  src="https://img.gocdn.online/2017/05/16/poster/2116d6719c710eabe83b377463230fbe-king-arthur-legend-of-the-sword.jpg" 
                 style="display: inline-block;">
            <span class="mli-info"><h2>King Arthur: Legend of the Sword</h2></span>
        </a>
    </div>
    <div data-movie-id="20724" class="ml-item">
        <a href="https://website.com/film/snatched-20724/" >
            <span class="mli-quality">CAM</span>
            <img data-original="https://img.gocdn.online/2017/05/16/poster/5ef66403dc331009bdb5aa37cfe819ba-snatched.jpg" 
                 class="lazy thumb mli-thumb" alt="Snatched" 
                 src="https://img.gocdn.online/2017/05/16/poster/5ef66403dc331009bdb5aa37cfe819ba-snatched.jpg" 
                 style="display: inline-block;">
            <span class="mli-info"><h2>Snatched</h2></span>
        </a>
    </div>
</div>
HTML

Como podemos ver, tenemos el ID de la película, el Título y el Enlace a la página detallada.

Empecemos a raspar este conjunto de datos:

public class MovieScraper : WebScraper
{
    public override void Init()
    {
        License.LicenseKey = "LicenseKey";
        this.LoggingLevel = WebScraper.LogLevel.All;
        this.WorkingDirectory = AppSetting.GetAppRoot() + @"\MovieSample\Output\";
        this.Request("www.website.com", Parse);
    }
    public override void Parse(Response response)
    {
        foreach (var Divs in response.Css("#movie-featured > div"))
        {
            if (Divs.Attributes ["class"] != "clearfix")
            {
                var MovieId = Divs.GetAttribute("data-movie-id");
                var link = Divs.Css("a")[0];
                var MovieTitle = link.TextContentClean;
                Scrape(new ScrapedData() { { "MovieId", MovieId }, { "MovieTitle", MovieTitle } }, "Movie.Jsonl");
            }
        }           
    }
}
public class MovieScraper : WebScraper
{
    public override void Init()
    {
        License.LicenseKey = "LicenseKey";
        this.LoggingLevel = WebScraper.LogLevel.All;
        this.WorkingDirectory = AppSetting.GetAppRoot() + @"\MovieSample\Output\";
        this.Request("www.website.com", Parse);
    }
    public override void Parse(Response response)
    {
        foreach (var Divs in response.Css("#movie-featured > div"))
        {
            if (Divs.Attributes ["class"] != "clearfix")
            {
                var MovieId = Divs.GetAttribute("data-movie-id");
                var link = Divs.Css("a")[0];
                var MovieTitle = link.TextContentClean;
                Scrape(new ScrapedData() { { "MovieId", MovieId }, { "MovieTitle", MovieTitle } }, "Movie.Jsonl");
            }
        }           
    }
}
Public Class MovieScraper
	Inherits WebScraper

	Public Overrides Sub Init()
		License.LicenseKey = "LicenseKey"
		Me.LoggingLevel = WebScraper.LogLevel.All
		Me.WorkingDirectory = AppSetting.GetAppRoot() & "\MovieSample\Output\"
		Me.Request("www.website.com", AddressOf Parse)
	End Sub
	Public Overrides Sub Parse(ByVal response As Response)
		For Each Divs In response.Css("#movie-featured > div")
			If Divs.Attributes ("class") <> "clearfix" Then
				Dim MovieId = Divs.GetAttribute("data-movie-id")
				Dim link = Divs.Css("a")(0)
				Dim MovieTitle = link.TextContentClean
				Scrape(New ScrapedData() From {
					{ "MovieId", MovieId },
					{ "MovieTitle", MovieTitle }
				},
				"Movie.Jsonl")
			End If
		Next Divs
	End Sub
End Class
VB   C#

¿Qué hay de nuevo en este código?

La propiedad Directorio de trabajo se utiliza para establecer el directorio de trabajo principal para todos los datos raspados y sus archivos relacionados.

Hagamos más.

¿Y si necesitamos construir objetos tipados que contengan datos raspados en objetos formateados?

Vamos a implementar una clase de película que contendrá nuestros datos formateados:

public class Movie
{
    public int Id { get; set; }
    public string Title { get; set; }
    public string URL { get; set; }

}
public class Movie
{
    public int Id { get; set; }
    public string Title { get; set; }
    public string URL { get; set; }

}
Public Class Movie
	Public Property Id() As Integer
	Public Property Title() As String
	Public Property URL() As String

End Class
VB   C#

Ahora actualizaremos nuestro código:

public class MovieScraper : WebScraper
{
    public override void Init()
    {
        License.LicenseKey = "LicenseKey";
        this.LoggingLevel = WebScraper.LogLevel.All;
        this.WorkingDirectory = AppSetting.GetAppRoot() + @"\MovieSample\Output\";
        this.Request("https://website.com/", Parse);
    }
    public override void Parse(Response response)
    {
        foreach (var Divs in response.Css("#movie-featured > div"))
        {
            if (Divs.Attributes ["class"] != "clearfix")
            {
                var movie = new Movie();
                movie.Id = Convert.ToInt32( Divs.GetAttribute("data-movie-id"));
                var link = Divs.Css("a")[0];
                movie.Title = link.TextContentClean;
                movie.URL = link.Attributes ["href"];
                Scrape(movie, "Movie.Jsonl");
            }
        }
    }
}
public class MovieScraper : WebScraper
{
    public override void Init()
    {
        License.LicenseKey = "LicenseKey";
        this.LoggingLevel = WebScraper.LogLevel.All;
        this.WorkingDirectory = AppSetting.GetAppRoot() + @"\MovieSample\Output\";
        this.Request("https://website.com/", Parse);
    }
    public override void Parse(Response response)
    {
        foreach (var Divs in response.Css("#movie-featured > div"))
        {
            if (Divs.Attributes ["class"] != "clearfix")
            {
                var movie = new Movie();
                movie.Id = Convert.ToInt32( Divs.GetAttribute("data-movie-id"));
                var link = Divs.Css("a")[0];
                movie.Title = link.TextContentClean;
                movie.URL = link.Attributes ["href"];
                Scrape(movie, "Movie.Jsonl");
            }
        }
    }
}
Public Class MovieScraper
	Inherits WebScraper

	Public Overrides Sub Init()
		License.LicenseKey = "LicenseKey"
		Me.LoggingLevel = WebScraper.LogLevel.All
		Me.WorkingDirectory = AppSetting.GetAppRoot() & "\MovieSample\Output\"
		Me.Request("https://website.com/", AddressOf Parse)
	End Sub
	Public Overrides Sub Parse(ByVal response As Response)
		For Each Divs In response.Css("#movie-featured > div")
			If Divs.Attributes ("class") <> "clearfix" Then
				Dim movie As New Movie()
				movie.Id = Convert.ToInt32(Divs.GetAttribute("data-movie-id"))
				Dim link = Divs.Css("a")(0)
				movie.Title = link.TextContentClean
				movie.URL = link.Attributes ("href")
				Scrape(movie, "Movie.Jsonl")
			End If
		Next Divs
	End Sub
End Class
VB   C#

¿Qué hay de nuevo?

  1. Implementamos Movie Class para mantener nuestros datos raspados
  2. Pasamos objetos de película al método Scrape y este entiende nuestro formato y guarda en un formato definido como podemos ver aquí:

    Empecemos a raspar una página más detallada.

La página de películas tiene este aspecto:

<div class="mvi-content">
    <div class="thumb mvic-thumb"
         style="background-image: url(https://img.gocdn.online/2017/04/28/poster/5a08e94ba02118f22dc30f298c603210-guardians-of-the-galaxy-vol-2.jpg);"></div>
    <div class="mvic-desc">
        <h3>Guardians of the Galaxy Vol. 2</h3>        
        <div class="desc">
            Set to the backdrop of Awesome Mixtape #2, Marvel's Guardians of the Galaxy Vol. 2 continues the team's adventures as they travel throughout the cosmos to help Peter Quill learn more about his true parentage.
        </div>
        <div class="mvic-info">
            <div class="mvici-left">
                <p>
                    <strong>Genre: </strong>
                    <a href="https://Domain/genre/action/" title="Action">Action</a>,
                    <a href="https://Domain/genre/adventure/" title="Adventure">Adventure</a>,
                    <a href="https://Domain/genre/sci-fi/" title="Sci-Fi">Sci-Fi</a>
                </p>
                <p>
                    <strong>Actor: </strong>
                    <a target="_blank" href="https://Domain/actor/chris-pratt" title="Chris Pratt">Chris Pratt</a>,
                    <a target="_blank" href="https://Domain/actor/-zoe-saldana" title="Zoe Saldana">Zoe Saldana</a>,
                    <a target="_blank" href="https://Domain/actor/-dave-bautista-" title="Dave Bautista">Dave Bautista</a>
                </p>
                <p>
                    <strong>Director: </strong>
                    <a href="#" title="James Gunn">James Gunn</a>
                </p>
                <p>
                    <strong>Country: </strong>
                    <a href="https://Domain/country/us" title="United States">United States</a>
                </p>
            </div>
            <div class="mvici-right">
                <p><strong>Duration:</strong> 136 min</p>
                <p><strong>Quality:</strong> <span class="quality">CAM</span></p>
                <p><strong>Release:</strong> 2017</p>
                <p><strong>IMDb:</strong> 8.3</p>
            </div>
            <div class="clearfix"></div>
        </div>
        <div class="clearfix"></div>
    </div>
    <div class="clearfix"></div>
</div>
<div class="mvi-content">
    <div class="thumb mvic-thumb"
         style="background-image: url(https://img.gocdn.online/2017/04/28/poster/5a08e94ba02118f22dc30f298c603210-guardians-of-the-galaxy-vol-2.jpg);"></div>
    <div class="mvic-desc">
        <h3>Guardians of the Galaxy Vol. 2</h3>        
        <div class="desc">
            Set to the backdrop of Awesome Mixtape #2, Marvel's Guardians of the Galaxy Vol. 2 continues the team's adventures as they travel throughout the cosmos to help Peter Quill learn more about his true parentage.
        </div>
        <div class="mvic-info">
            <div class="mvici-left">
                <p>
                    <strong>Genre: </strong>
                    <a href="https://Domain/genre/action/" title="Action">Action</a>,
                    <a href="https://Domain/genre/adventure/" title="Adventure">Adventure</a>,
                    <a href="https://Domain/genre/sci-fi/" title="Sci-Fi">Sci-Fi</a>
                </p>
                <p>
                    <strong>Actor: </strong>
                    <a target="_blank" href="https://Domain/actor/chris-pratt" title="Chris Pratt">Chris Pratt</a>,
                    <a target="_blank" href="https://Domain/actor/-zoe-saldana" title="Zoe Saldana">Zoe Saldana</a>,
                    <a target="_blank" href="https://Domain/actor/-dave-bautista-" title="Dave Bautista">Dave Bautista</a>
                </p>
                <p>
                    <strong>Director: </strong>
                    <a href="#" title="James Gunn">James Gunn</a>
                </p>
                <p>
                    <strong>Country: </strong>
                    <a href="https://Domain/country/us" title="United States">United States</a>
                </p>
            </div>
            <div class="mvici-right">
                <p><strong>Duration:</strong> 136 min</p>
                <p><strong>Quality:</strong> <span class="quality">CAM</span></p>
                <p><strong>Release:</strong> 2017</p>
                <p><strong>IMDb:</strong> 8.3</p>
            </div>
            <div class="clearfix"></div>
        </div>
        <div class="clearfix"></div>
    </div>
    <div class="clearfix"></div>
</div>
HTML

Podemos ampliar nuestra clase movie con nuevas propiedades (Descripción, Género, Actor, Director, País, Duración, Puntuación IMDB) pero usaremos (Descripción, Género, Actor) sólo para nuestra muestra.

public class Movie
{
    public int Id { get; set; }
    public string Title { get; set; }
    public string URL { get; set; }
    public string Description { get; set; }
    public List<string> Genre { get; set; }
    public List<string> Actor { get; set; }

}
public class Movie
{
    public int Id { get; set; }
    public string Title { get; set; }
    public string URL { get; set; }
    public string Description { get; set; }
    public List<string> Genre { get; set; }
    public List<string> Actor { get; set; }

}
Public Class Movie
	Public Property Id() As Integer
	Public Property Title() As String
	Public Property URL() As String
	Public Property Description() As String
	Public Property Genre() As List(Of String)
	Public Property Actor() As List(Of String)

End Class
VB   C#

Ahora navegaremos a la página Detallada para rasparla.

IronWebScraper le permite añadir más a la función de raspado para raspar diferentes tipos de formatos de página

Como podemos ver aquí:

public class MovieScraper : WebScraper
{
    public override void Init()
    {
        License.LicenseKey = "LicenseKey";
        this.LoggingLevel = WebScraper.LogLevel.All;
        this.WorkingDirectory = AppSetting.GetAppRoot() + @"\MovieSample\Output\";
        this.Request("https://domain/", Parse);
    }
    public override void Parse(Response response)
    {
        foreach (var Divs in response.Css("#movie-featured > div"))
        {
            if (Divs.Attributes ["class"] != "clearfix")
            {
                var movie = new Movie();
                movie.Id = Convert.ToInt32( Divs.GetAttribute("data-movie-id"));
                var link = Divs.Css("a")[0];
                movie.Title = link.TextContentClean;
                movie.URL = link.Attributes ["href"];
                this.Request(movie.URL, ParseDetails, new MetaData() { { "movie", movie } });//  a la página detallada del desguace
            }
        }           
    }
    public void ParseDetails(Response response)
    {
        var movie = response.MetaData.Get<Movie>("movie");
        var Div = response.Css("div.mvic-desc")[0];
        movie.Description = Div.Css("div.desc")[0].TextContentClean;
        foreach(var Genre in Div.Css("div > p > a"))
        {
            movie.Genre.Add(Genre.TextContentClean);
        }
        foreach (var Actor in Div.Css("div > p:nth-child(2) > a"))
        {
            movie.Actor.Add(Actor.TextContentClean);
        }
        Scrape(movie, "Movie.Jsonl");
    }
}
public class MovieScraper : WebScraper
{
    public override void Init()
    {
        License.LicenseKey = "LicenseKey";
        this.LoggingLevel = WebScraper.LogLevel.All;
        this.WorkingDirectory = AppSetting.GetAppRoot() + @"\MovieSample\Output\";
        this.Request("https://domain/", Parse);
    }
    public override void Parse(Response response)
    {
        foreach (var Divs in response.Css("#movie-featured > div"))
        {
            if (Divs.Attributes ["class"] != "clearfix")
            {
                var movie = new Movie();
                movie.Id = Convert.ToInt32( Divs.GetAttribute("data-movie-id"));
                var link = Divs.Css("a")[0];
                movie.Title = link.TextContentClean;
                movie.URL = link.Attributes ["href"];
                this.Request(movie.URL, ParseDetails, new MetaData() { { "movie", movie } });//  a la página detallada del desguace
            }
        }           
    }
    public void ParseDetails(Response response)
    {
        var movie = response.MetaData.Get<Movie>("movie");
        var Div = response.Css("div.mvic-desc")[0];
        movie.Description = Div.Css("div.desc")[0].TextContentClean;
        foreach(var Genre in Div.Css("div > p > a"))
        {
            movie.Genre.Add(Genre.TextContentClean);
        }
        foreach (var Actor in Div.Css("div > p:nth-child(2) > a"))
        {
            movie.Actor.Add(Actor.TextContentClean);
        }
        Scrape(movie, "Movie.Jsonl");
    }
}
Public Class MovieScraper
	Inherits WebScraper

	Public Overrides Sub Init()
		License.LicenseKey = "LicenseKey"
		Me.LoggingLevel = WebScraper.LogLevel.All
		Me.WorkingDirectory = AppSetting.GetAppRoot() & "\MovieSample\Output\"
		Me.Request("https://domain/", AddressOf Parse)
	End Sub
	Public Overrides Sub Parse(ByVal response As Response)
		For Each Divs In response.Css("#movie-featured > div")
			If Divs.Attributes ("class") <> "clearfix" Then
				Dim movie As New Movie()
				movie.Id = Convert.ToInt32(Divs.GetAttribute("data-movie-id"))
				Dim link = Divs.Css("a")(0)
				movie.Title = link.TextContentClean
				movie.URL = link.Attributes ("href")
				Me.Request(movie.URL, AddressOf ParseDetails, New MetaData() From {
					{ "movie", movie }
				}) '  a la página detallada del desguace
			End If
		Next Divs
	End Sub
	Public Sub ParseDetails(ByVal response As Response)
		Dim movie = response.MetaData.Get(Of Movie)("movie")
		Dim Div = response.Css("div.mvic-desc")(0)
		movie.Description = Div.Css("div.desc")(0).TextContentClean
		For Each Genre In Div.Css("div > p > a")
			movie.Genre.Add(Genre.TextContentClean)
		Next Genre
		For Each Actor In Div.Css("div > p:nth-child(2) > a")
			movie.Actor.Add(Actor.TextContentClean)
		Next Actor
		Scrape(movie, "Movie.Jsonl")
	End Sub
End Class
VB   C#

¿Qué hay de nuevo?

  1. Podemos añadir funciones de raspado (ParseDetails) para raspar páginas detalladas
  2. Trasladamos la función Scrape que genera nuestro fichero a la nueva función
  3. Utilizamos la función IronWebScraper (MetaDatos) para pasar nuestro objeto de película a la nueva función scrape
  4. Raspamos la página y guardamos los datos de nuestros objetos de película en un archivo

Extraer contenido de un sitio web de compras

Seleccionamos un sitio de compras para raspar su contenido

Como se puede ver en la imagen, tenemos una barra izquierda que contiene enlaces para las categorías de productos del sitio

Así que nuestro primer paso es investigar el HTML del sitio y planificar cómo queremos rasparlo.

Las categorías de sitios de moda tienen subcategorías (Hombres, Mujeres, Niños)

<li class="menu-item" data-id="">
    <a href="https://dominio.es/moda-por-/" class="main-category">
        <i class="cat-icon osh-font-fashion"></i> <span class="nav-subTxt">FASHION </span> <i class="osh-font-light-arrow-left"></i><i class="osh-font-light-arrow-right"></i>
    </a> <div class="navLayerWrapper" style="width: 633px; display: none;"><div class="submenu"><div class="column"><div class="categories"><a class="category" href="https://domain.com/fashion-by-/?sort=newest&amp;dir=desc&amp;viewType=gridView3">New Arrivals !</a>  </div><div class="categories"><a class="category" href="https://domain.com/men-fashion/">Men</a>   <a class="subcategory" href="https://domain.com/mens-shoes/">Shoes</a>   <a class="subcategory" href="https://domain.com/mens-clothing/">Clothing</a>   <a class="subcategory" href="https://domain.com/mens-accessories/">Accessories</a>  </div><div class="categories"><a class="category" href="https://domain.com/women-fashion/">Women</a>   <a class="subcategory" href="https://domain.com/womens-shoes/">Shoes</a>   <a class="subcategory" href="https://domain.com/womens-clothing/">Clothing</a>   <a class="subcategory" href="https://domain.com/womens-accessories/">Accessories</a>  </div><div class="categories"><a class="category" href="https://domain.com/girls-boys-fashion/">Kids</a>   <a class="subcategory" href="https://domain.com/boys-fashion/">Boys</a>   <a class="subcategory" href="https://domain.com/girls/">Girls</a>  </div><div class="categories"><a class="category" href="https://domain.com/maternity-clothes/">Maternity Clothes</a>  </div></div><div class="column"><div class="categories"> <span class="category defaultCursor">Men Best Sellers</span>  <a class="subcategory" href="https://domain.com/mens-casual-shoes/">Casual Shoes</a>   <a class="subcategory" href="https://domain.com/mens-sneakers/">Sneakers</a>   <a class="subcategory" href="https://domain.com/mens-t-shirts/">T-shirts</a>   <a class="subcategory" href="https://domain.com/mens-polos/">Polos</a>  </div><div class="categories"> <span class="category defaultCursor">Women Best Sellers</span>  <a class="subcategory" href="https://domain.com/womens-sandals/">Sandals</a>   <a class="subcategory" href="https://domain.com/womens-sneakers/">Sneakers</a>   <a class="subcategory" href="https://domain.com/women-dresses/">Dresses</a>   <a class="subcategory" href="https://domain.com/women-tops/">Tops</a>  </div><div class="categories"><a class="category" href="https://domain.com/womens-curvy-clothing/">Women's Curvy Clothing</a>  </div><div class="categories"><a class="category" href="https://domain.com/fashion-bundles/v/">Fashion Bundles</a>  </div><div class="categories"><a class="category" href="https://domain.com/hijab-fashion/">Hijab Fashion</a>  </div></div><div class="column"><div class="categories"><a class="category" href="https://domain.com/brands/fashion-by-/">SEE ALL BRANDS</a>   <a class="subcategory" href="https://domain.com/adidas/">Adidas</a>   <a class="subcategory" href="https://domain.com/converse/">Converse</a>   <a class="subcategory" href="https://domain.com/ravin/">Ravin</a>   <a class="subcategory" href="https://domain.com/dejavu/">Dejavu</a>   <a class="subcategory" href="https://domain.com/agu/">Agu</a>   <a class="subcategory" href="https://domain.com/activ/">Activ</a>   <a class="subcategory" href="https://domain.com/oxford--bellini--tie-house--milano/">Tie House</a>   <a class="subcategory" href="https://domain.com/shoe-room/">Shoe Room</a>   <a class="subcategory" href="https://domain.com/town-team/">Town Team</a>  </div></div></div></div>
</li>
<li class="menu-item" data-id="">
    <a href="https://dominio.es/moda-por-/" class="main-category">
        <i class="cat-icon osh-font-fashion"></i> <span class="nav-subTxt">FASHION </span> <i class="osh-font-light-arrow-left"></i><i class="osh-font-light-arrow-right"></i>
    </a> <div class="navLayerWrapper" style="width: 633px; display: none;"><div class="submenu"><div class="column"><div class="categories"><a class="category" href="https://domain.com/fashion-by-/?sort=newest&amp;dir=desc&amp;viewType=gridView3">New Arrivals !</a>  </div><div class="categories"><a class="category" href="https://domain.com/men-fashion/">Men</a>   <a class="subcategory" href="https://domain.com/mens-shoes/">Shoes</a>   <a class="subcategory" href="https://domain.com/mens-clothing/">Clothing</a>   <a class="subcategory" href="https://domain.com/mens-accessories/">Accessories</a>  </div><div class="categories"><a class="category" href="https://domain.com/women-fashion/">Women</a>   <a class="subcategory" href="https://domain.com/womens-shoes/">Shoes</a>   <a class="subcategory" href="https://domain.com/womens-clothing/">Clothing</a>   <a class="subcategory" href="https://domain.com/womens-accessories/">Accessories</a>  </div><div class="categories"><a class="category" href="https://domain.com/girls-boys-fashion/">Kids</a>   <a class="subcategory" href="https://domain.com/boys-fashion/">Boys</a>   <a class="subcategory" href="https://domain.com/girls/">Girls</a>  </div><div class="categories"><a class="category" href="https://domain.com/maternity-clothes/">Maternity Clothes</a>  </div></div><div class="column"><div class="categories"> <span class="category defaultCursor">Men Best Sellers</span>  <a class="subcategory" href="https://domain.com/mens-casual-shoes/">Casual Shoes</a>   <a class="subcategory" href="https://domain.com/mens-sneakers/">Sneakers</a>   <a class="subcategory" href="https://domain.com/mens-t-shirts/">T-shirts</a>   <a class="subcategory" href="https://domain.com/mens-polos/">Polos</a>  </div><div class="categories"> <span class="category defaultCursor">Women Best Sellers</span>  <a class="subcategory" href="https://domain.com/womens-sandals/">Sandals</a>   <a class="subcategory" href="https://domain.com/womens-sneakers/">Sneakers</a>   <a class="subcategory" href="https://domain.com/women-dresses/">Dresses</a>   <a class="subcategory" href="https://domain.com/women-tops/">Tops</a>  </div><div class="categories"><a class="category" href="https://domain.com/womens-curvy-clothing/">Women's Curvy Clothing</a>  </div><div class="categories"><a class="category" href="https://domain.com/fashion-bundles/v/">Fashion Bundles</a>  </div><div class="categories"><a class="category" href="https://domain.com/hijab-fashion/">Hijab Fashion</a>  </div></div><div class="column"><div class="categories"><a class="category" href="https://domain.com/brands/fashion-by-/">SEE ALL BRANDS</a>   <a class="subcategory" href="https://domain.com/adidas/">Adidas</a>   <a class="subcategory" href="https://domain.com/converse/">Converse</a>   <a class="subcategory" href="https://domain.com/ravin/">Ravin</a>   <a class="subcategory" href="https://domain.com/dejavu/">Dejavu</a>   <a class="subcategory" href="https://domain.com/agu/">Agu</a>   <a class="subcategory" href="https://domain.com/activ/">Activ</a>   <a class="subcategory" href="https://domain.com/oxford--bellini--tie-house--milano/">Tie House</a>   <a class="subcategory" href="https://domain.com/shoe-room/">Shoe Room</a>   <a class="subcategory" href="https://domain.com/town-team/">Town Team</a>  </div></div></div></div>
</li>
HTML

Creemos un proyecto

  1. Cree una nueva aplicación de consola o añada una nueva carpeta para nuestra nueva muestra con el nombre "ShoppingSiteSample".
  2. Añadir nueva clase con el nombre "ShoppingScraper"
  3. El primer paso será raspar las categorías del sitio y sus subcategorías

    Vamos a crear un Modelo de Categorías:

public class Category
{
    /// <summary>
    /// Obtiene o establece el nombre.
    /// </summary>
    /// <value>
    /// El nombre.
    /// </value>
    public string Name { get; set; }
    /// <summary>
    /// Obtiene o establece la URL.
    /// </summary>
    /// <value>
    /// La URL.
    /// </value>
    public string URL { get; set; }
    /// <summary>
    /// Obtiene o establece las subcategorías.
    /// </summary>
    /// <value>
    /// Las subcategorías.
    /// </value>
    public List<Category> SubCategories { get; set; }
}
public class Category
{
    /// <summary>
    /// Obtiene o establece el nombre.
    /// </summary>
    /// <value>
    /// El nombre.
    /// </value>
    public string Name { get; set; }
    /// <summary>
    /// Obtiene o establece la URL.
    /// </summary>
    /// <value>
    /// La URL.
    /// </value>
    public string URL { get; set; }
    /// <summary>
    /// Obtiene o establece las subcategorías.
    /// </summary>
    /// <value>
    /// Las subcategorías.
    /// </value>
    public List<Category> SubCategories { get; set; }
}
IRON VB CONVERTER ERROR developers@ironsoftware.com
VB   C#
  1. Ahora vamos a construir nuestra lógica de raspado
public class ShoppingScraper : WebScraper
{
    /// <summary>
    /// Anula este método para inicializar tu web-scraper.
    /// Tareas importantes serán Solicitar al menos una url de inicio... y establecer patrones de dominios o urls permitidos/prohibidos.
    /// </summary>
    public override void Init()
    {
        License.LicenseKey = "LicenseKey";
        this.LoggingLevel = WebScraper.LogLevel.All;
        this.WorkingDirectory = AppSetting.GetAppRoot() + @"\ShoppingSiteSample\Output\";
        this.Request("www.webSite.com", Parse);
    }

    /// <summary>
    /// Sustituya este método para crear el manejador de respuesta predeterminado para su raspador web.
    /// Si tiene varios tipos de página, puede añadir métodos similares adicionales.
    /// </summary>
    /// <param name="response">The http Response object to parse</param>
    public override void Parse(Response response)
    {
        var categoryList = new List<Category>();

        foreach (var Links in response.Css("#menuFixed > ul > li > a "))
        {
            var cat = new Category();
            cat.URL = Links.Attributes ["href"];
            cat.Name = Links.InnerText;
            categoryList.Add(cat);
        }
        Scrape(categoryList, "Shopping.Jsonl");
    }
}
public class ShoppingScraper : WebScraper
{
    /// <summary>
    /// Anula este método para inicializar tu web-scraper.
    /// Tareas importantes serán Solicitar al menos una url de inicio... y establecer patrones de dominios o urls permitidos/prohibidos.
    /// </summary>
    public override void Init()
    {
        License.LicenseKey = "LicenseKey";
        this.LoggingLevel = WebScraper.LogLevel.All;
        this.WorkingDirectory = AppSetting.GetAppRoot() + @"\ShoppingSiteSample\Output\";
        this.Request("www.webSite.com", Parse);
    }

    /// <summary>
    /// Sustituya este método para crear el manejador de respuesta predeterminado para su raspador web.
    /// Si tiene varios tipos de página, puede añadir métodos similares adicionales.
    /// </summary>
    /// <param name="response">The http Response object to parse</param>
    public override void Parse(Response response)
    {
        var categoryList = new List<Category>();

        foreach (var Links in response.Css("#menuFixed > ul > li > a "))
        {
            var cat = new Category();
            cat.URL = Links.Attributes ["href"];
            cat.Name = Links.InnerText;
            categoryList.Add(cat);
        }
        Scrape(categoryList, "Shopping.Jsonl");
    }
}
Public Class ShoppingScraper
	Inherits WebScraper

	''' <summary>
	''' Anula este método para inicializar tu web-scraper.
	''' Tareas importantes serán Solicitar al menos una url de inicio... y establecer patrones de dominios o urls permitidos/prohibidos.
	''' </summary>
	Public Overrides Sub Init()
		License.LicenseKey = "LicenseKey"
		Me.LoggingLevel = WebScraper.LogLevel.All
		Me.WorkingDirectory = AppSetting.GetAppRoot() & "\ShoppingSiteSample\Output\"
		Me.Request("www.webSite.com", AddressOf Parse)
	End Sub

	''' <summary>
	''' Sustituya este método para crear el manejador de respuesta predeterminado para su raspador web.
	''' Si tiene varios tipos de página, puede añadir métodos similares adicionales.
	''' </summary>
	''' <param name="response">The http Response object to parse</param>
	Public Overrides Sub Parse(ByVal response As Response)
		Dim categoryList = New List(Of Category)()

		For Each Links In response.Css("#menuFixed > ul > li > a ")
			Dim cat = New Category()
			cat.URL = Links.Attributes ("href")
			cat.Name = Links.InnerText
			categoryList.Add(cat)
		Next Links
		Scrape(categoryList, "Shopping.Jsonl")
	End Sub
End Class
VB   C#

Extracción de enlaces del menú

Actualicemos nuestro código para raspar las Categorías Principales y todos sus subenlaces

public override void Parse(Response response)
{
    //  Lista de Categorías Enlaces (Raíz)
    var categoryList = new List<Category>();

    foreach (var li in response.Css("#menuFixed > ul > li"))
    {
        //  Lista de enlaces principales
        foreach (var Links in li.Css("a"))
        {
            var cat = new Category();
            cat.URL = Links.Attributes ["href"];
            cat.Name = Links.InnerText;
            cat.SubCategories = new List<Category>();
            //  Lista de enlaces de subcategorías
            foreach (var subCategory in li.Css("a [class=subcategory]"))
            {
                var subcat = new Category();
                subcat.URL = Links.Attributes ["href"];
                subcat.Name = Links.InnerText;
                //  Compruebe si el enlace existe antes 
                if (cat.SubCategories.Find(c=>c.Name== subcat.Name && c.URL == subcat.URL) == null)
                {
                    //  Añadir subenlaces
                    cat.SubCategories.Add(subcat);
                }
            }
            //  Añadir categorías
            categoryList.Add(cat);
        }
    }
    Scrape(categoryList, "Shopping.Jsonl");
}
public override void Parse(Response response)
{
    //  Lista de Categorías Enlaces (Raíz)
    var categoryList = new List<Category>();

    foreach (var li in response.Css("#menuFixed > ul > li"))
    {
        //  Lista de enlaces principales
        foreach (var Links in li.Css("a"))
        {
            var cat = new Category();
            cat.URL = Links.Attributes ["href"];
            cat.Name = Links.InnerText;
            cat.SubCategories = new List<Category>();
            //  Lista de enlaces de subcategorías
            foreach (var subCategory in li.Css("a [class=subcategory]"))
            {
                var subcat = new Category();
                subcat.URL = Links.Attributes ["href"];
                subcat.Name = Links.InnerText;
                //  Compruebe si el enlace existe antes 
                if (cat.SubCategories.Find(c=>c.Name== subcat.Name && c.URL == subcat.URL) == null)
                {
                    //  Añadir subenlaces
                    cat.SubCategories.Add(subcat);
                }
            }
            //  Añadir categorías
            categoryList.Add(cat);
        }
    }
    Scrape(categoryList, "Shopping.Jsonl");
}
Public Overrides Sub Parse(ByVal response As Response)
	'  Lista de Categorías Enlaces (Raíz)
	Dim categoryList = New List(Of Category)()

	For Each li In response.Css("#menuFixed > ul > li")
		'  Lista de enlaces principales
		For Each Links In li.Css("a")
			Dim cat = New Category()
			cat.URL = Links.Attributes ("href")
			cat.Name = Links.InnerText
			cat.SubCategories = New List(Of Category)()
			'  Lista de enlaces de subcategorías
			For Each subCategory In li.Css("a [class=subcategory]")
				Dim subcat = New Category()
				subcat.URL = Links.Attributes ("href")
				subcat.Name = Links.InnerText
				'  Compruebe si el enlace existe antes 
				If cat.SubCategories.Find(Function(c) c.Name= subcat.Name AndAlso c.URL = subcat.URL) Is Nothing Then
					'  Añadir subenlaces
					cat.SubCategories.Add(subcat)
				End If
			Next subCategory
			'  Añadir categorías
			categoryList.Add(cat)
		Next Links
	Next li
	Scrape(categoryList, "Shopping.Jsonl")
End Sub
VB   C#

Ahora que tenemos enlaces a todas las categorías del sitio, vamos a empezar a raspar los productos dentro de cada categoría

Naveguemos a cualquier categoría y comprobemos el contenido.

Veamos su código

<section class="products">
    <div class="sku -gallery -validate-size " data-sku="AG249FA0T2PSGNAFAMZ" ft-product-sizes="41,42,43,44,45" ft-product-color="Multicolour">
        <a class="link" href="http://www.WebSite.com/agu-bundle-of-2-sneakers-black-navy-blue-653884.html">
            <div class="image-wrapper default-state">
                <img class="lazy image -loaded" alt="Bundle Of 2 Sneakers - Black &amp;amp; Navy Blue" data-image-vertical="1" width="210" height="262" src="https://static.WebSite.com/p/agu-6208-488356-1-catalog_grid_3.jpg" data-sku="AG249FA0T2PSGNAFAMZ" data-src="https://static.WebSite.com/p/agu-6208-488356-1-catalog_grid_3.jpg" data-placeholder="placeholder_m_1.jpg"><noscript>&lt;img src="https://static.WebSite.com/p/agu-6208-488356-1-catalog_grid_3.jpg" width="210" height="262" class="image" /&gt;</noscript>
            </div> <h2 class="title">
                <span class="brand ">Agu&nbsp;</span>
                <span class="name" dir="ltr">Bundle Of 2 Sneakers - Black &amp; Navy Blue</span>
            </h2><div class="price-container clearfix">
                <span class="price-box">
                    <span class="price">
                        <span data-currency-iso="EGP">EGP</span>
                        <span dir="ltr" data-price="299">299</span>
                    </span>   <span class="price -old  -no-special"></span>
                </span>
            </div><div class="rating-stars"><div class="stars-container"><div class="stars" style="width: 62%"></div></div> <div class="total-ratings">(30)</div> </div>    <span class="shop-first-logo-container"><img src="http://www.WebSite.com/images/local/logos/shop_first/ShoppingSite/logo_normal.png" data-src="http://www.WebSite.com/images/local/logos/shop_first/ShoppingSite/logo_normal.png" class="lazy shop-first-logo-img -mbxs -loaded"> </span>
            <span class="osh-icon -ShoppingSite-local shop_local--logo -block -mbs -mts"></span>
            <div class="list -sizes" data-selected-sku="">
                <span class="js-link sku-size" data-href="http://www.WebSite.com/agu-bundle-of-2-sneakers-black-navy-blue-653884.html?size=41">41</span>     <span class="js-link sku-size" data-href="http://www.WebSite.com/agu-bundle-of-2-sneakers-black-navy-blue-653884.html?size=42">42</span>
                <span class="js-link sku-size" data-href="http://www.WebSite.com/agu-bundle-of-2-sneakers-black-navy-blue-653884.html?size=43">43</span>     <span class="js-link sku-size" data-href="http://www.WebSite.com/agu-bundle-of-2-sneakers-black-navy-blue-653884.html?size=44">44</span>
                <span class="js-link sku-size" data-href="http://www.WebSite.com/agu-bundle-of-2-sneakers-black-navy-blue-653884.html?size=45">45</span>
            </div>
        </a>
    </div>
    <div class="sku -gallery -validate-size " data-sku="LE047FA01SRK4NAFAMZ" ft-product-sizes="110,115,120,125,130,135" ft-product-color="Black">
        <a class="link" href="http://www.WebSite.com/leather-shop-genuine-leather-belt-black-712030.html">
            <div class="image-wrapper default-state"><img class="lazy image -loaded" alt="Genuine Leather Belt - Black" data-image-vertical="1" width="210" height="262" src="https://static.WebSite.com/p/leather-shop-1831-030217-1-catalog_grid_3.jpg" data-sku="LE047FA01SRK4NAFAMZ" data-src="https://static.WebSite.com/p/leather-shop-1831-030217-1-catalog_grid_3.jpg" data-placeholder="placeholder_m_1.jpg"><noscript>&lt;img src="https://static.WebSite.com/p/leather-shop-1831-030217-1-catalog_grid_3.jpg" width="210" height="262" class="image" /&gt;</noscript></div>
            <h2 class="title"><span class="brand ">Leather Shop&nbsp;</span> <span class="name" dir="ltr">Genuine Leather Belt - Black</span></h2><div class="price-container clearfix">
                <span class="sale-flag-percent">-29%</span>  <span class="price-box"> <span class="price"><span data-currency-iso="EGP">EGP</span> <span dir="ltr" data-price="96">96</span> </span>   <span class="price -old "><span data-currency-iso="EGP">EGP</span> <span dir="ltr" data-price="135">135</span> </span> </span>
            </div><div class="rating-stars"><div class="stars-container"><div class="stars" style="width: 100%"></div></div> <div class="total-ratings">(1)</div> </div>
            <span class="osh-icon -ShoppingSite-local shop_local--logo -block -mbs -mts"></span>    <div class="list -sizes" data-selected-sku="">
                <span class="js-link sku-size" data-href="http://www.WebSite.com/leather-shop-genuine-leather-belt-black-712030.html?size=110">110</span>     <span class="js-link sku-size" data-href="http://www.WebSite.com/leather-shop-genuine-leather-belt-black-712030.html?size=115">115</span>
                <span class="js-link sku-size" data-href="http://www.WebSite.com/leather-shop-genuine-leather-belt-black-712030.html?size=120">120</span>     <span class="js-link sku-size" data-href="http://www.WebSite.com/leather-shop-genuine-leather-belt-black-712030.html?size=125">125</span>     <span class="js-link sku-size" data-href="http://www.WebSite.com/leather-shop-genuine-leather-belt-black-712030.html?size=130">130</span>
                <span class="js-link sku-size" data-href="http://www.WebSite.com/leather-shop-genuine-leather-belt-black-712030.html?size=135">135</span>
            </div>
        </a>
    </div>
</section>
<section class="products">
    <div class="sku -gallery -validate-size " data-sku="AG249FA0T2PSGNAFAMZ" ft-product-sizes="41,42,43,44,45" ft-product-color="Multicolour">
        <a class="link" href="http://www.WebSite.com/agu-bundle-of-2-sneakers-black-navy-blue-653884.html">
            <div class="image-wrapper default-state">
                <img class="lazy image -loaded" alt="Bundle Of 2 Sneakers - Black &amp;amp; Navy Blue" data-image-vertical="1" width="210" height="262" src="https://static.WebSite.com/p/agu-6208-488356-1-catalog_grid_3.jpg" data-sku="AG249FA0T2PSGNAFAMZ" data-src="https://static.WebSite.com/p/agu-6208-488356-1-catalog_grid_3.jpg" data-placeholder="placeholder_m_1.jpg"><noscript>&lt;img src="https://static.WebSite.com/p/agu-6208-488356-1-catalog_grid_3.jpg" width="210" height="262" class="image" /&gt;</noscript>
            </div> <h2 class="title">
                <span class="brand ">Agu&nbsp;</span>
                <span class="name" dir="ltr">Bundle Of 2 Sneakers - Black &amp; Navy Blue</span>
            </h2><div class="price-container clearfix">
                <span class="price-box">
                    <span class="price">
                        <span data-currency-iso="EGP">EGP</span>
                        <span dir="ltr" data-price="299">299</span>
                    </span>   <span class="price -old  -no-special"></span>
                </span>
            </div><div class="rating-stars"><div class="stars-container"><div class="stars" style="width: 62%"></div></div> <div class="total-ratings">(30)</div> </div>    <span class="shop-first-logo-container"><img src="http://www.WebSite.com/images/local/logos/shop_first/ShoppingSite/logo_normal.png" data-src="http://www.WebSite.com/images/local/logos/shop_first/ShoppingSite/logo_normal.png" class="lazy shop-first-logo-img -mbxs -loaded"> </span>
            <span class="osh-icon -ShoppingSite-local shop_local--logo -block -mbs -mts"></span>
            <div class="list -sizes" data-selected-sku="">
                <span class="js-link sku-size" data-href="http://www.WebSite.com/agu-bundle-of-2-sneakers-black-navy-blue-653884.html?size=41">41</span>     <span class="js-link sku-size" data-href="http://www.WebSite.com/agu-bundle-of-2-sneakers-black-navy-blue-653884.html?size=42">42</span>
                <span class="js-link sku-size" data-href="http://www.WebSite.com/agu-bundle-of-2-sneakers-black-navy-blue-653884.html?size=43">43</span>     <span class="js-link sku-size" data-href="http://www.WebSite.com/agu-bundle-of-2-sneakers-black-navy-blue-653884.html?size=44">44</span>
                <span class="js-link sku-size" data-href="http://www.WebSite.com/agu-bundle-of-2-sneakers-black-navy-blue-653884.html?size=45">45</span>
            </div>
        </a>
    </div>
    <div class="sku -gallery -validate-size " data-sku="LE047FA01SRK4NAFAMZ" ft-product-sizes="110,115,120,125,130,135" ft-product-color="Black">
        <a class="link" href="http://www.WebSite.com/leather-shop-genuine-leather-belt-black-712030.html">
            <div class="image-wrapper default-state"><img class="lazy image -loaded" alt="Genuine Leather Belt - Black" data-image-vertical="1" width="210" height="262" src="https://static.WebSite.com/p/leather-shop-1831-030217-1-catalog_grid_3.jpg" data-sku="LE047FA01SRK4NAFAMZ" data-src="https://static.WebSite.com/p/leather-shop-1831-030217-1-catalog_grid_3.jpg" data-placeholder="placeholder_m_1.jpg"><noscript>&lt;img src="https://static.WebSite.com/p/leather-shop-1831-030217-1-catalog_grid_3.jpg" width="210" height="262" class="image" /&gt;</noscript></div>
            <h2 class="title"><span class="brand ">Leather Shop&nbsp;</span> <span class="name" dir="ltr">Genuine Leather Belt - Black</span></h2><div class="price-container clearfix">
                <span class="sale-flag-percent">-29%</span>  <span class="price-box"> <span class="price"><span data-currency-iso="EGP">EGP</span> <span dir="ltr" data-price="96">96</span> </span>   <span class="price -old "><span data-currency-iso="EGP">EGP</span> <span dir="ltr" data-price="135">135</span> </span> </span>
            </div><div class="rating-stars"><div class="stars-container"><div class="stars" style="width: 100%"></div></div> <div class="total-ratings">(1)</div> </div>
            <span class="osh-icon -ShoppingSite-local shop_local--logo -block -mbs -mts"></span>    <div class="list -sizes" data-selected-sku="">
                <span class="js-link sku-size" data-href="http://www.WebSite.com/leather-shop-genuine-leather-belt-black-712030.html?size=110">110</span>     <span class="js-link sku-size" data-href="http://www.WebSite.com/leather-shop-genuine-leather-belt-black-712030.html?size=115">115</span>
                <span class="js-link sku-size" data-href="http://www.WebSite.com/leather-shop-genuine-leather-belt-black-712030.html?size=120">120</span>     <span class="js-link sku-size" data-href="http://www.WebSite.com/leather-shop-genuine-leather-belt-black-712030.html?size=125">125</span>     <span class="js-link sku-size" data-href="http://www.WebSite.com/leather-shop-genuine-leather-belt-black-712030.html?size=130">130</span>
                <span class="js-link sku-size" data-href="http://www.WebSite.com/leather-shop-genuine-leather-belt-black-712030.html?size=135">135</span>
            </div>
        </a>
    </div>
</section>
HTML

Construyamos nuestro modelo de producto para este contenido.

public class Product
{
    /// <summary>
    /// Obtiene o establece el nombre.
    /// </summary>
    /// <value>
    /// El nombre.
    /// </value>
    public string Name { get; set; }
    /// <summary>
    /// Obtiene o fija el precio.
    /// </summary>
    /// <value>
    /// El precio.
    /// </value>
    public string Price { get; set; }
    /// <summary>
    /// Obtiene o establece la imagen.
    /// </summary>
    /// <value>
    /// La imagen.
    /// </value>
    public string Image { get; set; }
}
public class Product
{
    /// <summary>
    /// Obtiene o establece el nombre.
    /// </summary>
    /// <value>
    /// El nombre.
    /// </value>
    public string Name { get; set; }
    /// <summary>
    /// Obtiene o fija el precio.
    /// </summary>
    /// <value>
    /// El precio.
    /// </value>
    public string Price { get; set; }
    /// <summary>
    /// Obtiene o establece la imagen.
    /// </summary>
    /// <value>
    /// La imagen.
    /// </value>
    public string Image { get; set; }
}
Public Class Product
	''' <summary>
	''' Obtiene o establece el nombre.
	''' </summary>
	''' <value>
	''' El nombre.
	''' </value>
	Public Property Name() As String
	''' <summary>
	''' Obtiene o fija el precio.
	''' </summary>
	''' <value>
	''' El precio.
	''' </value>
	Public Property Price() As String
	''' <summary>
	''' Obtiene o establece la imagen.
	''' </summary>
	''' <value>
	''' La imagen.
	''' </value>
	Public Property Image() As String
End Class
VB   C#

Para raspar páginas de categorías, añadimos un nuevo método de raspado:

public void ParseCatgory(Response response)
{          
    //  Lista de productos Enlaces (Raíz)
    var productList = new List<Product>();

    foreach (var Links in response.Css("body > main > section.osh-content > section.products > div > a"))
    {
        var product = new Product();
        product.Name = Links.InnerText;
        product.Image = Links.Css("div.image-wrapper.default-state > img")[0].Attributes ["src"];                
        productList.Add(product);
    }

    Scrape(productList, "Products.Jsonl");
}
public void ParseCatgory(Response response)
{          
    //  Lista de productos Enlaces (Raíz)
    var productList = new List<Product>();

    foreach (var Links in response.Css("body > main > section.osh-content > section.products > div > a"))
    {
        var product = new Product();
        product.Name = Links.InnerText;
        product.Image = Links.Css("div.image-wrapper.default-state > img")[0].Attributes ["src"];                
        productList.Add(product);
    }

    Scrape(productList, "Products.Jsonl");
}
Public Sub ParseCatgory(ByVal response As Response)
	'  Lista de productos Enlaces (Raíz)
	Dim productList = New List(Of Product)()

	For Each Links In response.Css("body > main > section.osh-content > section.products > div > a")
		Dim product As New Product()
		product.Name = Links.InnerText
		product.Image = Links.Css("div.image-wrapper.default-state > img")(0).Attributes ("src")
		productList.Add(product)
	Next Links

	Scrape(productList, "Products.Jsonl")
End Sub
VB   C#

Funciones avanzadas de Webscraping

Característica HttpIdentity:

Algunos sistemas de sitios web exigen que el usuario inicie sesión para ver el contenido; en este caso podemos utilizar una HttpIdentity: -

HttpIdentity id = new HttpIdentity();
id.NetworkUsername = "username";
id.NetworkPassword = "pwd";
Identities.Add(id); 
HttpIdentity id = new HttpIdentity();
id.NetworkUsername = "username";
id.NetworkPassword = "pwd";
Identities.Add(id); 
Dim id As New HttpIdentity()
id.NetworkUsername = "username"
id.NetworkPassword = "pwd"
Identities.Add(id)
VB   C#

Una de las características más impresionantes y potentes de IronWebScraper, es la capacidad de utilizar miles de únicos (credenciales del usuario y/o motores del navegador) para falsificar o rastrear sitios web utilizando varias sesiones de inicio de sesión.

public override void Init()
{
    License.LicenseKey = " LicenseKey ";
    this.LoggingLevel = WebScraper.LogLevel.All;
    this.WorkingDirectory = AppSetting.GetAppRoot() + @"\ShoppingSiteSample\Output\";
    var proxies = "IP-Proxy1: 8080,IP-Proxy2: 8081".Split(',');
    foreach (var UA in IronWebScraper.CommonUserAgents.ChromeDesktopUserAgents)
    {
        foreach (var proxy in proxies)
        {
            Identities.Add(new HttpIdentity()
            {
                UserAgent = UA,
                UseCookies = true,
                Proxy = proxy
            });
        }
    }
    this.Request("http://www.Website.com", Parse);
}
public override void Init()
{
    License.LicenseKey = " LicenseKey ";
    this.LoggingLevel = WebScraper.LogLevel.All;
    this.WorkingDirectory = AppSetting.GetAppRoot() + @"\ShoppingSiteSample\Output\";
    var proxies = "IP-Proxy1: 8080,IP-Proxy2: 8081".Split(',');
    foreach (var UA in IronWebScraper.CommonUserAgents.ChromeDesktopUserAgents)
    {
        foreach (var proxy in proxies)
        {
            Identities.Add(new HttpIdentity()
            {
                UserAgent = UA,
                UseCookies = true,
                Proxy = proxy
            });
        }
    }
    this.Request("http://www.Website.com", Parse);
}
Public Overrides Sub Init()
	License.LicenseKey = " LicenseKey "
	Me.LoggingLevel = WebScraper.LogLevel.All
	Me.WorkingDirectory = AppSetting.GetAppRoot() & "\ShoppingSiteSample\Output\"
	Dim proxies = "IP-Proxy1: 8080,IP-Proxy2: 8081".Split(","c)
	For Each UA In IronWebScraper.CommonUserAgents.ChromeDesktopUserAgents
		For Each proxy In proxies
			Identities.Add(New HttpIdentity() With {
				.UserAgent = UA,
				.UseCookies = True,
				.Proxy = proxy
			})
		Next proxy
	Next UA
	Me.Request("http://www.Website.com", Parse)
End Sub
VB   C#

Dispone de múltiples propiedades para darle diferentes comportamientos, evitando así que los sitios web le bloqueen.

Algunas de estas propiedades: -

  • Dominio de red : El dominio de red que se utilizará para la autenticación del usuario. Compatible con redes Windows, NTLM , Keroberos, Linux, BSD y Mac OS X. Debe utilizarse con (NetworkUsername y NetworkPassword)
  • NombreUsuarioRed : El nombre de usuario de red/http que se utilizará para la autenticación del usuario. Soporta Http, redes Windows, NTLM , Kerberos , redes Linux, redes BSD y Mac OS.
  • Contraseña de red : La contraseña de red/http que se utilizará para la autenticación del usuario. Soporta Http , redes Windows, NTLM , Keroberos , redes Linux, redes BSD y Mac OS.
  • Proxy : para configurar el proxy
  • UserAgent : para configurar el motor del navegador (chrome desktop , chrome mobile , chrome tablet , IE y Firefox , etc.)
  • HttpRequestHeaders : para los valores de cabecera personalizados que se utilizarán con esta identidad, y acepta objetos de diccionario.(Diccionario <cadena, cadena>)
  • UseCookies : activar/desactivar el uso de cookies

    IronWebScraper ejecuta el scraper utilizando identidades aleatorias. Si necesitamos especificar el uso de una identidad concreta para analizar una página, podemos hacerlo.

public override void Init()
{
    License.LicenseKey = " LicenseKey ";
    this.LoggingLevel = WebScraper.LogLevel.All;
    this.WorkingDirectory = AppSetting.GetAppRoot() + @"\ShoppingSiteSample\Output\";
    HttpIdentity identity = new HttpIdentity();
    identity.NetworkUsername = "username";
    identity.NetworkPassword = "pwd";
    Identities.Add(id);
    this.Request("http://www.Website.com", Parse, identity);
}
public override void Init()
{
    License.LicenseKey = " LicenseKey ";
    this.LoggingLevel = WebScraper.LogLevel.All;
    this.WorkingDirectory = AppSetting.GetAppRoot() + @"\ShoppingSiteSample\Output\";
    HttpIdentity identity = new HttpIdentity();
    identity.NetworkUsername = "username";
    identity.NetworkPassword = "pwd";
    Identities.Add(id);
    this.Request("http://www.Website.com", Parse, identity);
}
Public Overrides Sub Init()
	License.LicenseKey = " LicenseKey "
	Me.LoggingLevel = WebScraper.LogLevel.All
	Me.WorkingDirectory = AppSetting.GetAppRoot() & "\ShoppingSiteSample\Output\"
	Dim identity As New HttpIdentity()
	identity.NetworkUsername = "username"
	identity.NetworkPassword = "pwd"
	Identities.Add(id)
	Me.Request("http://www.Website.com", Parse, identity)
End Sub
VB   C#

Active la función de caché web:

Esta función se utiliza para almacenar en caché las páginas solicitadas. Suele utilizarse en las fases de desarrollo y prueba; que permite a los desarrolladores almacenar en caché las páginas necesarias para reutilizarlas tras actualizar el código. Esto le permite ejecutar su código en las páginas almacenadas en caché después de reiniciar su Web scraper y sin necesidad de conectarse al sitio web en vivo cada vez. (acción-reproducción).

*Puedes utilizarlo en Init() Método

EnableWebCache();

O

EnableWebCache(Expiración del plazo);

Guardará los datos en caché en la carpeta WebCache situada bajo la carpeta del directorio de trabajo

public override void Init()
{
    License.LicenseKey = " LicenseKey ";
    this.LoggingLevel = WebScraper.LogLevel.All;
    this.WorkingDirectory = AppSetting.GetAppRoot() + @"\ShoppingSiteSample\Output\";
    EnableWebCache(new TimeSpan(1,30,30));
    this.Request("http://www.WebSite.com", Parse);
}
public override void Init()
{
    License.LicenseKey = " LicenseKey ";
    this.LoggingLevel = WebScraper.LogLevel.All;
    this.WorkingDirectory = AppSetting.GetAppRoot() + @"\ShoppingSiteSample\Output\";
    EnableWebCache(new TimeSpan(1,30,30));
    this.Request("http://www.WebSite.com", Parse);
}
Public Overrides Sub Init()
	License.LicenseKey = " LicenseKey "
	Me.LoggingLevel = WebScraper.LogLevel.All
	Me.WorkingDirectory = AppSetting.GetAppRoot() & "\ShoppingSiteSample\Output\"
	EnableWebCache(New TimeSpan(1,30,30))
	Me.Request("http://www.WebSite.com", Parse)
End Sub
VB   C#

IronWebScraper también tiene características para permitir que su motor continúe raspando después de reiniciar el código estableciendo el nombre del proceso de inicio del motor mediante Start(CrawlID)

static void Main(string [] args)
{
    //  Crear objeto a partir de la clase Scraper
    EngineScraper scrape = new EngineScraper();
    //  Empezar a raspar
    scrape.Start("enginestate");
}
static void Main(string [] args)
{
    //  Crear objeto a partir de la clase Scraper
    EngineScraper scrape = new EngineScraper();
    //  Empezar a raspar
    scrape.Start("enginestate");
}
Shared Sub Main(ByVal args() As String)
	'  Crear objeto a partir de la clase Scraper
	Dim scrape As New EngineScraper()
	'  Empezar a raspar
	scrape.Start("enginestate")
End Sub
VB   C#

La solicitud de ejecución y la respuesta se guardarán en la carpeta SavedState dentro del directorio de trabajo.

Estrangulamiento

Podemos controlar el número mínimo y máximo de conexiones y la velocidad de conexión por dominio.

public override void Init()
{
    License.LicenseKey = "LicenseKey";
    this.LoggingLevel = WebScraper.LogLevel.All;
    this.WorkingDirectory = AppSetting.GetAppRoot() + @"\ShoppingSiteSample\Output\";
    //  Obtiene o establece el número total de peticiones HTTP abiertas permitidas (hilos)
    this.MaxHttpConnectionLimit = 80;
    //  Obtiene o establece el retardo (pausa) mínimo entre peticiones a un dominio o dirección IP determinados.
    this.RateLimitPerHost = TimeSpan.FromMilliseconds(50);            
    //          Obtiene o establece el número permitido de peticiones HTTP concurrentes (hilos) por nombre de host.
    //          o dirección IP. Esto ayuda a proteger a los hosts contra demasiadas peticiones.
    this.OpenConnectionLimitPerHost = 25;
    this.ObeyRobotsDotTxt = false;
    //          Hace que el WebSraper estrangule de forma inteligente las peticiones no sólo por nombre de host, sino
    //          también por las direcciones IP de los servidores anfitriones. Esto es útil en caso de que varios dominios raspados
    //          están alojados en la misma máquina.
    this.ThrottleMode = Throttle.ByDomainHostName;

    this.Request("https://www.Website.com", Parse);
}
public override void Init()
{
    License.LicenseKey = "LicenseKey";
    this.LoggingLevel = WebScraper.LogLevel.All;
    this.WorkingDirectory = AppSetting.GetAppRoot() + @"\ShoppingSiteSample\Output\";
    //  Obtiene o establece el número total de peticiones HTTP abiertas permitidas (hilos)
    this.MaxHttpConnectionLimit = 80;
    //  Obtiene o establece el retardo (pausa) mínimo entre peticiones a un dominio o dirección IP determinados.
    this.RateLimitPerHost = TimeSpan.FromMilliseconds(50);            
    //          Obtiene o establece el número permitido de peticiones HTTP concurrentes (hilos) por nombre de host.
    //          o dirección IP. Esto ayuda a proteger a los hosts contra demasiadas peticiones.
    this.OpenConnectionLimitPerHost = 25;
    this.ObeyRobotsDotTxt = false;
    //          Hace que el WebSraper estrangule de forma inteligente las peticiones no sólo por nombre de host, sino
    //          también por las direcciones IP de los servidores anfitriones. Esto es útil en caso de que varios dominios raspados
    //          están alojados en la misma máquina.
    this.ThrottleMode = Throttle.ByDomainHostName;

    this.Request("https://www.Website.com", Parse);
}
Public Overrides Sub Init()
	License.LicenseKey = "LicenseKey"
	Me.LoggingLevel = WebScraper.LogLevel.All
	Me.WorkingDirectory = AppSetting.GetAppRoot() & "\ShoppingSiteSample\Output\"
	'  Obtiene o establece el número total de peticiones HTTP abiertas permitidas (hilos)
	Me.MaxHttpConnectionLimit = 80
	'  Obtiene o establece el retardo (pausa) mínimo entre peticiones a un dominio o dirección IP determinados.
	Me.RateLimitPerHost = TimeSpan.FromMilliseconds(50)
	'          Obtiene o establece el número permitido de peticiones HTTP concurrentes (hilos) por nombre de host.
	'          o dirección IP. Esto ayuda a proteger a los hosts contra demasiadas peticiones.
	Me.OpenConnectionLimitPerHost = 25
	Me.ObeyRobotsDotTxt = False
	'          Hace que el WebSraper estrangule de forma inteligente las peticiones no sólo por nombre de host, sino
	'          también por las direcciones IP de los servidores anfitriones. Esto es útil en caso de que varios dominios raspados
	'          están alojados en la misma máquina.
	Me.ThrottleMode = Throttle.ByDomainHostName

	Me.Request("https://www.Website.com", Parse)
End Sub
VB   C#

Propiedades de estrangulamiento

  • MaxHttpConnectionLimit
    número total de peticiones HTTP abiertas permitidas (hilos)
  • TarifaLímitePorHost
    retardo o pausa de cortesía mínima (en milisegundos) entre peticiones a un determinado dominio o dirección IP
  • OpenConnectionLimitPerHost (Límite de conexión abierta por host)
    número permitido de peticiones HTTP simultáneas (hilos)
  • Acelerador
    Hace que el WebSraper estrangule de forma inteligente las peticiones no sólo por nombre de host, sino también por direcciones IP de los servidores host. Esto es útil en el caso de que varios dominios raspados estén alojados en la misma máquina.

Anexo

¿Cómo crear una aplicación Windows Form?

Para ello debemos utilizar Visual Studio 2013 o superior.

Siga estos pasos para crear un nuevo proyecto Windows Forms:

  1. Abrir Visual Studio

  2. Archivo -> Nuevo -> Proyecto

  3. En Plantilla, elija el lenguaje de programación (Visual C# o VB) -> Windows -> Aplicación Windows Forms

    **Nombre del proyecto IronScraperSample

Ubicación: Elige una ubicación en tu disco duro

¿Cómo crear una aplicación de formulario web?

Para ello, debe utilizar Visual Studio 2013 o superior.

Siga los pasos para Crear un Nuevo Proyecto Asp.NET Web forms

  1. Abrir Visual Studio

  2. Archivo -> Nuevo -> Proyecto

  3. Desde Plantilla Elegir lenguaje de programación (Visual C# o VB) -> Web -> Aplicación Web ASP.NET (.NET Framework).

    **Nombre del proyecto IronScraperSample

Ubicación: Elija una ubicación de su disco duro

  1. Desde sus plantillas ASP.NET

    1. Seleccionar plantilla vacía
    2. Comprobar formularios web
  2. Ahora su proyecto básico de formulario web ASP.NET está creado

    Pulse aquí para descargar el tutorial completo del proyecto de código de muestra.

Ingeniero de Software .NET Para muchos esta es la forma más eficiente de generar archivos PDF desde .NET, porque no hay una API adicional que aprender, ni un complejo sistema de diseño por el que navegar.

Ahmed Aboelmagd

Arquitecto de soluciones de software .NET en una empresa multinacional de TI

Ahmed es un especialista certificado en tecnología Microsoft con más de 10 años de experiencia en TI y desarrollo de software. Ha trabajado en diversas empresas y ahora es director nacional de una multinacional de TI.

Ahmed lleva más de un año trabajando con IronPDF e IronWebScraper, utilizándolos en múltiples proyectos con su empresa.