elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado: (TUTORIAL) Aprende a emular Sentinel Dongle By Yapis


+  Foro de elhacker.net
|-+  Programación
| |-+  Programación General
| | |-+  .NET (C#, VB.NET, ASP) (Moderador: kub0x)
| | | |-+  Problema con Expresiones regulares
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: [1] Ir Abajo Respuesta Imprimir
Autor Tema: Problema con Expresiones regulares  (Leído 1,547 veces)
Lekim

Desconectado Desconectado

Mensajes: 268



Ver Perfil
Problema con Expresiones regulares
« en: 19 Diciembre 2015, 19:12 pm »

Hola

La verdad no comprendo como funcionan las expresiones regulares, pese a que hay ejemplos en la ayuda msdn.

Estoy intentando obtener la Url de las imágenes de una página html junto con los valores Width, height y alt.

El problema está en que no siempre está en el mismo orden. Es decir primero puede establecerse src después height, width y luego alt:

<img src="..." height="128" width="128" alt"..."/>

También:

<img src="..." width"128" height="128" alt"..."/>


O por el contrario, establecerse el width o el heigth antes que el src:

  <img width"128" height="128" src="..."  alt"..."/>

  <img height"128" width="128" src="..."  alt"..."/>


Utilizando el sistema de las expresiones regulares con Regex ocurre que sólo obtiene los valores siempre y cuando estén el orden establecido en el pattern:

Código
  1. Dim Pattern As String = "<img[^>]+(src)\s*=\s*""?([^ "">]+)""?(?:[^>]+(width|height)\s*=\s*""?([^ "">]+)""?\s+(height|width)\s*=\s*""?([^ "">]+)""?)?(?:[^>]+(alt)\s*=\s*""?([^"">]+)""?)?"
  2.  
  3.        Dim re As New Regex(Pattern, RegexOptions.IgnoreCase)
  4.        Dim m As Match = re.Match(code)
  5.  
  6.        While m.Success
  7.  
  8.            For I As Integer = 0 To m.Groups.Count - 1
  9.                ListBox1.Items.Add(m.Groups(I).Value)
  10.            Next
  11.  
  12.        End While


'¿Como puedo obtener los valores independientemente del orden en que se encuentren?

Necesito encontrar los valores Width, height independientemente de si están antes que el src o después


Gracias


« Última modificación: 19 Diciembre 2015, 19:18 pm por Lekim » En línea

El Benjo


Desconectado Desconectado

Mensajes: 390



Ver Perfil WWW
Re: Problema con Expresiones regulares
« Respuesta #1 en: 19 Diciembre 2015, 19:39 pm »

Prueba primero obteniendo todas lás imágenes buscando únicamente la etiqueta "<img />" y por cada item devuelto realizas la busqueda de su height, después la búsqueda de su width, etc.


En línea

www.es.neftis-ai.com

Sí hay un mejor lenguaje de programación y es ese con el que puedes desarrollar tus objetivos.
mOrfiUs0

Desconectado Desconectado

Mensajes: 10

Searching job...


Ver Perfil WWW
Re: Problema con Expresiones regulares
« Respuesta #2 en: 19 Diciembre 2015, 20:49 pm »

Hola.
En ingeniería existe una máxima que a veces se olvida:
Divide y Vencerás
Prueba con bloques "<img(.*?)/>" y analiza con un regex más simple la casuística.
Para hacer scraping hay varias librerías que simplifican el trabajo, como RestSharp

Acabo de publicar un código que hace uso intensivo de regex, pero está en c#.
Y te recomiendo que mires tutoriales antes de meterte de lleno. La web del guille en su día tenía ejemplos muy buenos. Regex es una herramienta muy potente, pero requiere de un aprendizaje previo, a mi modo de ver.

Saludos!!
En línea

If you need a custom development, please contact via email.
apifilmaffinityimdb[[at]]g m ail.com
Eleкtro
Ex-Staff
*
Desconectado Desconectado

Mensajes: 9.709



Ver Perfil
Re: Problema con Expresiones regulares
« Respuesta #3 en: 20 Diciembre 2015, 04:01 am »

@Lekim
Se que esto te va a gustar tan poco como cuando te aconsejé que era absurdo e ineficiente utilizar los wrappers de Vb6 en Vb.Net (el código fuente habla por si solo), y se que no te gustan mis "tochos", no me cojas más manía... ;) pero ahí va:

Utilizando el sistema de las expresiones regulares con Regex ocurre que sólo obtiene los valores siempre y cuando estén el orden establecido en el pattern:s

En .Net, RegEx se debería utilizar solamente cómo último recurso, cuando no nos quedan ideas para llevar a cabo esa tarea, o para escribir algoritmos con más rapidez cuando nos es indiferente el rendimiento y solo queremos acabar de escribir el algoritmo, pero lo cierto es que siempre habrá otro recurso más óptimo que reemplace a RegEx si estamos desarrollando en .Net. A pesar de lo que he dicho, el motor RegEx de .Net es sofisticadísimo, ahora no recuerdo en que principios/fórmulas se basa (soy un inepto en matemáticas de todas formas), pero en ciertas circunstancias puede superar en velocidad a un simple String.Split.

Dicho esto, algo muy importante a tener en cuenta es que los motores RegEx no se idearon ni diseñaron para parsear Html o lenguajes de markups en general; es un completo overkill hacer eso, con respecto al rendimiento y estabilidad de tu algoritmo en general.

De todas formas, si, puedes hacerlo.

Si desconoces el orden de los factores entonces no debes utilizar índices de grupos, debes construir los grupos tu mismo.

Fíjate que el indexer de la class GroupCollection tiene un overload que acepta un nombre de grupo:



...Eso debería llevarte a la siguiente conclusión: se pueden agrupar las capturas por nombres de grupo.

Para ello, esta es la sintaxis adecuada:
Código:
(?<NombreDeGrupo>|Expresión de búsqueda)

donde (? es la apertura de grupo.

Aquí tienes la solución, pero he eliminado el atributo height para que hagas tu el resto del trabajo :P:

Código
  1. Dim value1 As String = "<img width=""128"" src=""...""/>"
  2. Dim value2 As String = "<img src=""..."" width=""256""/>"
  3.  
  4. Dim rgx As New Regex("img\s+(src\=.+width\=\""(?<width>|(\d+))\""|width\=\""(?<width>|(\d+))\"".+src\=.+)")
  5.  
  6. Console.WriteLine(rgx.Match(value1).Groups("width").Value)
  7. Console.WriteLine(rgx.Match(value2).Groups("width").Value)

Aquí tienes otro código de ejemplo:

EDITO: Y aquí más info sobre el tema (pero cuidado, la sintaxis RegEx es para perl):



¿Como puedo obtener los valores independientemente del orden en que se encuentren?

Como te indiqué arriba es la manera de hacerlo mediante expresiones regulares, pero como también dije al principio, no se debe hacer,
la razón es simple, aparte de que no es apto, no es lo recomendable por Microsoft, y RegEx es un mecanismo (muy) lento;
aparte de todo eso también es completamente innecesario, ya que la maravillosa IDE de Microsoft tiene un interprete/parser en tiempo de diseño para lenguajes de markups, es practicamente lo mismo para Html y Xml.

Una manera sería tan sencilla como obtener el string del documento que quieres parsear, convertirlo a otro formato más amistoso para la tarea (HtmlDocument o XDocument), obtener el elemento (mediante LINQ, o una expresión XPath, o el intérprete en tiempo de diseño), y leer el atributo del elemento.

Pseudo-ejemplo:
Código
  1. Dim html As XDocument = XDocument.Load("source-code")
  2. Dim value As String = html.<body>.<element>.@attribute

Otro ejemplo:
Código
  1. Dim el As XElement =
  2.    <img src="..."
  3.        height="128"
  4.        width="128"
  5.        alt="..."
  6.    />
  7.  
  8. Dim width As Integer = CInt(el.@width)
  9. Dim height As Integer = CInt(el.@height)

PD: Además, siempre puedes optar por utilizar los métodos de esas classes si lo prefieres en lugar de parsear el documento en tiempo de diseño.

Saludos
« Última modificación: 20 Diciembre 2015, 08:52 am por Eleкtro » En línea


Lekim

Desconectado Desconectado

Mensajes: 268



Ver Perfil
Re: Problema con Expresiones regulares
« Respuesta #4 en: 25 Diciembre 2015, 19:23 pm »

Hola y felices fiestas para quien las celebre

Gracias a todos por las respuestas. He tardado en responder porque ahora estoy currando y no he tenido tiempo para mí y para programar.

Tras probar varios sistemas me inclino por Regex.  XDocument es para XML y HtmlDocument me obliga a usar WebBroser y parsear desde  el evento DocumentCompleted y tarda un huevo  :-\

También he probado con mshtml.IHTMLDocument2:

Código
  1. Imports mshtml 'Debe agregarse la referéncia Microsoft.mshtml para que esté disponible
  2. Public Class Form1
  3.  
  4.    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
  5.        Dim CodeHtml As String = Nothing
  6.        Using CodeFromStream As System.IO.Stream = GetHttpStream("http://www.google.es")
  7.            '///Convierte Stream a String con codificación  EncodingHtml
  8.            Try
  9.                Dim streamRead As System.IO.StreamReader = _
  10.                            New System.IO.StreamReader(CodeFromStream, System.Text.Encoding.GetEncoding(name:="utf-8"))
  11.                CodeHtml = streamRead.ReadToEnd()
  12.                While CodeHtml = ""
  13.                    My.Application.DoEvents()
  14.                End While
  15.            Catch ex As Exception
  16.            End Try
  17.        End Using
  18.  
  19.        ' Obtain the document interface
  20.        Dim htmlDocument As IHTMLDocument2 = DirectCast(New HTMLDocument(), IHTMLDocument2)
  21.        ' Construct the document
  22.        htmlDocument.designMode = "On" 'Evita error script
  23.        htmlDocument.write(CodeHtml)
  24.        ListBox1.Items.Clear()
  25.  
  26.        'IMG
  27.        Dim allElements As IHTMLElementCollection = htmlDocument.body.all.Tags("img")
  28.        For Each element As IHTMLElement In allElements
  29.            Try
  30.                ListBox1.Items.Add(element.getAttribute("src"))
  31.                ListBox1.Items.Add(element.getAttribute("width"))
  32.                ListBox1.Items.Add(element.getAttribute("height"))
  33.                ListBox1.Items.Add(element.getAttribute("alt"))
  34.  
  35.            Catch ex As Exception
  36.            End Try
  37.        Next
  38.  
  39.        ' Dim imgElements As IHTMLElementCollection = htmlDocument.images
  40.        'For Each img As IHTMLImgElement In imgElements
  41.        ' ListBox1.Items.Add(img.href)
  42.        ' ListBox1.Items.Add(img.width)
  43.        ' ListBox1.Items.Add(img.height)
  44.        'Try
  45.        '  ListBox1.Items.Add(img.alt)
  46.        'Catch ex As Exception
  47.        ' End Try
  48.        ' Next
  49.  
  50.    End Sub
  51.  
  52.  
  53. #Region "Obtener código página"
  54.    Function GetHttpStream(ByVal url As String) As System.IO.Stream
  55.  
  56.        Dim MyWebRequest As System.Net.HttpWebRequest
  57.        Dim MyWebResponse As System.Net.HttpWebResponse
  58.        Dim CodeStream As System.IO.Stream = Nothing
  59.        Try
  60.            MyWebRequest = CType(System.Net.WebRequest.Create(url), System.Net.HttpWebRequest)
  61.            With MyWebRequest
  62.                .UserAgent = "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.2; .NET CLR 1.1.4322; .NET CLR 2.0.50727)"
  63.                '.Method = "GET"
  64.                '.Timeout = 10000
  65.                '.ProtocolVersion = System.Net.HttpVersion.Version10
  66.            End With
  67.            MyWebResponse = CType(MyWebRequest.GetResponse(), System.Net.HttpWebResponse)
  68.            CodeStream = MyWebResponse.GetResponseStream()
  69.  
  70.  
  71.        Catch ex As Exception
  72.            MessageBox.Show(ex.Message)
  73.        End Try
  74.  
  75.        Return CodeStream
  76.  
  77.    End Function
  78. #End Region
  79. End Class
  80.  


Pero no me devuelve el Width ni el Height. Siempre devuelve 0, no se porqué.

Por otro lado HtmlDocument NO devuelve todos los img, no sé por qué con algunas páginas no muestra todos los enlaces src siempre se deja algunos, cosa que no ocurre usando regex

Sldos
« Última modificación: 25 Diciembre 2015, 19:31 pm por Lekim » En línea

Eleкtro
Ex-Staff
*
Desconectado Desconectado

Mensajes: 9.709



Ver Perfil
Re: Problema con Expresiones regulares
« Respuesta #5 en: 25 Diciembre 2015, 20:39 pm »

XDocument es para XML

Intenta evitar el uso de mshtml por dos motivos, primero por que es innecesario para esta tarea existiendo los miembros mencionados con los que puedes hacerlo, y segundo por que está ausente de documentación oficial en su mayor parte, lo que te podría resultar una pesdailla ya que estarías condenado a un búcle trial-and-error sin salida...

Si quieres publica aquí o pásame por privado el código fuente de la página y te muestro como hacerlo.



HtmlDocument me obliga a usar WebBroser y parsear desde  el evento DocumentCompleted y tarda un huevo  :-\

En realidad no.

Es cierto que un HtmlDocument no se puede instanciar así como así, está limitado en ese sentido ya que debes usar un WebBrowser, pero simplemente lo usarías para cargar el document y listo, no tarda.

Código sacado de mi API, ElektroKit:


Código
  1. ''' ----------------------------------------------------------------------------------------------------
  2. ''' <summary>
  3. ''' Converts a string containing an Html source-code to an <see cref="HtmlDocument"/>.
  4. ''' </summary>
  5. ''' ----------------------------------------------------------------------------------------------------
  6. ''' <example> This is a code example.
  7. ''' <code>
  8. ''' Dim html As String = NetworkUtil.DownloadHtmlPage("http://www.elhacker.net/")
  9. ''' Dim htmlDoc As HtmlDocument = NetworkUtil.ConvertHtmlPageToHtmlDocument(html)
  10. ''' Console.WriteLine(htmlDoc.Body.OuterText)
  11. ''' </code>
  12. ''' </example>
  13. ''' ----------------------------------------------------------------------------------------------------
  14. ''' <param name="sourceCode">
  15. ''' The Html source-code.
  16. ''' </param>
  17. ''' ----------------------------------------------------------------------------------------------------
  18. ''' <returns>
  19. ''' The resulting <see cref="HtmlDocument"/> instance.
  20. ''' </returns>
  21. ''' ----------------------------------------------------------------------------------------------------
  22. <DebuggerStepThrough>
  23. Public Shared Function ConvertHtmlPageToHtmlDocument(ByVal sourceCode As String) As HtmlDocument
  24.  
  25.    Using wb As New WebBrowser
  26.  
  27.        wb.ScriptErrorsSuppressed = True
  28.        wb.DocumentText = ""
  29.        wb.Document.OpenNew(replaceInHistory:=True)
  30.        wb.Document.Write(sourceCode)
  31.  
  32.        Return wb.Document
  33.  
  34.    End Using
  35.  
  36. End Function

Saludos y feliz navidad a ti también.
« Última modificación: 24 Enero 2016, 14:21 pm por Eleкtro » En línea


Lekim

Desconectado Desconectado

Mensajes: 268



Ver Perfil
Re: Problema con Expresiones regulares
« Respuesta #6 en: 24 Enero 2016, 10:02 am »

Hola

Por fin me he podido poner a programar  ;-)

Perdona que sea tan cabezón, pero de verdad, no me gusta WebBrowser. Y como comenté, según que páginas no me devuelve todas los enlaces. No se porqué.

Finalmente esto es lo que usaré utilizando el sistema que me habéis comentado:

Código
  1.       '//Obtiene los enlaces
  2.        'Inicia regex para obtener el link src
  3.        Dim PatternImg As String = "<[^>]+(src)\s*=\s*""?([^"">]+)""?.*?>" '"(?i:<img.*?>)" '"<img(.*?)/>"
  4.        Dim MyRegexSRC As New Regex(PatternImg, RegexOptions.IgnoreCase)
  5.        Dim MyMatchSRC As Match = MyRegexSRC.Match(strCode)
  6.        While MyMatchSRC.Success
  7.            Dim ImgLine As String = MyMatchSRC.Groups(0).Value 'Obtiene una linea tal como: <img src="...\imagen.jpg">
  8.            Dim strLink As String = MyMatchSRC.Groups(2).Value 'Obtiene el link de una imagen
  9.  
  10.            'Inicia regex para obtener el ancho, alto y valor alt de una imagen a partir de la línea ImgLine
  11.            Dim PatternWidth As String = "<[^>]""?(?:[^>]+(width|height)\s*=\s*""?([^ "">]+)""?\s+(height|width)\s*=\s*""?([^ "">]+)""?)?(?:[^>]+(alt)\s*=\s*""?([^"">]+)""?)?" '"width=""(.*?)"""  "(?i:width="".*?.*?"")"
  12.            Dim MyRegexWidth As New Regex(PatternWidth, RegexOptions.IgnoreCase)
  13.            Dim MyMatchWidth As Match = MyRegexWidth.Match(ImgLine)
  14.  
  15.            Dim strWidth As String = MyMatchWidth.Groups(2).Value 'Obtiene el ancho
  16.            Dim strHeight As String = MyMatchWidth.Groups(4).Value 'Obtiene el alto
  17.            Dim strAlt As String = MyMatchWidth.Groups(6).Value 'Obtiene el valor Alt
  18.  
  19.            '....
  20.  
  21.            MyMatchSRC = MyMatchSRC.NextMatch() 'Continúe el bucle hasta la siguiente coincidencia.
  22.        End While

Sl2s y se agradece la ayuda.
« Última modificación: 24 Enero 2016, 10:04 am por Lekim » En línea

Páginas: [1] Ir Arriba Respuesta Imprimir 

Ir a:  

Mensajes similares
Asunto Iniciado por Respuestas Vistas Último mensaje
Expresiones regulares
Programación Visual Basic
chrominum 1 1,334 Último mensaje 30 Enero 2008, 23:09 pm
por LeandroA
Problema con expresiones regulares
Scripting
Debci 9 2,706 Último mensaje 22 Agosto 2010, 23:13 pm
por ~ Yoya ~
Problema expresiones regulares
Programación General
luiggy2 2 1,443 Último mensaje 8 Noviembre 2012, 20:32 pm
por luiggy2
[ayuda][python]problema con expresiones regulares
Scripting
daryo 3 1,302 Último mensaje 16 Enero 2014, 04:38 am
por Once
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines