Página 1 de 1

Guardar datos de un documento HTML

Publicado: Lun Mar 13, 2023 2:06 am
por ryder1912
Buenas a todos. Consulta, como hago para guardar datos de un documento Html.
Los datos se leen mediante una consulta a la pagina del banco nación (argentina) para obtener la cotización del dólar y como respuesta me devuelve un Html.
El Html de respuesta es un poco largo asi que solo voy a postear la ultima parte. La idea es obtener los datos que vienen a partir del <td> y ponerlos en un array

Código: Seleccionar todo

<div id="cotizacionesCercanas">
    <p class="tituloCotizador">La cotizaciones más cercanas a la fecha solicitada son:</p>
<br clear="all" />
        <div id="tablaDolar" style="text-align:left;">
           <h4 class="cotizador" >Dolar U.S.A</h4>
            <table class="table table-bordered cotizador" >
                    <thead>
                    <tr>
                        <th>Monedas</th>
                        <th>Compra</th>
                        <th>Venta</th>
                        <th>Fecha</th>
                    </tr>
                    </thead>
                    <tbody>
                                        <tr>
                                            <td>Dolar U.S.A</td>
                                            <td class="dest">200.1600</td>
                                            <td class="dest">200.3600</td>
                                            <td>9/3/2023</td>
                                        </tr>
                                        <tr>
                                            <td>Dolar U.S.A</td>
                                            <td class="dest">200.5300</td>
                                            <td class="dest">200.7300</td>
                                            <td>10/3/2023</td>
                                        </tr>

                    </tbody>
            </table>
        </div>

</div>
Este es el código con el que obtengo el Html. Es una función

Código: Seleccionar todo

Function GetCotizacionDolarDivisaBNA()
local aDatCot:={}, oWinHTTP, cURL, cRespuesta
local oDocHtml, oNode
  
      * Creo y Valido el Objeto oWinHTTP
      oWinHTTP := CreateObject( 'MSXML2.XMLHTTP' )
      If Empty(oWinHTTP)
         MsgAlert( 'NO se Pudo Crear el Objeto oWinHTTP', 'Error de Programa')
         Return Nil
      End

      cURL:="https://www.bna.com.ar/Cotizador/HistoricoPrincipales?id=monedas&fecha=27/01/2023&filtroEuro=0&filtroDolar=1"
     * Llamo al Webservice y Defino Opciones
      oWinHTTP:Open( 'GET', cURL, .F. )

      oWinHTTP:SetRequestHeader( "Content-Type" , "text/html; charset=utf-8" )

      * Envio el Archivo y Recibo la Respuesta
      oWinHTTP:Send()

      cRespuesta := oWinHTTP:ResponseText
      oDocHtml:=THtmlDocument():New(cRespuesta)
      oNode   :=oDocHtml:body:divs("tablaDolar") 
    
     // Aqui no se como seguir, la idea es poner los datos de la cotizacion en la variable aDatCot
    
      oWinHTTP:= NIL
      Release oWSFE

Return aDatCot
Saludos.

Re: Guardar datos de un documento HTML

Publicado: Lun Mar 13, 2023 8:44 pm
por jfgimenez
Hola,

no necesitas usar OLE para descargar una página web. En su lugar puedes usar la clase TAsyncDownload, que además se ejecuta en un segundo hilo y no interrumpe tu programa. Adjunto un ejemplo
Test.zip
(2.51 KiB) Descargado 93 veces

Re: Guardar datos de un documento HTML

Publicado: Mié Mar 15, 2023 12:23 pm
por bingen
Hay una manera más sencilla, si te registras gratuitamente en:

https://free.currconv.com

y te dan una clave de api xxxxxxxxx podrás utilizar este código, con alguna adaptación por supuesto.

PROBLEMA La API key es solo para 1 mes y luego te la renuevan pero tendrás que cambiarla al mes y si no pagar para que te dejen en paz.
Gestión de administradores de fincas V.15.4 - xFincas.jpg
Gestión de administradores de fincas V.15.4 - xFincas.jpg (23.18 KiB) Visto 735 veces

Código: Seleccionar todo

//------------------------------------------------------------------------------
//Este es el Widget de conversión de moneda que se refresca cada hora
Method WidgetCotizacion( oSender ) CLASS TFrmMain

   WITH OBJECT ::oBevelCotizacion := TBevel():New( ::oBevelBotones )
      :nAlign := alLEFT
      :nAlignMarginLeft    := 10
      :nAlignMarginTop     := 3
      :nAlignMarginBottom  := 3
      :nWidth              := 80
      :lTransparent        := .T.
      :Create()
   END

   WITH OBJECT ::oCotizacionTitle := TLabelEx():New( ::oBevelCotizacion )
      :lAutoSize        :=.T.
      :nAlign           := alTOP
      :nHeight          := 14
      :nTooltipIcon     := tiINFO
      :lTransparent     := .T.
      :Create()
      :OnLButtonUp      := {|| WidgetCotizacionSwitch() }
      :OnRButtonDown    := {|| WidgetCotizacionSelect() }
   END

   WITH OBJECT ::oCotizacionResult := TLabelEx():New( ::oBevelCotizacion )
      :lAutoSize        :=.T.
      :nAlign           := alTOP
      :nHeight          := 14
      :nTooltipIcon     := tiINFO
      :lTransparent     := .T.
      :Create()
      :OnLButtonUp      := {|| WidgetCotizacionSwitch() }
      :OnRButtonDown    := {|| WidgetCotizacionSelect() }
   END

Return Nil

//------------------------------------------------------------------------------

Function WidgetCotizacionRefresh()
   Local cDivisas:="", cOrigen:="", cDestino:="", cCambio  := ""
   Local hData := {=>}, oErr
   Local cResult:= "", cLectura

   //Tomar las divisas desde el INI
   WITH OBJECT TIni():Create( Appdata:cAppPath+"UserData\"+AppData:cUserName+".Ini" )
      cDivisas:=:GetEntry( "WidgetCotizacion", "Divisas", "USD_EUR" )
      :SetEntry("WidgetCotizacion", "Divisas", cDivisas )
      cOrigen  := :GetEntry( "WidgetCotizacion", "Origen", "US Dollar $" )
      cDestino := :GetEntry( "WidgetCotizacion", "Destino", "Euro €" )
   END WITH

   WITH OBJECT TInternet():New()
      IF :Open()
         ProcessMessages()
         hData := :OpenURL( "https://free.currconv.com/api/v7/convert?q="+cDivisas+"&compact=ultra&apiKey=xxxxxxxxxxxx" ) //Donde xxxxxxxxxxx será tu clave de API
         IF !Empty( hData )
            while :ReadFile( hData, @cLectura, 1024 )
                  cResult+= cLectura
                  ProcessMessages()
            end
            :CloseURL( hData )
         ENDIF
         :Close()
      ENDIF
   END


   If cResult<>"{}"
      hb_jsondecode( cResult, @hData )
   Else
      hData:={"Error"=>0}
   Endif

   cCambio  := Left(ToString(hb_HPairAt(hData,1)[2]),8)

   With Object Application:oMainForm:oCotizacionTitle
      :cText          := "<b><#2E2EFE> "+StrTran(hb_HPairAt(hData,1)[1],"_"," => ")
      :cTooltipTiTle := "Conversión de moneda "+cDivisas
      :cBalloon      := "1 "+cOrigen+" => " +cCambio + " "+ cDestino+CRLF+CRLF+"Haga click izquierdo para invertir el cambio y"+CRLF+"click derecho para seleccionar otras monedas"
   End

   With Object Application:oMainForm:oCotizacionResult
      :cText          := "<#886A08><h2>"+cCambio
      :cTooltipTiTle := "Conversión de moneda "+cDivisas
      :cBalloon      := "1 "+cOrigen+" => " +cCambio + " "+ cDestino+CRLF+CRLF+"Haga click izquierdo para invertir el cambio y"+CRLF+"click derecho para seleccionar otras monedas"
   End

return Nil

//------------------------------------------------------------------------------

Function WidgetCotizacionSelect()

   LOCAL hData
   LOCAL cData, cJson:="", aCurrency:={}, aData:={}, aOrigen:={}, aDestino:={}
   LOCAL nLen
   local cUrl  := "https://free.currconv.com/api/v7/currencies?apiKey=a99bcc4dacf1ccbc94fe"

   WITH OBJECT TInternet():New()
      IF :Open()
         IF !Empty( hData := :OpenURL( cUrl ) )
            WHILE :ReadFile( hData, @cData, 65536 )
               cJson += cData
            ENDDO
            :CloseURL( hData )
         ENDIF
         :Close()
      ENDIF
   END

   cJson := SubStr(cJson,12,Len(cJson)-1)
   nLen  := hb_jsondecode( cJson, @hData )

   aCurrency:=HB_HKeys(hData)

*   hb_HGetDef(hData, "currencySymbol", "")
   For nLen:=1 to Len(aCurrency)
      Try
         AAdd(aData, aCurrency[nLen]+" "+hData[ aCurrency[nLen], "currencyName"]+" "+hData[ aCurrency[nLen], "currencySymbol"] )
      Catch
         AAdd(aData, aCurrency[nLen]+" "+hData[ aCurrency[nLen], "currencyName"] )
      End
   Next

   aData :=ASort(aData)
   aOrigen  := aData
   aDestino := aData

   If !MsgEdit("Elija desde que moneda desea hacer la conversión","Conversor de divisas",@aOrigen,"Dinero")
      Return Nil
   Endif
   aDestino:=HB_ADel(aDestino,AScan(aDestino,{|x| x=aOrigen[2]}),.T.)
   If !MsgEdit("Elija a que moneda desea hacer la conversión","Conversor de divisas",@aDestino,"Dinero")
      Return Nil
   Endif

   //Grabar las divisas desde el INI
   WITH OBJECT TIni():Create( Appdata:cAppPath+"UserData\"+AppData:cUserName+".Ini" )
      :SetEntry("WidgetCotizacion", "Divisas", Left(aOrigen[2],3)+"_"+Left(aDestino[2],3) )
      :SetEntry("WidgetCotizacion", "Origen", aOrigen[2] )
      :SetEntry("WidgetCotizacion", "Destino", aDestino[2] )
   END WITH
   WidgetCotizacionRefresh()

Return Nil

//------------------------------------------------------------------------------

Function WidgetCotizacionSwitch()
   Local cDivisas:="", cOrigen:="", cDestino:=""

   //Tomar las divisas desde el INI y cambiarlos de orden
   WITH OBJECT TIni():Create( Appdata:cAppPath+"UserData\"+AppData:cUserName+".Ini" )
      cDivisas:=:GetEntry( "WidgetCotizacion", "Divisas", "USD_EUR" )
      :SetEntry("WidgetCotizacion", "Divisas", Right(cDivisas,3)+"_"+Left(cDivisas,3) )
      cOrigen  := :GetEntry( "WidgetCotizacion", "Origen", "" )
      cDestino := :GetEntry( "WidgetCotizacion", "Destino", "" )
      :SetEntry("WidgetCotizacion", "Origen", cDestino )
      :SetEntry("WidgetCotizacion", "Destino", cOrigen )
   END WITH
   WidgetCotizacionRefresh()
Return Nil

//------------------------------------------------------------------------------

Re: Guardar datos de un documento HTML

Publicado: Sab Abr 01, 2023 6:23 pm
por xhermita
No he conseguido información sobre la clase THtmlDocument, por las pruebas que hice con tu código parece que no funciona del todo bien. Así que lo he preparado con un poco de código.
Se que el uso que hago del TAsyncDownload no es muy ortodoxo, pero funciona. :D

Código: Seleccionar todo

Function GetCotizacionDolarDivisaBNA()
   LOCAL hDatCot := { "Moneda" => "", "Compra" => 0, "Venta" => 0, "Fecha" => ""}
   LOCAL cRespuesta, lOk := .F.
   LOCAL cHoy := StrZero( Day( Date() ), 2 ) + "/" + StrZero( Month( Date() ), 2 ) + "/" + StrZero( Year( Date() ), 4 )
   LOCAL nIni, nFin

   // Llamo al Webservice
   WITH OBJECT TAsyncDownload():New()
      :cURL := "https://www.bna.com.ar/Cotizador/HistoricoPrincipales?id=monedas&fecha=" + cHoy + "&filtroEuro=0&filtroDolar=1"
      :OnDisconnect := {|oSender| cRespuesta := :cBuffer, lOk := .T. }
      :Create()
      :Run()

      DO WHILE !lOk
         ProcessMessages(100)
      ENDDO

      IF :nStatus <> 200
         MsgInfo( "Error: [" + ToString( :nStatus ) + "] " + :cError )
      ENDIF

   END WITH

   IF !Empty( cRespuesta )
      nIni := HB_At( "<td>Dolar U.S.A</td>", cRespuesta )
      if nIni > 0
         // Encontrada Moneda
         hDatCot["Moneda"] := "Dolar U.S.A."
         nIni := HB_At( '<td class="dest">', cRespuesta, nIni )
         IF nIni > 0
            // Encontrada Compra
            nIni += 17
            nFin := HB_At( '</td>', cRespuesta, nIni ) - nIni
            hDatCot["Compra"] := Val( SubStr( cRespuesta, nIni, nFin ) )
            nIni := HB_At( '<td class="dest">', cRespuesta, nIni )
            IF nIni > 0
               // Encontrada Venta
               nIni += 17
               nFin := HB_At( '</td>', cRespuesta, nIni ) - nIni
               hDatCot["Venta"] := Val( SubStr( cRespuesta, nIni, nFin ) )
               nIni := HB_At( '<td>', cRespuesta, nIni )
               IF nIni > 0
                  // Encontrada Fecha
                  nIni += 4
                  nFin := HB_At( '</td>', cRespuesta, nIni ) - nIni
                  hDatCot["Fecha"] := CToD( SubStr( cRespuesta, nIni, nFin ) )
               ENDIF
            ENDIF
         ENDIF
      ENDIF
   ENDIF

RETURN hDatCot
Te devuelve un Hash con los cuatro valores (Moneda,Compra,Venta y Fecha)