Después de mucho tiempo de no publicar un Demo, vamos a compartir un pedido de una persona que necesitaba ingresar a la pagina de la SUNAT diariamente y copiar el tipo de cambio para ingresarlo en su sistema, lo ideal seria tener un Servicio Web de uso libre, pero ante la falta de este o si existe necesitaríamos las credenciales, les dejo esta solución.
Requerimiento
Obtener diariamente en forma automática el tipo de cambio de la SUNAT publicado en la siguiente dirección: http://www.sunat.gob.pe/cl-at-ittipcam/tcS01Alias
Solución
Vamos a crear una aplicación Windows en C# .NET que use la clase HttpClient para hacer una llamada asíncrona a la dirección de la pagina, bajarla a memoria, crear una cadena con el contenido y extraer la parte que corresponde al tipo de cambio del ultimo día: las 3 ultimas celdas de la ultima fila de la segunda tabla de la página.
Restricción
La aplicación podría fallar en un futuro si la SUNAT cambia su contenido agregando o quitando tablas y habría que hacer los ajustes respectivos al código, pero aun así es una ayuda por mientras.
Crear una Aplicación Windows Forms en C#
Abrir Visual Studio y crear una aplicación Windows Forms en C# llamada "TipoCambioSUNAT", cambiarle de nombre al formulario por "frmSUNAT" y realizar el diseño similar a la figura mostrada:
Hacer una referencia a la librería: "System.Net.Http.dll" y escribir el siguiente código en el formulario:
using System;
using System.Collections.Generic; //List
using System.Text; //Encoding
using System.Windows.Forms;
using System.Net.Http; //HttpClient, HttpResponseMessage
using System.IO; //File, MemoryStream
namespace TipoCambioSUNAT
{
public partial class frmSUNAT : Form
{
public frmSUNAT()
{
InitializeComponent();
}
private void btnConsultar_Click(object sender, EventArgs e)
{
HttpClient cliente = new HttpClient();
cliente.BaseAddress = new Uri("http://www.sunat.gob.pe/");
HttpResponseMessage rpta = cliente.GetAsync("cl-at-ittipcam/tcS01Alias").Result;
if (rpta != null&&rpta.IsSuccessStatusCode)
{
string contenido = "";
using(MemoryStream ms= (MemoryStream)
rpta.Content.ReadAsStreamAsync().Result)
{
byte[] buffer = ms.ToArray();
contenido = Encoding.UTF8.GetString(buffer);
contenido = contenido.ToLower();
}
if (contenido.Length > 0)
{
File.WriteAllText("Sunat.txt", contenido);
int posInicioT1= contenido.IndexOf("<table");
int posFinT1 = contenido.IndexOf("</table");
if (posInicioT1 > -1&&posFinT1>-1)
{
int posInicioT2 = contenido.IndexOf("<table",posInicioT1+1);
int posFinT2 = contenido.IndexOf("</table", posFinT1 + 1);
string tabla = contenido.Substring(posInicioT2, posFinT2 - posInicioT2 + 8);
File.WriteAllText("Tabla.txt", tabla);
posInicioT1 = 0;
tabla = tabla.Replace("</strong>", "");
List<string> valores = new List<string>();
for (int i = 1; i < 4; i++)
{
posInicioT1 = tabla.LastIndexOf("</td");
if (posInicioT1 > -1)
{
tabla = tabla.Substring(0,posInicioT1).Trim();
posFinT1 = tabla.LastIndexOf(">");
if (posFinT1 > -1)
{
valores.Add(tabla.Substring(posFinT1 + 1,
tabla.Length - posFinT1 -1).Trim());
}
}
}
if (valores.Count > 0)
{
txtVenta.Text = valores[0];
txtCompra.Text = valores[1];
txtFecha.Text = valores[2];
}
}
}
}
}
}
}
Ejecutar y Probar la Aplicación Windows Forms
Grabar la aplicación y pulsar F5 para ejecutarla, luego clic al botón "Consultar" y se mostrarán los datos del último día, el tipo de cambio compra y el tipo de cambio venta, tal como se muestra en la siguiente figura:
Comentarios
Muchas veces queremos obtener un cierto dato de una pagina y tenemos que entrar manualmente, en este post hemos visto como usando el método "GetAsync" de la clase "HttpClient" del Namespace "System.Net.Http" podemos hacerlo vía código.
En este caso lo hemos aplicado a la pagina de la SUNAT, la cual se analizó su HTML y se observó que tiene varias tablas, la segunda corresponde a la tabla con los datos de los tipos de cambios de la última semana, para lo cual se obtuvo la última fila y de esta las 3 últimas celdas.
No se hizo mediante XML porque el HTML estaba mal formado y no generaría bien el XML DOM, es por eso que trabajamos con texto puro y substrings.
Este Demo lo terminamos en colaboración con mis alumnos del Taller de los Domingos a los cuales les doy las gracias por estar siempre pendientes de aprender y querer mejorar.
Si alguien de ustedes tiene alguna URL de algún Servicio Web que consideren útil compartir por ejemplo el del Tipo de Cambio o Consulta de RUC de la SUNAT, DNI de la RENIEC, ONPE, etc. seria bueno hacer otro post pero ya usando Servicios.
Descarga del Código
DemoDia_TipoCambioSUNAT
Muy buena aplicación, excelente forma de obtener los datos del tipo de cambio. Me gusta....
ResponderBorrarBuena aplicación profesor, yo también realicé mi aplicativo de obtener el tipo de cambio de la Sunat y de la SBS aplique todo lo aprendido en el taller. Lo realicé similar al utilizando substrig con split.
ResponderBorrarSaludos.
Gracias por la aplicación. Tuve oportunidad al igual que el resto de compañeros en el taller de los fines de semana, de presenciar el desarrollo de este demo, muy buena experiencia y enviaré luego mi sugerencia de un servicio.
ResponderBorrarEs increible que le BCR, ni la SUNAT , ni la SBS, tengan publicado el tipo de cambio con Web Service. Estamos en la edad de piedra , creo qu elo hacen para evadir responsabilidades, puesto que cada uno de ellos dice fuente: xxx ECHANDOLE LA PELOTA A UNO Y TRO , que verguenza como pais
ResponderBorrarAquí les copio lo que desarrollé para PHP, espero le pueda servir a alguien:
ResponderBorrar$sUrl = "http://www.sunat.gob.pe/cl-at-ittipcam/tcS01Alias";
$sContent = file_get_contents($sUrl);
$doc = new DOMDocument();
$doc->loadHTML($sContent);
$xpath = new DOMXPath($doc);
$tablaTC = $xpath->query("//table[@class='class=\"form-table\"']"); //obtenemos la tabla TC
$filas = [];
foreach($tablaTC as $fila){
$filas = $fila->getElementsByTagName("tr"); //obtiene todas las tr de la tabla de TC
}
$tcs = array(); //array de tcs, por dia como clave
foreach($filas as $fila){//recorremos cada tr
$tds = [];
$tds = $fila->getElementsByTagName("td");
$i = 0;
$j = 0;
$arr = [];
$dia = "";
foreach($tds as $td){//recorremos cada td
if($j == 3){
$j = 0;
$arr = [];
}
if($j == 0){
$dia = trim(preg_replace("/[\r\n]+/", " ", $td->nodeValue));
$tcs[$dia] = [];
}
if($j > 0 && $j < 3){
$tcs[$dia][] = trim(preg_replace("/[\r\n]+/", " ", $td->nodeValue));
}
$j++;
}
}
Josué Rodriguez P.
Este comentario ha sido eliminado por el autor.
BorrarHola no tendras en php
ResponderBorrarAlguien con el codigo en PHP..... Gracias
ResponderBorrarcon vb habrá?
ResponderBorrar