Desglosar un string en partes.

Iniciado por **Aincrad**, 26 Diciembre 2018, 21:21 PM

0 Miembros y 1 Visitante están viendo este tema.

**Aincrad**

#10
Ptamadre si es verdad xd, ya la Solucionado gracias.





Eleкtro

#11
Te respondo por aquí al privado...

en esta parte de tu código obtienes una respuesta con un documento en JSON:

Código (vbnet) [Seleccionar]
Dim URLDATA As String = cliente.DownloadString(url)
TextBox2.Text = URLDATA


Mediante el ejemplo que te mostré, deserializas ese JSON, tal que así:

Cita de: Elektro
Código (vbnet) [Seleccionar]
   <Serializable>
   Public NotInheritable Class MyType
       Public Property [Error] As Boolean
       Public Property Title As String
       Public Property Duration As Integer
       Public Property File As String
   
       Public Sub New()
       End Sub
   
       Public Overrides Function ToString() As String
           Return New JavaScriptSerializer().Serialize(Me).ToString
       End Function
   End Class

Código (vbnet) [Seleccionar]
Dim obj As MyType = New JavaScriptSerializer().Deserialize(Of MyType)(URLDATA)

Y por último, en la propiedad MyType.File tienes la url al archivo .mp3 que puedes descargar, por ejemplo usando la función cliente.DownloadFile().

Código (vbnet) [Seleccionar]
cliente.DownloadFile(obj.File, IO.Path.GetFileName(obj.File))




No tiene que ver con el tema, pero ya que estás abierto a escuchar críticas, pues acabo de fijarme en esta parte del código donde usas esta expresión regular...

Citar
Código (vbnet) [Seleccionar]
   Private Function getID(ByVal url As String) As String 'Function by Stack Overflow Forum.
       Try

           Dim myMatches As System.Text.RegularExpressions.Match
           Dim MyRegEx As New System.Text.RegularExpressions.Regex("youtu(?:\.be|be\.com )/(?:.*v(?:/|=)|(?:.*/)?)([a-zA-Z0-9-_]+)", RegexOptions.IgnoreCase) 'This is where the magic happens/SHOULD work on all normal youtube links including youtu.be
           myMatches = MyRegEx.Match(url)
           If myMatches.Success = True Then
               Return myMatches.Groups(1).Value
           Else
               Return ""
           End If
       Catch ex As Exception
           Return ex.ToString
       End Try
   End Function

y... bueno. Me limitaré a decir que copiar cosas publicadas por programadores random de Internet con conocimientos mediocres sobre el lenguaje que están manipulando, conlleva a aprender y acostumbrarse a malas prácticas de programación.

En no pocas ocasiones, el uso de expresiones regulares es un planteamiento totálmente innecesario y con un margen de error (falsos positivos y fallos de captura) que puede llegar a ser excesivamente elevado, y por ende, intolerablemente ineficiente. Aparte, si ya de por sí el motor RegEx de .NET (y de cualquier otro) supone un impacto negativo en el rendimiento de la aplicación, las expresiones regulares complejas son sinónimo de un impacto negativo aun mayor.

(en tu aplicación el impacto será inapreciable, insignificante. No es algo de lo que debas preocuparte, pero yo siempre hablo en términos generales.)

RegEx es el recurso fácil y multi-usos. En muchas ocasiones es tan fácil de aplicar una expresión regular que nos olvidamos de que podemos hacer las cosas de forma más eficiente... aunque no será posible hacerlo mejor en todos los casos, pero en muchos sí, cómo este.

A continuación te mostraré como puedes y deberías obtener la id de un video de Youtube usando los miembros built-in más apropiados disponibles en la librería de clases de .NET Framework sin tener que recurrir al uso de expresiones regulares.

Bueno, primero estas funciones reutilizables que he escrito:

Código (vbnet) [Seleccionar]
Public Shared Function GetQuery(ByVal url As String) As NameValueCollection
   Return GetQuery(url, Encoding.UTF8)
End Function

Public Shared Function GetQuery(ByVal url As String, ByVal enc As Encoding) As NameValueCollection
   Return GetQuery(New Uri(url), enc)
End Function

Public Shared Function GetQuery(ByVal uri As Uri) As NameValueCollection
   Return GetQuery(uri, Encoding.UTF8)
End Function

Public Shared Function GetQuery(ByVal uri As Uri, ByVal enc As Encoding) As NameValueCollection
   Dim queryString As String = uri.GetComponents(UriComponents.Query, UriFormat.UriEscaped)
   Return HttpUtility.ParseQueryString(queryString, enc)
End Function


Y entonces...
Código (vbnet) [Seleccionar]
Dim query As NameValueCollection = GetQuery("https://www.youtube.com/watch?v=FtcVlSytJF4&feature=em-uploademail")
Dim id As String = query("v")
If String.IsNullOrEmpty(id) Then
   Throw New NullReferenceException()
Else
   ' ...
End If


PD: cabría destacar que, Microsoft, para algunas implementaciones internas hace uso de la clase RegEx, pero usar cualquier miembro de la librería de clases de .NET Framework cuya implementación interna recurra al uso de expresiones regulares, siempre será mejor opción y más seguro que implementar tu propio algoritmo 'home-made' de análisis de string mediante expresiones regulares aleatorias cuya eficacia en no pocas ocasiones es más que cuestionable de lo ofusca que es su sintaxis o los ejemplos de captura (si es que el autor proporciona alguno)...

Saludos.








**Aincrad**

Gracias por responder , ya termine la app, pero se blockea un poco al principio cuando esta obteniendo los datos. me puedes ayudar con eso?

otra cosilla >

'HttpUtility' no está declarado. Puede que esté inaccesible debido a su nivel de protección.

debo importar algo?




Eleкtro

#13
Cita de: **Aincrad** en 28 Diciembre 2018, 02:53 AM
'HttpUtility' no está declarado. Puede que esté inaccesible debido a su nivel de protección.
debo importar algo?

Sí, debes añadir una referencia el ensamblado System.Web.dll, e importar el espacio de nombres System.Web.

Si colocas el puntero del ratón sobre el nombre "HttpUtility" en esa linea de código que te da error, Visual Studio te dice el ensamblado que debes referenciar. Al menos en Visual Studio 2013, 2015 y 2017; no recuerdo si en VS 2010 también.




Cita de: **Aincrad** en 28 Diciembre 2018, 02:53 AMse blockea un poco al principio cuando esta obteniendo los datos. me puedes ayudar con eso?

WebClient.DownloadString y WebClient.DownloadFile son métodos sincrónicos, o lo que se conoce como una llamada bloqueante. Debido a que estás llamando a ese método en el thread de la UI, la UI se "bloquea" hasta que el método haya finalizado su ejecución (conectar con el servidor, procesar la query, esperar la respuesta del servidor, etc...) y eso dura un par de segundos... en los que la UI deja de procesar mensajes de ventana.

Para solucionarlo, debes hacer uso de programación asíncrona, y para ello practicamente debes modificar casi todo tu algoritmo. Para empezar, debes usar los métodos asíncronos de la clase WebClient. Puedes recurrir a dos metodologías distintas:

1. Usar los métodos WebClient.DownloadStringAsync() y WebClient.DownloadFileAsync, y suscribirte a los eventos WebClient.DownloadStringCompleted y WebClient.DownloadFileCompleted.

2. Usar las funciones WebClient.DownloadStringTaskAsync() y WebClient.DownloadFileTaskAsync, junto al uso de los operadores Async y Await.

La segunda metodología es más simple/sencilla de aplicar, requiere menos cambios en el código original. Lamentablemente en .NET 4.0 no puedes aplicar dicha metodología, puesto que las funciones mencionadas no están disponibles. Así que estás limitado a tener que recurrir a la primera metodología.

Aquí tienes la documentación oficial del método WebClient.DownloadStringAsync():

Y aquí un ejemplo de código:

PD: el modo de empleo del método WebClient.DownloadFileAsync es practicamente igual que en el ejemplo provisto, solo cambia el nombre del evento al que debes suscribirte, el cual ya mencioné.

Un saludo.




EDITO: bueno, por si al final te resulta dificil el uso de WebClient.DownloadStringAsync(), y cómo alternativa, la opción más sencilla y cutre para resolver el problema con el mínimo de cambios requeridos en tu código actual, sería de la siguiente forma:

Código (vbnet) [Seleccionar]
Private Sub descarga(ByVal url As String)

   Dim isCompleted As Boolean

   Dim t As New Task(
       Sub()
           Try
               Dim URLDATA As String = cliente.DownloadString(url)
               Me.Invoke(Sub()
                             TextBox2.Text = URLDATA
                             If TextBox2.Text = "" Then
                                 alert("error", "No response was obtained from the server.")
                             Else
                                 alert("alert", "Data Obtained, Descripting ...")
                             End If
                         End Sub)
           Catch ex As Exception
               Me.Invoke(Sub() alert("error", ex.Message))

           Finally
               isCompleted = True
           End Try
       End Sub)

   t.Start()

   Do Until isCompleted
       Application.DoEvents()
   Loop

End Sub


...pero el uso de ese código implica malas prácticas de programación, tenlo en cuenta.








**Aincrad**

Gracias una vez mas!! ya no se congela. te lo envie para que me digas que tal quedo.

ahora buscare una api para descargar en mp4 y 3gp y la agregare al proyecto.




Eleкtro

Cita de: **Aincrad** en  1 Enero 2019, 17:12 PM
ahora buscare una api para descargar en mp4 y 3gp y la agregare al proyecto.

Hace unos años probé 'libvideo' y me funcionó de maravilla...


Saludos