Menú

Mostrar Mensajes

Esta sección te permite ver todos los mensajes escritos por este usuario. Ten en cuenta que sólo puedes ver los mensajes escritos en zonas a las que tienes acceso en este momento.

Mostrar Mensajes Menú

Mensajes - Eleкtro

#1101
Foro Libre / Re: Tiroteo en YouTube
5 Abril 2018, 19:11 PM
Cita de: Orubatosu en  5 Abril 2018, 18:37 PM
El problema no es que tengan armas creo yo. Quitaselas y usarán ballestas, bates o a mordiscos. El problema es que han fomentado excesivamente la violencia, no hay mas

Asumir que el riesgo sin armas de fuego sería el mismo o parecido no justifica que sigan teniendo armas de fuego, además, ten en cuenta que las armas de fuego se utilizan por que permiten matar a distancia y con el menor de los esfuerzos (bueno, excepto por el esfuerzo de mantener rígida el arma para no darte un hostión en la cara por el retroceso), así que sin duda alguna prefiero que cada individuo estado unidense se pasee por la calle con uno o cinco bates en cada mano, que ya verías como la tasa de muertes descendería considerablemente por que las probabilidades de matar "eficientemente" se reducirían, ya que pegar con un bate implicaría un riesgo de acercamiento hacia la persona a la que quieres golpear, así que a muchos degenerados se les pasaría por la cabeza pegarle un "batazo" a alguien inocente, pero luego se acojonarían por si no lo consiguen, pero eso con una pistola no pasa, la pistola te da "poder", apuntas a tu víctima, aprietas el gatillo y si aciertas en algún punto crítico se muere... y sino, puedes vovlerlo a itentar todas las veces que te permita el cargador mientras la víctima sigue a varios metros bien lejos de ti... sin peligro para ti.

Las armas ayudan a que esa violencia de la que hablas vaya en crecimiento, es un círculo vicioso. La posesión de armas de fuego a estas alturas en este siglo es injustificable como tu bien pareciste querer decir por la mitad de tu comentario...

Saludos!
#1102
Foro Libre / Re: Tiroteo en YouTube
5 Abril 2018, 18:17 PM
1. Esto en un claro motivo más para seguir defendiendo la legalidad de las armas en EEUU, ¿a que si?. (no se si concretamente en California es legal o ilegal, pero me da exactamente igual.)

2. No me gusta hablar de los muertos, pero por lo visto esa mujer era un poco DESAGRADECIDA por que Youtube no es un trabajo como tal, aunque a algunos se lo parezca y aunque algunos se lo tomen como una forma de vida y abusen de ello hasta el punto en que digan que youtube es donde "trabajan", pero no lo es, Youtube es una plataforma gratuita que además de serlo te ofrece una recompensa o motivación en forma de dinero por subir tu contenido, así que menos quejas, que nadie le obligaba a esa mujer a hacer y subir videos, y aun así le pagaban por hacerlo siendo algo gratuito, pues creo que esa persona deberia poner una sonrisa en vez de ponerse a pegar tiros a la gente... es que es de ser descerebrado/a y muy desagradecido/a ya que a esa señora le estaban ofreciendo un servicio gratuito y además cobraba algo de dinero por usarlo, pero cuando le quitan ese dinero de gratis no se le ocurre otra cosa más sensata que reclamar un derecho el cual nunca le ha pertenecido, y ponerse a matr gente, venga por favor... esa mujer desde luego está mejor muerta si pensamos en la seguridad del resto de ciudadanos que tienen al menos dos neuronas en el cerebro...

Quizás podría sensibilizarme hasta cierto punto y tener en consideración el punto de desesperación de esa mujer que le llevó a disparar un arma, pero es que no, no puedo, ver a gente que actua así y por esos motivos tan injustificados es algo que me supera.

Y digo yo, toda esa gente que tiene 200 afiliados pero gana una absurda miseria de céntimos con servicios PTC y plafaromas piramidales del estilo... nunca he escuchado el caso de que nadie matara a los dueños de esos servicios por que le pagaban poco... es que es de lo más absurdo por Dios.

Esa es mi opiión. Saludos!
#1103
Obtener un valor aleatorio de tipo Single (float en C#), Double o Decimal dentro de un rango mínimo y máximo específico.




He implementado esta solución mediante un módulo de extensiones de método para la clase System.Random

La lista de miembros disponibles son los siguientes:


  • Random.NextSingle() As Single
  • Random.NextSingle(Single) As Single
  • Random.NextSingle(Single, Single) As Single
  • Random.NextDouble(Double) As Double
  • Random.NextDouble(Double, Double) As Double
  • Random.NextDecimal() As Decimal
  • Random.NextDecimal(Decimal) As Decimal
  • Random.NextDecimal(Decimal, Decimal) As Decimal

El código fuente:
Código (vbnet) [Seleccionar]
#Region " Option Statements "

Option Strict On
Option Explicit On
Option Infer Off

#End Region

#Region " Imports "

Imports System.ComponentModel
Imports System.Runtime.CompilerServices

#End Region

#Region " Random Extensions "

Namespace Extensions

   ''' ----------------------------------------------------------------------------------------------------
   ''' <summary>
   ''' Contains custom extension methods to use with the <see cref="Random"/> type.
   ''' </summary>
   ''' ----------------------------------------------------------------------------------------------------
   <ImmutableObject(True)>
   <HideModuleName>
   Public Module RandomExtensions

#Region " Public Extension Methods "

       ''' ----------------------------------------------------------------------------------------------------
       ''' <summary>
       ''' Returns a non-negative <see cref="Single"/> value.
       ''' </summary>
       ''' ----------------------------------------------------------------------------------------------------
       ''' <param name="sender">
       ''' The source <see cref="Random"/>.
       ''' </param>
       ''' ----------------------------------------------------------------------------------------------------
       ''' <returns>
       ''' The resulting <see cref="Single"/> value.
       ''' </returns>
       ''' ----------------------------------------------------------------------------------------------------
       <DebuggerStepThrough>
       <Extension>
        <EditorBrowsable(EditorBrowsableState.Always)>
       Public Function NextSingle(ByVal sender As Random) As Single
           Return CSng(sender.NextDouble())
       End Function

       ''' ----------------------------------------------------------------------------------------------------
       ''' <summary>
       ''' Returns a non-negative <see cref="Single"/> value between zero and the maximum specified.
       ''' </summary>
       ''' ----------------------------------------------------------------------------------------------------
       ''' <param name="sender">
       ''' The source <see cref="Random"/>.
       ''' </param>
       '''
       ''' <param name="maxValue">
       ''' The maximum value.
       ''' </param>
       ''' ----------------------------------------------------------------------------------------------------
       ''' <returns>
       ''' The resulting <see cref="Single"/> value.
       ''' </returns>
       ''' ----------------------------------------------------------------------------------------------------
       <DebuggerStepThrough>
       <Extension>
        <EditorBrowsable(EditorBrowsableState.Always)>
       Public Function NextSingle(ByVal sender As Random, ByVal maxValue As Single) As Single
           Return NextSingle(sender, 0.0F, maxValue)
       End Function

       ''' ----------------------------------------------------------------------------------------------------
       ''' <summary>
       ''' Returns a non-negative <see cref="Single"/> value between the minimum and maximum specified.
       ''' </summary>
       ''' ----------------------------------------------------------------------------------------------------
       ''' <param name="sender">
       ''' The source <see cref="Random"/>.
       ''' </param>
       '''
       ''' <param name="minValue">
       ''' The minimum value.
       ''' </param>
       '''
       ''' <param name="maxValue">
       ''' The maximum value.
       ''' </param>
       ''' ----------------------------------------------------------------------------------------------------
       ''' <returns>
       ''' The resulting <see cref="Single"/> value.
       ''' </returns>
       ''' ----------------------------------------------------------------------------------------------------
       <DebuggerStepThrough>
       <Extension>
        <EditorBrowsable(EditorBrowsableState.Always)>
       Public Function NextSingle(ByVal sender As Random, ByVal minValue As Single, ByVal maxValue As Single) As Single
           Return NextSingle(sender) * (maxValue - minValue) + minValue
       End Function

       ''' ----------------------------------------------------------------------------------------------------
       ''' <summary>
       ''' Returns a non-negative <see cref="Double"/> value between zero and the maximum specified.
       ''' </summary>
       ''' ----------------------------------------------------------------------------------------------------
       ''' <param name="sender">
       ''' The source <see cref="Random"/>.
       ''' </param>
       '''
       ''' <param name="maxValue">
       ''' The maximum value.
       ''' </param>
       ''' ----------------------------------------------------------------------------------------------------
       ''' <returns>
       ''' The resulting <see cref="Double"/> value.
       ''' </returns>
       ''' ----------------------------------------------------------------------------------------------------
       <DebuggerStepThrough>
       <Extension>
        <EditorBrowsable(EditorBrowsableState.Always)>
       Public Function NextDouble(ByVal sender As Random, ByVal maxValue As Double) As Double
           Return NextDouble(sender, 0.0R, maxValue)
       End Function

       ''' ----------------------------------------------------------------------------------------------------
       ''' <summary>
       ''' Returns a non-negative <see cref="Double"/> value between the minimum and maximum specified.
       ''' </summary>
       ''' ----------------------------------------------------------------------------------------------------
       ''' <param name="sender">
       ''' The source <see cref="Random"/>.
       ''' </param>
       '''
       ''' <param name="minValue">
       ''' The minimum value.
       ''' </param>
       '''
       ''' <param name="maxValue">
       ''' The maximum value.
       ''' </param>
       ''' ----------------------------------------------------------------------------------------------------
       ''' <returns>
       ''' The resulting <see cref="Double"/> value.
       ''' </returns>
       ''' ----------------------------------------------------------------------------------------------------
       <DebuggerStepThrough>
       <Extension>
        <EditorBrowsable(EditorBrowsableState.Always)>
       Public Function NextDouble(ByVal sender As Random, ByVal minValue As Double, ByVal maxValue As Double) As Double
           Return sender.NextDouble() * (maxValue - minValue) + minValue
       End Function

       ''' ----------------------------------------------------------------------------------------------------
       ''' <summary>
       ''' Returns a non-negative <see cref="Decimal"/> value.
       ''' </summary>
       ''' ----------------------------------------------------------------------------------------------------
       ''' <param name="sender">
       ''' The source <see cref="Random"/>.
       ''' </param>
       ''' ----------------------------------------------------------------------------------------------------
       ''' <returns>
       ''' The resulting <see cref="Decimal"/> value.
       ''' </returns>
       ''' ----------------------------------------------------------------------------------------------------
       <DebuggerStepThrough>
       <Extension>
        <EditorBrowsable(EditorBrowsableState.Always)>
       Public Function NextDecimal(ByVal sender As Random) As Decimal
           Return NextDecimal(sender, Decimal.MaxValue)
       End Function

       ''' ----------------------------------------------------------------------------------------------------
       ''' <summary>
       ''' Returns a non-negative <see cref="Decimal"/> value between zero and the maximum specified.
       ''' </summary>
       ''' ----------------------------------------------------------------------------------------------------
       ''' <param name="sender">
       ''' The source <see cref="Random"/>.
       ''' </param>
       '''
       ''' <param name="maxValue">
       ''' The maximum value.
       ''' </param>
       ''' ----------------------------------------------------------------------------------------------------
       ''' <returns>
       ''' The resulting <see cref="Decimal"/> value.
       ''' </returns>
       ''' ----------------------------------------------------------------------------------------------------
       <DebuggerStepThrough>
       <Extension>
        <EditorBrowsable(EditorBrowsableState.Always)>
       Public Function NextDecimal(ByVal sender As Random, ByVal maxValue As Decimal) As Decimal
           Return NextDecimal(sender, Decimal.Zero, maxValue)
       End Function

       ''' ----------------------------------------------------------------------------------------------------
       ''' <summary>
       ''' Returns a non-negative <see cref="Decimal"/> value between the minimum and maximum specified.
       ''' </summary>
       ''' ----------------------------------------------------------------------------------------------------
       ''' <param name="sender">
       ''' The source <see cref="Random"/>.
       ''' </param>
       '''
       ''' <param name="minValue">
       ''' The minimum value.
       ''' </param>
       '''
       ''' <param name="maxValue">
       ''' The maximum value.
       ''' </param>
       ''' ----------------------------------------------------------------------------------------------------
       ''' <returns>
       ''' The resulting <see cref="Decimal"/> value.
       ''' </returns>
       ''' ----------------------------------------------------------------------------------------------------
       <DebuggerStepThrough>
       <Extension>
        <EditorBrowsable(EditorBrowsableState.Always)>
       Public Function NextDecimal(ByVal sender As Random, ByVal minValue As Decimal, ByVal maxValue As Decimal) As Decimal
           Dim nextSample As Decimal = NextDecimalSample(sender)
           Return maxValue * nextSample + minValue * (1 - nextSample)
       End Function

#End Region

#Region " Private Methods "

       ''' ----------------------------------------------------------------------------------------------------
       ''' <summary>
       ''' Provides a random <see cref="Decimal"/> value
       ''' in the range: [0.0000000000000000000000000000, 0.9999999999999999999999999999)
       ''' with (theoretical) uniform and discrete distribution.
       ''' </summary>
       ''' ----------------------------------------------------------------------------------------------------
       ''' <remarks>
       ''' <see href="https://stackoverflow.com/a/28860710/1248295"/>
       ''' </remarks>
       ''' ----------------------------------------------------------------------------------------------------
       ''' <param name="rng">
       ''' The source <see cref="Random"/>.
       ''' </param>
       ''' ----------------------------------------------------------------------------------------------------
       ''' <returns>
       ''' The resulting <see cref="Decimal"/> value.
       ''' </returns>
       ''' ----------------------------------------------------------------------------------------------------
        <DebuggerStepperBoundary>
       Private Function NextDecimalSample(ByVal rng As Random) As Decimal
           Dim sample As Decimal = 1D
           ' After ~200 million tries this never took more than one attempt
           ' but it Is possible To generate combinations Of a, b, and c
           ' With the approach below resulting In a sample >= 1.
           Do While (sample >= 1D)
               Dim a As Integer = rng.Next(0, Integer.MaxValue)
               Dim b As Integer = rng.Next(0, Integer.MaxValue)
               Dim c As Integer = rng.Next(542101087) ' The high bits of 0.9999999999999999999999999999m are 542101086.
               sample = New Decimal(a, b, c, False, 28)
           Loop
           Return sample
       End Function

#End Region

   End Module

End Namespace

#End Region
#1104
Ejemplo de uso del FHM Crawler que compartí en este otro post: https://foro.elhacker.net/net/libreria_de_snippets_para_vbnet_compartan_aqui_sus_snippets-t378770.0.html;msg2158878#msg2158878

Código (vbnet) [Seleccionar]
Imports FHM

Public Module Module1

   Private WithEvents FHMCrawler As New Crawler
   Private mre As New ManualResetEvent(initialState:=False)

   Public Sub Main()
       FHMCrawler.SearchQuery.Artist = "Paramore"

       Console.WriteLine("URL: {0}", FHMCrawler.SearchQuery.ToString())
       Console.WriteLine()
       Console.WriteLine("Retrieving Album count...")
       Dim albumCount As Integer = FHMCrawler.GetAlbumCount()
       Console.WriteLine("Album Count: {0}", albumCount)
       Console.WriteLine()
       Console.WriteLine("Begin crawling, please wait...")
       Fetch()
       mre.WaitOne()
       Console.WriteLine("Done!. Press any key to exit...")
       Console.ReadKey()
   End Sub

   Public Async Sub Fetch()
       Dim success As Boolean = Await FHMCrawler.FetchAlbumsAsync()
       mre.Set()
   End Sub

   <DebuggerStepperBoundary>
   Private Sub FHMCrawler_BeginPageCrawl(ByVal sender As Object, e As PageCrawlBeginEventArgs) Handles FHMCrawler.PageCrawlBegin
       Console.WriteLine("[+] Begin crawling page with index: {0}", e.SearchPage)
       Console.WriteLine()
   End Sub

   <DebuggerStepperBoundary>
   Private Sub FHMCrawler_EndPageCrawl(ByVal sender As Object, e As PageCrawlEndEventArgs) Handles FHMCrawler.PageCrawlEnd
       For Each albumInfo As AlbumInfo In e.Albums
           Dim sb As New StringBuilder()
           sb.AppendLine(String.Format("Artist Name.....: {0}", albumInfo.Artist))
           sb.AppendLine(String.Format("Album Title.....: {0}", albumInfo.Title))
           sb.AppendLine(String.Format("Album Year......: {0}", albumInfo.Year))
           sb.AppendLine(String.Format("Album Country...: {0}", albumInfo.Country))
           sb.AppendLine(String.Format("Album Genre.....: {0}", albumInfo.Genre))
           sb.AppendLine(String.Format("Album Id........: {0}", albumInfo.Id))
           sb.AppendLine(String.Format("Album Url.......: {0}", albumInfo.Uri.AbsoluteUri))
           sb.AppendLine(String.Format("Download Link(s): {0}", String.Format("{{ {0} }}", String.Join(", ", albumInfo.DownloadLinks))))
           Console.WriteLine(sb.ToString())
       Next albumInfo
       Console.WriteLine("[+] End crawling page with index: {0}", e.SearchPage)
       Console.WriteLine()
   End Sub

End Module


Output:
Citar
URL: http://freehardmusic.com/index.php?field_band=Paramore&field_country=all&field_genre=all&field_year=all&option=com_sobi2&search=Search&searchphrase=exact&sobi2Search=&sobi2Task=axSearch&SobiCatSelected_0=0&sobiCid=0&SobiSearchPage=0

Retrieving Album count...
Album Count: 13

Begin crawling, please wait...
Otro output addicional:
Search Params: field_band=h%c3%a9roes+del+silencio&field_country=all&field_genre=all&field_year=all

Uri: http://freehardmusic.com/index.php?field_band=h%C3%A9roes+del+silencio&field_country=all&field_genre=all&field_year=all&option=com_sobi2&search=Search&searchphrase=exact&sobi2Search=&sobi2Task=axSearch&SobiCatSelected_0=0&sobiCid=0&SobiSearchPage=0

Retrieving Album count...
Album Count: 21

Begin crawling, please wait...
[+] Begin crawling page with index: 0

Artist Name.....: Héroes Del Silencio
Album Title.....: The Platinum Collection (Compilation)
Album Year......: 2006
Album Country...: Spain
Album Genre.....: Hard Rock
Album Id........: 770138
Album Url.......: http://freehardmusic.com/albums.html?sobi2Task=sobi2Details&catid=0&sobi2Id=770138
Download Link(s): { https://mega.nz/#!5yAE0ZpA!IFhADBkkKHgEN4Gghum-h9iKbQlH6N3owXymDokmF4Q }

Artist Name.....: Héroes Del Silencio
Album Title.....: Tesoro - Concert In Valencia 27Th October 2007 (Video)
Album Year......: 2008
Album Country...: Spain
Album Genre.....: Hard Rock
Album Id........: 770135
Album Url.......: http://freehardmusic.com/albums.html?sobi2Task=sobi2Details&catid=0&sobi2Id=770135
Download Link(s): { https://mega.nz/#!834HAAiY!S7NDexqPxuPU6nEVv9PriekUi3MN3O2oBCtrTd2Nx8Y }

Artist Name.....: Héroes Del Silencio
Album Title.....: Senda '91 (Live)
Album Year......: 1991
Album Country...: Spain
Album Genre.....: Hard Rock
Album Id........: 770129
Album Url.......: http://freehardmusic.com/albums.html?sobi2Task=sobi2Details&catid=0&sobi2Id=770129
Download Link(s): { https://mega.nz/#!8uAC1DIS!tctPPSySY6I2v7kteAahx6iKlDVs8R5WnrWvXUBtqaM }

Artist Name.....: Héroes Del Silencio
Album Title.....: En Directo
Album Year......: 1989
Album Country...: Spain
Album Genre.....: Hard Rock
Album Id........: 770127
Album Url.......: http://freehardmusic.com/albums.html?sobi2Task=sobi2Details&catid=0&sobi2Id=770127
Download Link(s): { https://mega.nz/#!wnJwmYpD!XIFosoFfCar5UTAAjgORH0QHW8jm5ELRqZGK4UTNMfU }

Artist Name.....: Héroes Del Silencio
Album Title.....: Héroes Del Silencio (Compilation)
Album Year......: 1999
Album Country...: Spain
Album Genre.....: Hard Rock
Album Id........: 770126
Album Url.......: http://freehardmusic.com/albums.html?sobi2Task=sobi2Details&catid=0&sobi2Id=770126
Download Link(s): { https://mega.nz/#!47R2jKqD!WmwbU3DvhVoBcZvf2IMPMATpAC_woGtKiBo_YzTp3eo }

Artist Name.....: Héroes Del Silencio
Album Title.....: Senderos De Traición (25Th Anniversary Edition)
Album Year......: 2015
Album Country...: Spain
Album Genre.....: Rock And Roll
Album Id........: 703496
Album Url.......: http://freehardmusic.com/albums.html?sobi2Task=sobi2Details&catid=0&sobi2Id=703496
Download Link(s): { https://www.mediafire.com/?gwyzc4pvvhjdiax }

Artist Name.....: Héroes Del Silencio
Album Title.....: Volveremos (Compilation)
Album Year......: 2016
Album Country...: Spain
Album Genre.....: Rock And Roll
Album Id........: 703259
Album Url.......: http://freehardmusic.com/albums.html?sobi2Task=sobi2Details&catid=0&sobi2Id=703259
Download Link(s): { http://www.mediafire.com/file/sh9pr3uvb86my6b/703259.rar }

Artist Name.....: Héroes Del Silencio
Album Title.....: El Espíritu Del Vino (20Th Anniversary Edition)
Album Year......: 2012
Album Country...: Spain
Album Genre.....: Hard Rock
Album Id........: 700503
Album Url.......: http://freehardmusic.com/albums.html?sobi2Task=sobi2Details&catid=0&sobi2Id=700503
Download Link(s): { https://mega.nz/#!lgESxaJb!5K3YpWZ1Znq5EhZij9ltPd1GLaTaH_dSePXm5pCN6dg }

Artist Name.....: Héroes Del Silencio
Album Title.....: Antología Audiovisual (Compilation)
Album Year......: 2004
Album Country...: Spain
Album Genre.....: Hard Rock
Album Id........: 700490
Album Url.......: http://freehardmusic.com/albums.html?sobi2Task=sobi2Details&catid=0&sobi2Id=700490
Download Link(s): { https://mega.nz/#!w8FUDQhb!COgXmh-uPayeSk5k1mpHrdIy5VziIIvTO7iaW0MfmTM }

Artist Name.....: Héroes Del Silencio
Album Title.....: Entre Dos Tierras (Ep)
Album Year......: 1992
Album Country...: Spain
Album Genre.....: Hard Rock
Album Id........: 700488
Album Url.......: http://freehardmusic.com/albums.html?sobi2Task=sobi2Details&catid=0&sobi2Id=700488
Download Link(s): { https://mega.nz/#!7V1H3T4L!1q_o2lLp-b6Ky2p7P_minriRplYwUc8WRdSi7K24aes }

[+] End crawling page with index: 0

[+] Begin crawling page with index: 1

Artist Name.....: Héroes Del Silencio
Album Title.....: Héroes Del Silencio (Ep)
Album Year......: 1986
Album Country...: Spain
Album Genre.....: Hard Rock
Album Id........: 700487
Album Url.......: http://freehardmusic.com/albums.html?sobi2Task=sobi2Details&catid=0&sobi2Id=700487
Download Link(s): { https://mega.nz/#!GNkTyZwA!0EXRDQwIpyG5BoVoY5zCnkonnAe3ZzFJmD4hwfmi-og, https://mega.nz/#!ljZ13RRK!u36qptAkX9XJN2LNKKZYTk25o-6kC4vgp1TXZ5wDRyo }

Artist Name.....: Heroés Del Silencio
Album Title.....: Live In Germany (Live)
Album Year......: 2011
Album Country...: Spain
Album Genre.....: Pop Rock, Alternative Rock
Album Id........: 691258
Album Url.......: http://freehardmusic.com/albums.html?sobi2Task=sobi2Details&catid=0&sobi2Id=691258
Download Link(s): { https://mega.nz/#!84oxmBgB!q1x4NuAd79OUAyp4X7O5Da0b0KFwWwOoFNKqGGFQHW8 }

Artist Name.....: Héroes Del Silencio
Album Title.....: Canciones '84 - '96 (Compilation)
Album Year......: 2000
Album Country...: Spain
Album Genre.....: Classic Rock
Album Id........: 675749
Album Url.......: http://freehardmusic.com/albums.html?sobi2Task=sobi2Details&catid=0&sobi2Id=675749
Download Link(s): { https://mega.nz/#!8uI0iBBD!3SFYXCJRse5ijwmC9TLgTtfhL8Jr__t3-qSI7IPurSI }

Artist Name.....: Héroes Del Silencio
Album Title.....: Tour 2007 (Live)
Album Year......: 2007
Album Country...: Spain
Album Genre.....: Hard Rock
Album Id........: 639726
Album Url.......: http://freehardmusic.com/albums.html?sobi2Task=sobi2Details&catid=0&sobi2Id=639726
Download Link(s): { https://mega.co.nz/#!t81VUIxT!Y5qEQUR5C8wIA69pH4w90DWRCxN8dcKsCVSFmCT46P8 }

Artist Name.....: Héroes Del Silencio
Album Title.....: Rarezas (Compilation)
Album Year......: 1998
Album Country...: Spain
Album Genre.....: Hard Rock
Album Id........: 639724
Album Url.......: http://freehardmusic.com/albums.html?sobi2Task=sobi2Details&catid=0&sobi2Id=639724
Download Link(s): { http://www.mediafire.com/download/v6oyrrh7un9o8t0/HDS98-R.gif, https://mega.co.nz/#!pgUlFC5Y!M3KOBFXZb5ZoN1TD-KRHOhl1mzIwm5WoQjqtsbncevk }

Artist Name.....: Héroes Del Silencio
Album Title.....: El Ruido Y La Furia (Live)
Album Year......: 2005
Album Country...: Spain
Album Genre.....: Rock And Roll, Hard Rock
Album Id........: 639723
Album Url.......: http://freehardmusic.com/albums.html?sobi2Task=sobi2Details&catid=0&sobi2Id=639723
Download Link(s): { https://mega.co.nz/#!N1tgEIhA!FhSGL1xaktCN1HphZuOJFn5EmRhetkfS8bUpAB47KCY }

Artist Name.....: Héroes Del Silencio
Album Title.....: El Mar No Cesa
Album Year......: 1988
Album Country...: Spain
Album Genre.....: Pop Rock
Album Id........: 46543
Album Url.......: http://freehardmusic.com/albums.html?sobi2Task=sobi2Details&catid=0&sobi2Id=46543
Download Link(s): { http://www.mediafire.com/?no7d4y5vp2btna6 }

Artist Name.....: Héroes Del Silencio
Album Title.....: Para Siempre (Live)
Album Year......: 1996
Album Country...: Spain
Album Genre.....: Hard Rock
Album Id........: 43036
Album Url.......: http://freehardmusic.com/albums.html?sobi2Task=sobi2Details&catid=0&sobi2Id=43036
Download Link(s): { http://www.mediafire.com/?q73ip21df7qb19d }

Artist Name.....: Héroes Del Silencio
Album Title.....: Senderos De Traición
Album Year......: 1990
Album Country...: Spain
Album Genre.....: Hard Rock
Album Id........: 37296
Album Url.......: http://freehardmusic.com/albums.html?sobi2Task=sobi2Details&catid=0&sobi2Id=37296
Download Link(s): { https://mega.co.nz/#!ok0UQIrB!bfQdCTtlLd4Rh7MIptTvfnPFDI9oBEd-ZvotzILoCFw }

Artist Name.....: Héroes Del Silencio
Album Title.....: Avalancha
Album Year......: 1995
Album Country...: Spain
Album Genre.....: Hard Rock
Album Id........: 37292
Album Url.......: http://freehardmusic.com/albums.html?sobi2Task=sobi2Details&catid=0&sobi2Id=37292
Download Link(s): { https://mega.nz/#!Fc4zEaia!-5LYB3ueWHoZB890f34zsW_aTUTrsFQAwIvbpcZH4as }

[+] End crawling page with index: 1

[+] Begin crawling page with index: 2

Artist Name.....: Héroes Del Silencio
Album Title.....: El Espíritu Del Vino
Album Year......: 1993
Album Country...: Spain
Album Genre.....: Hard Rock
Album Id........: 37253
Album Url.......: http://freehardmusic.com/albums.html?sobi2Task=sobi2Details&catid=0&sobi2Id=37253
Download Link(s): { https://mega.nz/#!0ZxC2LiJ!D1Rl95lm9sgz9RGxEPSmGSrW8ZvzVH5VckbDOJ81GnA }

[+] End crawling page with index: 2

Done!. Press any key to exit...
#1105
Comparto el código fuente de FHM Crawler, mejorado y documentado... (bueno, me he visto obligado a simplificar y recortar la documentación por el límite de caracteres del foro)

Aquí el programa original:


Aquí el nuevo algoritmo reutilizable:

AlbumInfo.vb
Código (vbnet) [Seleccionar]
#Region " Imports "

Imports System.Collections.ObjectModel

#End Region

Namespace FHM

   ''' <summary>Represents the information of an album crawled with <see cref="FHM.Crawler"/>.</summary>
   Public NotInheritable Class AlbumInfo

#Region " Properties "

       ''' <summary>Gets the album identifier (that is used in the 'sobiid' and 'sobi2id' parameters).</summary>
       Public ReadOnly Property Id As String

       ''' <summary>Gets the album <see cref="Uri"/>.</summary>
       Public ReadOnly Property Uri As Uri

       ''' <summary>Gets the artist name.</summary>
       Public ReadOnly Property Artist As String

       ''' <summary>Gets the album title.</summary>
       Public ReadOnly Property Title As String

       ''' <summary>Gets the country of the band/artist.</summary>
       Public ReadOnly Property Country As String

       ''' <summary>Gets the music genre.</summary>
       Public ReadOnly Property Genre As String

       ''' <summary>Gets the year that the album has been released.</summary>
       Public ReadOnly Property Year As Integer

       ''' <summary>Gets the urls to download the album. It can be a single url, or multiple of them.</summary>
       Public ReadOnly Property DownloadLinks As ReadOnlyCollection(Of String)

#End Region

#Region " Constructors "

       Private Sub New()
       End Sub

       ''' <summary>Initializes a new instance of the <see cref="AlbumInfo"/> class.</summary>
       ''' <param name="id">The album identifier>.</param>
       ''' <param name="uri">The album <see cref="Uri"/>.</param>
       ''' <param name="artist">The artist name.</param>
       ''' <param name="title">The album title.</param>
       ''' <param name="country">The country of the band/artist.</param>
       ''' <param name="genre">The music genre.</param>
       ''' <param name="year">The year that the album has been released.</param>
       ''' <param name="downloadLinks">The urls to download the album. It can be a single url, or multiple of them.</param>
       Public Sub New(id As String, uri As Uri,
                      artist As String, title As String,
                      country As String, genre As String, year As Integer,
                      downloadLinks As IEnumerable(Of String))

           Me.Id = id
           Me.Uri = uri
           Me.Artist = artist
           Me.Title = title
           Me.Country = country
           Me.Genre = genre
           Me.Year = year
           Me.DownloadLinks = New ReadOnlyCollection(Of String)(downloadLinks)

       End Sub

#End Region

   End Class

End Namespace


SearchQuery.vb
Código (vbnet) [Seleccionar]

#Region " Imports "

Imports System.Collections.Specialized

Imports ElektroKit.Core.Extensions.NameValueCollection

#End Region

Namespace FHM

   ''' <summary>Represents a search query of the http://freehardmusic.com/ website,
   ''' that is managed by the <see cref="FHM.Crawler.FetchAlbums()"/>
   ''' and <see cref="FHM.Crawler.FetchAlbumsAsync()"/> methods.
   ''' <para></para>
   ''' Note that a search query can be performed in two different ways:
   ''' <para></para>
   ''' 1. An artist-name based search (<see cref="SearchQuery.Artist"/>).
   ''' <para></para>
   ''' 2. A non-artist name based search. That is, a custom search based on country (<see cref="SearchQuery.Country"/>),
   ''' genre (<see cref="SearchQuery.Genre"/>) or year criterias (<see cref="SearchQuery.Year"/>);
   ''' this kind of search can combine the three mentioned criterias, but not the artist name (<see cref="SearchQuery.Artist"/>).
   Public NotInheritable Class SearchQuery

#Region " Properties "

       ''' <summary>Gets or sets the artist name.</summary>
       Public Property Artist As String
           Get
               Return Me.artistB
           End Get
           <DebuggerStepThrough>
           Set(value As String)
               If Not (Me.countryB.Equals("all", StringComparison.OrdinalIgnoreCase)) OrElse
                  Not (Me.genreB.Equals("all", StringComparison.OrdinalIgnoreCase)) OrElse
                  Not (Me.yearB.Equals("all", StringComparison.OrdinalIgnoreCase)) Then

                   Throw New ArgumentException("To perform an artist-name based search, you must set the value of Country, Genre and Year properties to ""all"" before setting the Artist property.", paramName:=NameOf(value))
               End If
               Me.artistB = value
           End Set
       End Property
       Private artistB As String

       ''' <summary>Gets or sets the country of the band/artist.</summary>
       Public Property Country As String
           Get
               Return Me.countryB
           End Get
           <DebuggerStepThrough>
           Set(value As String)
               If Not (value.Equals("all", StringComparison.OrdinalIgnoreCase)) AndAlso Not String.IsNullOrEmpty(Me.artistB) Then
                   Throw New ArgumentException("To perform a country based search, you must set the value of Artist property to an empty string.", paramName:=NameOf(value))
               End If
               Me.countryB = value
           End Set
       End Property
       Private countryB As String

       ''' <summary>Gets or sets the music genre.</summary>
       Public Property Genre As String
           Get
               Return Me.genreB
           End Get
           <DebuggerStepThrough>
           Set(value As String)
               If Not (value.Equals("all", StringComparison.OrdinalIgnoreCase)) AndAlso Not String.IsNullOrEmpty(Me.artistB) Then
                   Throw New ArgumentException("To perform a genre based search, you must set the value of Artist property to an empty string.", paramName:=NameOf(value))
               End If
               Me.genreB = value
           End Set
       End Property
       Private genreB As String

       ''' <summary>Gets or sets the year that the album has been released.</summary>
       Public Property Year As String
           Get
               Return Me.yearB
           End Get
           <DebuggerStepThrough>
           Set(value As String)
               If Not (value.Equals("all", StringComparison.OrdinalIgnoreCase)) AndAlso Not String.IsNullOrEmpty(Me.artistB) Then
                   Throw New ArgumentException("To perform a year based search, you must set the value of Artist property to an empty string.", paramName:=NameOf(value))
               End If
               Me.yearB = value
           End Set
       End Property
       Private yearB As String

       ''' <summary>Gets the <see cref="Uri"/> that represents this search query.</summary>
       Public ReadOnly Property Uri As Uri
           Get
               Return Me.Uri(searchPage:=0)
           End Get
       End Property

       ''' <summary>Gets the <see cref="Uri"/> that represents this search query.</summary>
       ''' <param name="searchPage">The index of the search page parameter.</param>
       Public ReadOnly Property Uri(searchPage As Integer) As Uri
           Get
               Return New Uri(Me.ToString(searchPage), UriKind.Absolute)
           End Get
       End Property

#End Region

#Region " Constructors "

       Private Sub New()
       End Sub

       ''' <summary>Initializes a new instance of the <see cref="SearchQuery"/> class.</summary>
       ''' <param name="artist">The artist name.</param>
       Public Sub New(artist As String)
           Me.artistB = artist
           Me.genreB = "all"
           Me.countryB = "all"
           Me.yearB = "all"
       End Sub

       ''' <summary>Initializes a new instance of the <see cref="SearchQuery"/> class.</summary>
       ''' <param name="genre">The music genre. Default value is: "all"</param>
       ''' <param name="country">The country of the band/artist. Default value is: "all"</param>
       ''' <param name="year">The year that the album has been released. Default value is: "all"</param>
       Public Sub New(Optional genre As String = "all",
                      Optional country As String = "all",
                      Optional year As String = "all")

           Me.artistB = ""
           Me.genreB = genre
           Me.countryB = country
           Me.yearB = year
       End Sub

#End Region

#Region " Public Methods "

       ''' <summary>Resets the current search query to its default values.</summary>
       <DebuggerStepThrough>
       Public Sub Reset()
           Me.Artist = ""
           Me.Country = "all"
           Me.Genre = "all"
           Me.Year = "all"
       End Sub

       ''' <summary>Returns a <see cref="String"/> that represents the search query.</summary>
       ''' <returns>A <see cref="String"/> that represents the search query.</returns>
       Public Overrides Function ToString() As String
           Return Me.ToString(searchPage:=0)
       End Function

       ''' <summary>Returns a <see cref="String"/> that represents the search query.</summary>
       ''' <param name="searchPage">The index of the search page parameter.</param>
       ''' <returns>A <see cref="String"/> that represents the search query.</returns>
       Public Overloads Function ToString(searchPage As Integer) As String

           If (searchPage < 0) Then
               Throw New ArgumentException("Positive integer value is required.", paramName:=NameOf(searchPage))
           End If

           Dim params As New NameValueCollection From {
               {"field_band", Me.Artist},
               {"field_country", Me.Country},
               {"field_genre", Me.Genre},
               {"field_year", Me.Year},
               {"option", "com_sobi2"},
               {"search", "Search"},
               {"searchphrase", "exact"},
               {"sobi2Search", ""},
               {"sobi2Task", "axSearch"},
               {"SobiCatSelected_0", "0"},
               {"sobiCid", "0"},
               {"SobiSearchPage", searchPage}
           }

           Return params.ToQueryString(New Uri("http://freehardmusic.com/index.php"))

       End Function

#End Region

   End Class

End Namespace


PageCrawlBeginEventArgs.vb
Código (vbnet) [Seleccionar]

Namespace FHM

   ''' <summary>Represents the event data of the <see cref="FHM.Crawler.PageCrawlBegin"/> event.</summary>
   Public NotInheritable Class PageCrawlBeginEventArgs : Inherits EventArgs

#Region " Properties "

       ''' <summary>Gets the search query used.</summary>
       Public ReadOnly Property SearchQuery As SearchQuery

       ''' <summary>Gets the index of the search page being crawled.</summary>
       Public ReadOnly Property SearchPage As Integer

#End Region

#Region " Constructors "

       Private Sub New()
       End Sub

       ''' <summary>Initializes a new instance of the <see cref="PageCrawlBeginEventArgs"/> class.</summary>
       ''' <param name="searchQuery">The search query used.</param>
       ''' <param name="searchPage">The index of the search page.</param>
       Public Sub New(searchQuery As SearchQuery, searchPage As Integer)
           Me.SearchQuery = searchQuery
           Me.SearchPage = searchPage
       End Sub

#End Region

   End Class

End Namespace


PageCrawlEndEventArgs.vb
Código (vbnet) [Seleccionar]

Namespace FHM

   ''' <summary>Represents the event data of the <see cref="FHM.Crawler.PageCrawlEnd"/> event.</summary>
   Public NotInheritable Class PageCrawlEndEventArgs : Inherits EventArgs

#Region " Properties "

       ''' <summary>Gets the search query used.</summary>
       Public ReadOnly Property SearchQuery As SearchQuery

       ''' <summary>Gets the index of the search page crawled.</summary>
       Public ReadOnly Property SearchPage As Integer

       ''' <summary>Gets a collection of <see cref="AlbumInfo"/> that contains the information of the albums that were crawled.</summary>
       Public ReadOnly Property Albums As ReadOnlyCollection(Of AlbumInfo)

#End Region

#Region " Constructors "

       Private Sub New()
       End Sub

       ''' <summary>Initializes a new instance of the <see cref="PageCrawlEndEventArgs"/> class.</summary>
       ''' <param name="searchQuery">The search query used.</param>
       ''' <param name="searchPage">The index of the search page crawled.</param>
       ''' <param name="albums">A collection of <see cref="AlbumInfo"/> that contains the information of the albums that were crawled.</param>
       Public Sub New(searchQuery As SearchQuery, searchPage As Integer, albums As ICollection(Of AlbumInfo))
           Me.SearchQuery = searchQuery
           Me.SearchPage = searchPage
           Me.Albums = New ReadOnlyCollection(Of AlbumInfo)(albums)
       End Sub

#End Region

   End Class

End Namespace


Crawler.vb
Código (vbnet) [Seleccionar]
#Region " Imports "

Imports System.Collections.Specialized
Imports System.Text.RegularExpressions

Imports HtmlDocument = HtmlAgilityPack.HtmlDocument
Imports HtmlNode = HtmlAgilityPack.HtmlNode
Imports HtmlNodeCollection = HtmlAgilityPack.HtmlNodeCollection

Imports ElektroKit.Core.Extensions.NameValueCollection

#End Region

Namespace FHM

   ''' <summary>A crawler that searchs and collect albums (its download links) from the http://freehardmusic.com/ website.</summary>
   Public Class Crawler : Implements IDisposable

#Region " Private Fields "

       ''' <summary>The <see cref="Uri"/> that points to "http://freehardmusic.com/".</summary>
       Protected ReadOnly uriBase As New Uri("http://freehardmusic.com/")

       ''' <summary>The <see cref="Uri"/> that points to "http://freehardmusic.com/index2.php".</summary>
       Protected ReadOnly uriIndex As New Uri(Me.uriBase, "/index2.php")

       ''' <summary>Flag that determines whether this <see cref="Crawler"/> is busy in a pending fetch operation.</summary>
       Protected isFetching As Boolean

       ''' <summary>The <see cref="CancellationToken"/> instance that cancels a pending fetch operation
       ''' started by a call of <see cref="Crawler.FetchAlbumsAsync()"/>.</summary>
       Protected cancelToken As CancellationToken

       ''' <summary>The <see cref="CancellationTokenSource"/> instance that signals to <see cref="Crawler.cancelToken"/>.</summary>
       Protected cancelTokenSrc As CancellationTokenSource

#End Region

#Region " Properties "

       ''' <summary>Gets the search query.</summary>
       Public ReadOnly Property SearchQuery As SearchQuery

#End Region

#Region " Events "

       ''' <summary>Occurs when a page is about to be crawled.</summary>
       Public Event PageCrawlBegin As EventHandler(Of PageCrawlBeginEventArgs)

       ''' <summary>Occurs when a page is crawled.</summary>
       Public Event PageCrawlEnd As EventHandler(Of PageCrawlEndEventArgs)

#End Region

#Region " Constructors "

       ''' <summary>Initializes a new instance of the <see cref="Crawler"/> class.</summary>
       Public Sub New()
           Me.SearchQuery = New SearchQuery()
           Me.cancelTokenSrc = New CancellationTokenSource()
           Me.cancelToken = Me.cancelTokenSrc.Token
       End Sub

#End Region

#Region " Public Methods "

       ''' <summary>Gets the count of the albums found using the current search query.</summary>
       ''' <returns>The count of the albums found using the current search query.</returns>
       <DebuggerStepThrough>
       Public Overridable Function GetAlbumCount() As Integer
           Dim t As Task(Of Integer) = Task.Run(Of Integer)(AddressOf Me.GetAlbumCountAsync)
           t.Wait()

           Return t.Result
       End Function

       ''' <summary>Asynchronously gets the count of the albums found using the current search query.</summary>
       ''' <returns>The count of the albums found using the current search query.</returns>
       <DebuggerStepThrough>
       Public Overridable Async Function GetAlbumCountAsync() As Task(Of Integer)
           Dim query As String = Me.SearchQuery.ToString(searchPage:=0)
           Dim uriSearch As New Uri(query)
           Dim htmlSourceCode As String = String.Empty
           Using wc As New WebClient
               htmlSourceCode = Await wc.DownloadStringTaskAsync(uriSearch)
           End Using

           Dim htmldoc As New HtmlDocument
           htmldoc.LoadHtml(htmlSourceCode)

           Dim xPathResultString As String = "//div[@id='mainbody']/table[1]/tr[2]/td"

           Dim node As HtmlNode = htmldoc.DocumentNode.SelectSingleNode(xPathResultString)

           Dim text As String = node.InnerText
           text = Regex.Replace(text, "\n", "", RegexOptions.None)    ' Remove new lines.
           text = Regex.Replace(text, "\t", " "c, RegexOptions.None)  ' Replace tabs for white-spaces.
           text = Regex.Replace(text, "\s+", " "c, RegexOptions.None) ' Replace duplicated white-spaces.

           Dim albumCount As Integer = CInt(Regex.Match(text, "\d+", RegexOptions.None).Value)
           Return albumCount
       End Function

       ''' <summary>Fetch any album found using the current search query.</summary>
       <DebuggerStepThrough>
       Public Overridable Sub FetchAlbums()
           Dim t As Task = Task.Run(AddressOf Me.FetchAlbumsAsync)
           t.Wait()
       End Sub

       ''' <summary>Asynchronously fetch any album found using the current search query.</summary>
       ''' <returns>Returns <see langword="False"/> if the fetch operation was canceled by a call to
       ''' <see cref="Crawler.CancelFetchAlbumsAsync()"/> method.</returns>
       <DebuggerStepThrough>
       Public Overridable Async Function FetchAlbumsAsync() As Task(Of Boolean)
           If (Me.isFetching) Then
               Throw New Exception("Another fetch operation is already running in background.")
           End If
           Me.isFetching = True

           Me.cancelTokenSrc.Dispose()
           Me.cancelTokenSrc = New CancellationTokenSource()
           Me.cancelToken = Me.cancelTokenSrc.Token

           Dim albumCount As Integer = Await Me.GetAlbumCountAsync()
           If (albumCount = 0) Then
               Me.isFetching = False
               Return True
           End If

           Dim maxPages As Integer = ((albumCount \ 10) + 1) ' 10 albums per page.
           For i As Integer = 0 To (maxPages - 1)
               Dim query As String = Me.SearchQuery.ToString(searchPage:=i)
               Dim uriSearch As New Uri(query)
               Dim htmlSourceCode As String = String.Empty
               Using wc As New WebClient
                   htmlSourceCode = Await wc.DownloadStringTaskAsync(uriSearch)
               End Using

               If (Me.cancelToken.IsCancellationRequested) Then
                   Me.isFetching = False
                   Return False
               End If

               Me.OnPageCrawlBegin(New PageCrawlBeginEventArgs(Me.SearchQuery, i))
               Await Me.ParseHtmlSourceCode(i, htmlSourceCode)
           Next i

           Me.isFetching = False
           Return True
       End Function

       ''' <summary>Aborts a pending fetch operation started by a call to <see cref="Crawler.FetchAlbumsAsync()"/> function.</summary>
       <DebuggerStepThrough>
       Public Sub CancelFetchAlbumsAsync()
           If Not (Me.isFetching) Then
               Throw New Exception("No fetch operation is running.")
           End If

           If (Me.cancelToken.IsCancellationRequested) Then
               ' Handle redundant cancellation calls to CancelFetchAlbums()...
               Me.cancelToken.ThrowIfCancellationRequested()
           End If

           Me.cancelTokenSrc.Cancel()
       End Sub

       ''' <summary>Resets the current search query (<see cref="Crawler.SearchQuery"/>) to its default values.</summary>
       <DebuggerStepThrough>
       Public Sub ResetSearchQuery()
           Me.SearchQuery.Reset()
       End Sub

#End Region

#Region " Event-Invocators "

       ''' <summary>Raises the <see cref="Crawler.PageCrawlBegin"/> event.</summary>
       ''' <param name="e">The <see cref="PageCrawlBeginEventArgs"/> instance containing the event data.</param>
       Protected Overridable Sub OnPageCrawlBegin(e As PageCrawlBeginEventArgs)
           If (Me.PageCrawlBeginEvent IsNot Nothing) Then
               RaiseEvent PageCrawlBegin(Me, e)
           End If
       End Sub

       ''' <summary>Raises the <see cref="Crawler.PageCrawlEnd"/> event.</summary>
       ''' <param name="e">The <see cref="PageCrawlBeginEventArgs"/> instance containing the event data.</param>
       Protected Overridable Sub OnPageCrawlEnd(e As PageCrawlEndEventArgs)
           If (Me.PageCrawlEndEvent IsNot Nothing) Then
               RaiseEvent PageCrawlEnd(Me, e)
           End If
       End Sub

#End Region

#Region " Private Methods "

       ''' <summary>Parses the html source code to crawl the albums.</summary>
       ''' <param name="searchPage">The index of the search page.</param>
       ''' <param name="htmlSourceCode">The html source code to parse.</param>
       ''' <returns>Returns <see langword="True"/> if the operation succed; otherwise, <see langword="False"/>.</returns>
       <DebuggerStepperBoundary>
       Private Async Function ParseHtmlSourceCode(searchPage As Integer, htmlSourceCode As String) As Task(Of Boolean)

           Dim albums As New Collection(Of AlbumInfo)

           Dim xPathTable As String = "//table[@class='vicard']"
           Dim xPathArtist As String = ".//tr/td/span[@class='sobi2Listing_field_band']"
           Dim xPathCountry As String = ".//table[@class='vicard2']/tr/td[@class='goods']/table[@class='goods']/tr/td/img"
           Dim xPathGenre As String = ".//tr[3]/td/table/tr/td[2]/table/tr/td"
           Dim xPathYear As String = ".//tr/td/span[@class='sobi2Listing_field_year']"
           Dim xPathTitle As String = ".//tr/td/p[@class='sobi2ItemTitle']/a[@title]"
           Dim xPathUrl As String = ".//table[@class='vicard2']/tr/td/a[@href]"

           Dim htmldoc As New HtmlDocument
           Try
             htmldoc.LoadHtml(htmlSourceCode)
           Catch ex As Exception
               Return False
           End Try

           Dim nodes As HtmlNodeCollection = htmldoc.DocumentNode.SelectNodes(xPathTable)
           If (nodes.Count = 0) Then
               Return False
           End If

           For Each node As HtmlNode In nodes
               Dim artist As String
               Dim title As String
               Dim country As String
               Dim genre As String
               Dim year As String

               Dim albumId As String
               Dim albumUrl As String

               Try
                   artist = node.SelectSingleNode(xPathArtist).InnerText
                   artist = Encoding.UTF8.GetString(Encoding.Default.GetBytes(artist))
                   artist = HttpUtility.HtmlDecode(artist)
                   artist = New CultureInfo("en-US").TextInfo.ToTitleCase(artist.Trim(" "c).ToLower())
               Catch ex As Exception
                   artist = "unknown"
               End Try

               Try
                   title = node.SelectSingleNode(xPathTitle).GetAttributeValue("title", "")
                   title = Encoding.UTF8.GetString(Encoding.Default.GetBytes(title))
                   title = HttpUtility.HtmlDecode(title)
                   title = New CultureInfo("en-US").TextInfo.ToTitleCase(title.Trim(" "c).ToLower())
               Catch ex As Exception
                   title = "unknown"
               End Try

               Try
                   country = node.SelectSingleNode(xPathCountry).GetAttributeValue("src", "unknown")
                   country = Path.GetFileNameWithoutExtension(country)
                   country = New CultureInfo("en-US").TextInfo.ToTitleCase(country.ToLower())
               Catch ex As Exception
                   country = "unknown"
               End Try

               Try
                   genre = node.SelectSingleNode(xPathGenre).InnerText
                   genre = Regex.Replace(genre, "\n", "", RegexOptions.None)    ' Remove new lines.
                   genre = Regex.Replace(genre, "\t", " "c, RegexOptions.None)  ' Replace tabs for white-spaces.
                   genre = Regex.Replace(genre, "\s+", " "c, RegexOptions.None) ' Replace duplicated white-spaces.
                   genre = New CultureInfo("en-US").TextInfo.ToTitleCase(genre.Trim(" "c).ToLower())
               Catch ex As Exception
                   genre = "unknown"
               End Try

               Try
                   year = node.SelectSingleNode(xPathYear).InnerText.Trim(" "c)
               Catch ex As Exception
                   year = "unknown"
               End Try

               Try
                   albumUrl = node.SelectSingleNode(xPathUrl).GetAttributeValue("href", "").Trim(" "c)
                   albumUrl = HttpUtility.HtmlDecode(albumUrl)
               Catch ex As Exception
                   Continue For
               End Try

               albumId = HttpUtility.ParseQueryString(New Uri(albumUrl).Query)("sobi2Id")

               Dim downloadUrlParams As New NameValueCollection From {
                   {"sobiid", albumId},
                   {"sobi2Task", "addSRev"},
                   {"no_html", "1"},
                   {"option", "com_sobi2"},
                   {"rvote", "1"}
               }

               Dim downloadLinks As List(Of String)
               Try
                   Using wc As New WebClient()
                       htmlSourceCode = Await wc.DownloadStringTaskAsync(New Uri(downloadUrlParams.ToQueryString(Me.uriIndex)))
                   End Using

                   Dim xDoc As XDocument = XDocument.Parse(htmlSourceCode)
                   Dim elements As IEnumerable(Of XElement) = xDoc.<rev>
                   downloadLinks = New List(Of String) From {
                       elements.<msg>.Value,
                       elements.<msg2>.Value,
                       elements.<msg3>.Value,
                       elements.<msg4>.Value,
                       elements.<msg5>.Value,
                       elements.<msg6>.Value,
                       elements.<msg7>.Value,
                       elements.<msg8>.Value,
                       elements.<msg9>.Value,
                       elements.<msg10>.Value,
                       elements.<msg11>.Value,
                       elements.<msg12>.Value,
                       elements.<msg13>.Value
                   }
               Catch ex As Exception
                   Continue For
               End Try

               downloadLinks = (From item As String In downloadLinks
                                Where Not String.IsNullOrWhiteSpace(item)
                                Select item.TrimEnd(" "c)
                               ).ToList()

               Dim albumInfo As New AlbumInfo(albumId, New Uri(albumUrl, UriKind.Absolute),
                                              artist, title, country, genre, year,
                                              downloadLinks)

               albums.Add(albumInfo)
           Next node

           Me.OnPageCrawlEnd(New PageCrawlEndEventArgs(Me.SearchQuery, searchPage, albums))
           Return True
       End Function

#End Region

#Region " IDisposable Implementation "

       ''' <summary>Flag to detect redundant calls when disposing.</summary>
       Private isDisposed As Boolean = False

       ''' <summary>Releases all the resources used by this <see cref="Crawler"/>.</summary>
       <DebuggerStepThrough>
       Public Sub Dispose() Implements IDisposable.Dispose
           Me.Dispose(isDisposing:=True)
           GC.SuppressFinalize(obj:=Me)
       End Sub

       ''' <summary>Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.</summary>
       ''' <param name="isDisposing"><see langword="True"/> to release both managed and unmanaged resources;
       ''' <see langword="False"/> to release only unmanaged resources.</param>
       <DebuggerStepThrough>
       Protected Overridable Sub Dispose(isDisposing As Boolean)
           If (Not Me.isDisposed) AndAlso (isDisposing) Then
               If (Me.cancelTokenSrc IsNot Nothing) Then
                   Me.cancelTokenSrc.Dispose()
                   Me.cancelTokenSrc = Nothing
               End If
               Me.cancelToken = Nothing
               Me.isFetching = False
               Me.ResetSearchQuery()
           End If

           Me.isDisposed = True
       End Sub

#End Region

   End Class

End Namespace


NameValueCollectionExtensions.vb
#1106
Lo que comentas es normal y obvio; la función Process.GetProcesses() como su nombre indica por si mismo tiene el propósito de devolver una colección de procesos en ejecución, no una colección de ventanas creadas por "X" proceso...

Aquí abajo te comparto un código de mi librería comercial ElektroKit para obtener las ventanas abiertas del explorador de Windows:

Código (vbnet) [Seleccionar]

''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Gets a <see cref="IEnumerable(Of ShellBrowserWindow)"/> containing the opened windows explorer instances.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <returns>
''' A <see cref="IEnumerable(Of ShellBrowserWindow)"/> containing the opened windows explorer instances.
''' </returns>
''' ----------------------------------------------------------------------------------------------------
<DebuggerStepThrough>
Public Shared Iterator Function GetExplorerWindows() As IEnumerable(Of ShellBrowserWindow)

   Dim shell As New Shell32.Shell

   Try
       For Each window As ShellBrowserWindow In DirectCast(shell.Windows, IShellWindows)

           Select Case window.Document.GetType().Name

               Case "__ComObject" ' Explorer Window. ShellWindowTypeConstants.SWC_EXPLORER
                   Yield window

              ' Case "HTMLDocumentClass" ' Internet Explorer Window. ShellWindowTypeConstants.SWC_BROWSER
              '     ' Do Nothing.

               Case Else ' Other type of window.
                   ' Do Nothing.

           End Select

       Next window

   Catch ex As Exception
       Throw ex

   Finally
       Marshal.FinalReleaseComObject(shell)

   End Try

End Function


En C# el equivalente sería practicamente igual, pero con la sintaxis de C# claro está:
Código (csharp) [Seleccionar]
/// ----------------------------------------------------------------------------------------------------
/// <summary>
/// Gets a <see cref="IEnumerable{ShellBrowserWindow}"/> containing the opened windows explorer instances.
/// </summary>
/// ----------------------------------------------------------------------------------------------------
/// <returns>
/// A <see cref="IEnumerable{ShellBrowserWindow}"/> containing the opened windows explorer instances.
/// </returns>
/// ----------------------------------------------------------------------------------------------------
[DebuggerStepThrough]
public static IEnumerable<ShellBrowserWindow> GetExplorerWindows() {

   Shell32.Shell shell = new Shell32.Shell();

   try {
       foreach (ShellBrowserWindow window in (IShellWindows)shell.Windows()) {

           switch (window.Document.GetType().Name) {

               case "__ComObject":  // Explorer Window. ShellWindowTypeConstants.SWC_EXPLORER
                   yield return window;
                   break;

               // case "HTMLDocumentClass": // Internet Explorer Window. ShellWindowTypeConstants.SWC_BROWSER
               //    break;

               default: // Other type of window.
                   break;
           }
       }
   } finally {
       Marshal.FinalReleaseComObject(shell);
   }
}


La colección enumerable devuelta podrías iterarla de la siguiente forma que muestro aquí abajo. En este ejemplo busco la primera coincidencia de una ventana cuya ruta especificada en la barra de navegación sea "C:\", y cierro dicha ventana...

Código (csharp) [Seleccionar]
[STAThread]
static void Main(string[] args) {

   IEnumerable<ShellBrowserWindow> explorerWindows = GetExplorerWindows();

   foreach (ShellBrowserWindow Window in explorerWindows) {
       ShellFolderView view = (ShellFolderView)Window.Document;
       Folder2 folder = (Folder2)view.Folder;
       string path = folder.Self.Path;

       // Si la ruta en la barra de navegación es "C:\", cerramos esta ventana y salimos del búcle.
       if (path.Equals(@"C:\", StringComparison.OrdinalIgnoreCase)) {
           Window.Quit();
           break;
       }
   }


Nótese que necesitas referenciar las librerías Shell32.dll y SHDocv.dll para poder utilizar el código mostrado. Y aparte, no te olvides de especificar la clase de atributo STAThread como en el ejemplo, de lo contrario en C# tendrás errores de casting/conversión de tipos en tiempo de ejecución con las interfaces COM de Shell32 / SHDocVw.

Saludos.
#1107
FHM Crawler


Este tipo de programa se suele conocer como web-crawler o web-spider.

FHM Crawler es un simple programa para recolectar los enlaces de descarga del sitio web http://freehardmusic.com/,
el cual posee una base de datos gigantesca de álbumes de Rock y subgéneros.



Antes de seguir, me gustaría aclarar una cosa para los criticones y usuarios interesados en analizar el código fuente:

Si ven las imágenes del programa aquí abajo, se puede apreciar a simple vista que no me he esmerado más que lo justo y necesario en el diseño de la interfaz gráfica,
la disposición de los controles en la interfaz de usuario es fea, varias funcionalidades se podrían integrar a través de un menú contextual en el control ListView,
esto es como es, por que la intención fue crear una interfaz muy simple con el único objetivo de demostrar el uso del algoritmo-crawler que he desarrollado para esta página web. Esto lo hice para ustedes, no para mi, así que no me esmeré en la UI; y por ese mismo motivo también, esta será la única release que publicaré de este programa.

Además, a diferencia de como siempre hago cuando comparto un código fuente, en esta ocasión el código fuente lo comparto sin documentar (excepto la parte de mi librería comercial ElektroKit), esto tiene una sencilla razón, y es que solo desarrollé este algoritmo para utilizarlo una única vez y olvidarme de él para siempre (aun así, es un algoritmo robusto al menos en principio), así que no invertí esfuerzo en escribir documentación XML, pero creo que el código es lo suficientemente sencillo como para entenderlo por si mismo.

Por último, cabría mencionar que la aplicación hace uso de la conocida librería de terceros HtmlagilityPack para simplificar el parsing/análisis de datos del código fuente de la página web.




Imágenes










Vídeo





Descarga


Saludos!
#1108
+1 a todo lo que sea NFS de la vieja escuela. Lo cierto es que los NFS de ahora (los de los últimos 10 años hasta ahora) apestan. El último que jugué fue el NFS Payback hace poquito y... ñeh, es que a mi un NFS con "checkpoints" no me acaba de convencer, así que dos horas de vida le di hasta que lo tiré a la papelera de reciclaje. El NFS de la PS4 parece ser de los más realistas y, aunque ese juego no lo he catado pero también tiene una especie de checkpoints, así que... en fin.

Por ponerle alguna pega a los videos: estaría bien que fuesen comentados.

Saludos!
#1109
Puedes usar la clase SecureString para asignar un string mediante el cifrado en un bloque de memoria no administrada, pero no se si esa solución se ajustará a las necesidades que tengas:

+

no se muy bien lo que quieres conseguir, y tampoco soy un experto en cifrado ni obfuscación avanzada, pero no veo que quieres conseguir mediante XOR para ocultar un string en el código IL...

Yo creo que el compañero @KuBoX debe tener buena idea sobre estos temas, a ver si se deja ver por aquí...

Saludos
#1110
Cita de: rigorvzla en 29 Marzo 2018, 08:07 AM
el unico detalle es q no crea un subdirectorio y complica un poco las cosas por que esparece los archivos por donde esta, este detalle si seria bueno que me indicaras por que ni idea y eso que busque...

disculpa pero no comprendo muy bien esto a que te refieres con: "esparece los archivos por donde esta"

Antes de iniciar la operación de compresión, siempre puedes crear tú el subdirectorio de destino con el método que te indiqué: Directory.CreateDirectory(), ¿eso no te sirve para solucionar el problema que tengas?.