CAPITULO 2 UNA MUESTRA DE EL PODER DE C #

Hola que tal como estan, antes que nada disculpen por la tardanza de este capitulo 2 de C# pero pues hubo varias condiciones criticas que me impidieron seguir con esto.

Ahora ya estamos instalados en otra oficina nueva y pues con ya todo configurado vamos a recomenzar a trabajar en este nuevo capitulo

Pues bien tanto asi como un capitulo 2 de la serie de C# no va a ser puesto que aqui voy a tratar de demostrar lo poderosa que puede ser esta plataforma.

En dias pasados me vi en la necesidad de conseguir un nuevo empleo y pues note que la perdida de tiempo que se genera del revisar miles de anuncios que no eran de mi area de trabajo en sitios como mexplaza y el informador pues era excesiva por lo que me di a la tarea de crear un pequeño programita que me auxiliara a seleccionar los avisos que correspondian a mi perfil de trabajo, a esto le sume que al encontrar un aviso de esta indole le mandara por correo mi curriculum con un mensaje ya preestablecido y si no tenia mail que me mandara a mi el telefono y el contacto, a lo mejor no suena como algo super util pero creanme que a mi me sirvio bastante. El programita esta operando y una amiga de mi extrabajo a quien estimo muchisimo le puso el nombre de “Autoseek” (Gracias Paty) a lo que yo le agregaria una palabra mas como Autoseek empleos o Autoseek Pareja porque puedes modificarlo para que busque en distintas tablas de clasificados

Bueno despues de el rollo vamos a pasar a el “Y como hago eso??” la verdad el programa es sencillo consta de una busqueda por palabras claves una clase que baja el contenido del html con los anuncios y los regresa a una cadena, la seccion del mail y ya Simple

Buno lo primero es tener la informacion cierto? Vamos a bajarla de Mexplaza de la UDG ok la direccion es http://clasificados.mexplaza.com.mx/cgi-bin/clasificados/listarempleos.cgi , esta direccion ejecuta un cgi y nos regresa un listado semi estructurado de empleos disponibles ordenados por fechas de publicacion, ahora bien, necesito esa informacion en una cadena o archivo o lo que sea para poder analizarla, entonces vamos a crear una clasesita que haga esto:

Al principio veran que el codigo puede resultar algo extraño pero en realidad es muy sencillo:

using System;

using System.Text;

using System.IO;

using System.Net;

public class RegresaAvisos

{

public void Descarga (out string strPagina,string strDir){

WebRequest peticion = WebRequest.Create(strDir);

WebResponse resultado = peticion.GetResponse();

int iBuffer = 0;

Byte[] Buffer = new Byte[128];

Stream datos = resultado.GetResponseStream();

iBuffer = datos.Read(Buffer, 0, 128);

StringBuilder strTotal = new StringBuilder("");

while(iBuffer != 0)

{

strTotal.Append(Encoding.ASCII.GetString(Buffer, 0, iBuffer));

iBuffer = datos.Read(Buffer, 0, 128);

}

strPagina = strTotal.ToString();

}

}

Creen que con este codigo me baje una pagina entera? Esta algo dificil de creer no, incluso yo imaginaba que seria mas codigo pero aqui esta ahora vamos a analizarlo. Lo primero es incluir las clases adecuadas del espacio System para tratar texto, para entrada y salida y de los componentes de web en orden de aparicion, ya que tenemos esto pues hacemos una clasesita simple con un solo metodo. La clase se llama RegresaAvisos y lo que hara es recibir una URL como parametro y devolvera el cuerpo de la pagina entero a fin de que sea analizado en una cadena

 

Ok una ves que tenemos esta clase pues hay que ver si funciona ya que no pretendo que me crean a ciegas asi que si gustan en el mismo codigo hacemos una aplicacioncita de consola simple y sin chiste, que instancie un objeto del tipo RegresaAvisos, le pase el URL de los clasificados e imprima la cadena resultante en pantalla

Aqui esta el codigo por si no le quieren pensar como hacerla:

class Prueba

{

public static void Main()

{

string strOut;

RegresaAvisos web = new RegresaAvisos();

web.Descarga( out strOut,"http://clasificados.mexplaza.com.mx/cgi-bin/clasificados/listarempleos.cgi");

Console.WriteLine(strOut);

}

 

}

}

 

Simple no? la ejecutamos y veremos que trae algo asi:


Ahora bien, ya tenemos lo menos dificil que es la informacion y ahora que?? Que hago con esa informacion. Tenemos que analizarla a fin de que el programa sea lo suficientemente "inteligente" como para decidir a que trabajos nos va a mandar no? si no imaginate que te llaman para vender productos naturistas cuando eres arquitecto o ingeniero en sistemas, creo que no seria muy alentador no crees? . Pues entonces habra que buscar un estandar en el que viene el archivo y a hacer talacha de contar caracteres , hacer splits y demas. Antes que nada debemos limpiar el archivo de todos los tags de HTML que trae y demas cosas que vienen como estandar del archivo y no nos sirven por lo que haremos un metodo al que yo le puse limpia() que se va a encargar de regresarme una version mas clara de mi informacion.

public void limpia(string T){

 

T=T.Replace("<font color=#000099>","");

T=T.Replace("<img src='http://clasificados.mexplaza.com.mx/imagen/pleca.gif'>","");

T=T.Replace("/","");

T=T.Replace("\"","");

T=T.Replace("<font>","");

T=T.Replace("<br>","");

T=T.Replace("<blockquote>","");

T=T.Replace("<p>","");

T= Regex.Replace(T, @"<!-- inicio, ", "");

T=T.Replace("<center>","");

T=T.Replace("<!-- fin -->","");

T=T.Replace("<a>","");

T=T.Replace("<b>","");

T=T.Replace("'mailto:","");

T=T.Replace("<a href=http:clasificados.mexplaza.com.mxcgi-binclasificadosreporteform.cgi?registro=","");

T=Regex.Replace(T,@"..........&seccion=empleos><font size=-1>Reporta el mensaje si es ofensivo","");

T=T.Replace("<a href='mailto:","");

T=T.Replace("'>","");

T=T.Replace("&seccion=empleos><font size=-1>Reporta el mensaje si es ofensivo<font><a>","");

T= Regex.Replace(T, @"<font face=arial,helvetica SIZE=2>Dise.o por: <a href=http:mexplaza.com.mx> Mexplaza","");

}

 

Hasta aqui limpia lo que hace es tomar un parametro string y limpiarlo de todo lo que yo le indico en el codigo, pero que es eso de Replace y Regex y todo el choro de datos, ok C# tiene una caracteristica que si bien es muy util tambien tiene funcionando en unix desde sus inicios que son las Expresiones Regulares, estas expresiones nos permiten hacer busquedas y Match con cualquier cadena para hacerla como queramos, si alguien a usado Perl estoy seguro que sabe que es una expresion regular. En C# se manejan mediante la clase Regex y se encuentra dentro de la libreria de System.Text.RegularExpressions;

 

Para que uso yo las expresiones regulares?? Ok si observas hay en la cadena de mexplaza bastantes cosas que si bien se repiten tambien traen datos algo variables por ejemplo la linea donde se envia el reporte de anuncio ofensivo, tiene el ID del anuncio en la liga por lo que cada registro tiene uno y yo no puedo ir por alli retirandolos de uno por uno por lo que le digo al sistema que reemplaze …….&el resto de la linea, por nada y listo , los puntos en las expresiones regulares son sustituidos por cualquier caracter entonces el sistema toma 7 caracteres cualquiera y el resto de la cadena y los elimina o sea los reemplaza por nada. Para que una expresion regular lo sea , y no se piense que es una cadena normal con puntitos en este caso, se le coloca el prefijo @ antes de las comillas que habren la cadena o sea que @"Hola Mundo" seria una expresion regular. Esto de las expresiones es algo bastante interesante pero si se requiere de algunos dos capitulos para ser expertos por lo que les voy a dedicar esos capitulos en un futuro cercano de cualquier forma si les urge entrarle a esto pueden checarse la clase Regex en la documentacion de microsoft o preguntarme.

 

Ok ya que puse esta limpia pues hay que ver que me devolvio no? entonces agrego un parametro de salida : de tal forma que la funcion quede como sigue:

public void limpia(out string Limpio,string T){

 

T=T.Replace("<font color=#000099>","");

T=T.Replace("<img src='http://clasificados.mexplaza.com.mx/imagen/pleca.gif'>","");

T=T.Replace("/","");

T=T.Replace("\"","");

T=T.Replace("<font>","");

T=T.Replace("<br>","");

T=T.Replace("<blockquote>","");

T=T.Replace("<p>","");

T= Regex.Replace(T, @"<!-- inicio, ", "");

T=T.Replace("<center>","");

T=T.Replace("<!-- fin -->","");

T=T.Replace("<a>","");

T=T.Replace("<b>","");

T=T.Replace("'mailto:","");

T=T.Replace("<a href=http:clasificados.mexplaza.com.mxcgi-binclasificadosreporteform.cgi?registro=","");

T=Regex.Replace(T,@"..........&seccion=empleos><font size=-1>Reporta el mensaje si es ofensivo","");

T=T.Replace("<a href='mailto:","");

T=T.Replace("'>","");

T=T.Replace("&seccion=empleos><font size=-1>Reporta el mensaje si es ofensivo<font><a>","");

T= Regex.Replace(T, @"<font face=arial,helvetica SIZE=2>Dise.o por: <a href=http:mexplaza.com.mx> Mexplaza","");

Limpio=T;

Y listo ya tengo la cadena de la siguiente forma:

Ahora lo que tengo que hacer es separar la informacion del resto de la basura que es mas inestable (tanto que no la quite) y separar los campos de los valores por el caracter de ':' de tal forma que podamos crear un documento util ya con los trabajos que nos interesen en formato XML para que el metodo que envie el correo lo haga de una forma mas eficiente asi que creamos un metodo llamado separa el cual va como sigue:

 

public void parte(string Modelo){

string[] Registros=Modelo.Split('>');

}

Con esto lo que voy a obtener es un arreglo llamado Registros  que contendra a partir de la posicion 13 y cada numero impar de indice un registro de un anuncio completo

A partir de aqui podemos separar cada una de esa posiciones por el caracter de retorno de carro y tendriamos por registro un arreglo de 11 posiciones que contendrian el dato y su nomenclatura en el mismo elemento separados por ': '

Simple no?

Vamos a hacer esto en codigo y poco a poco despues lo iremos refinando para no perdernos tan drasticamente, a partir de aqui vamos a usar un estandar que ya debemos conocer :XML es muy sencillo si nunca lo has manejado o visto siquiera aqui vamos a ver muy pero muy basicamente que onda ok?

Va:

 

De entrada voy a manejar una funcion carnicera (porque parte la cadena ;) ) que seria la siguiente:

public void parte(string Modelo){

string[] Registros=Modelo.Split('>');

Console.WriteLine(Registros[13]);

string[] datos=Registros[13].Split('\n');

escribeXML(datos);

}

 

Esta funcion me separara la cadena cada vez que encuentre un caracter > de esta forma tendremos el cuerpo de los datos en los numeros impares del arreglo y la basura en los pares ,despues aqui solo tomo un registro y lo separo por lineas .Asi de simple tendria un arreglo de cadenas llamado Registros donde estaran los datos que necesito, siempre vamos a tener aun algo de basura asi que habra que fijarnos en que index de Registros comienzan los datos utiles, de esto se encargara la funcion que escriba el XML ok?

Pero, como voy yo a escribir un XML???? Facil la verdad suena mas complejo de lo que es, para escribirlo usare esta funcion:

 

void escribeXML(string[] aviso) {

string archivo="Empleos.xml";

XmlTextWriter escribano=new XmlTextWriter(archivo,null);

escribano.Formatting=Formatting.Indented;

escribano.WriteStartDocument();

escribano.WriteStartElement("Mensaje");

escribano.WriteElementString("from","[email protected]");

escribano.WriteElementString("to",aviso[10]);

escribano.WriteElementString("subject","Empleo");

escribano.WriteElementString("mensaje","le anexo mi curriculo para que sea considerado para el puesto:"+aviso[6]);

escribano.WriteStartElement("Adjuntos");

escribano.WriteElementString("atachmment","micurriculo.doc");

escribano.WriteEndElement();

escribano.WriteEndDocument();

escribano.Flush();

escribano.Close();

}

 

}

 

Como pueden observar el asunto de escribir un XML no es la gran ciencia, se usa una clase llamada XmlTextWriter a la que le paso el archivo , se le formatea para que este identado, se inicializa o sea se coloca la etiqueta que lo ubica como un xml y despues simplemente se escriben los elementos, al hacer un StarElement se crea un elemento y se cierra al final del archivo inmediatamente despues del ultimo elemento abierto por ejemplo aqui estoy creando <mensaje> </mensaje> que delimita el cuerpo del mensaje.

La parte del WriteElementString escribe un elemento de la siguiente forma: <from>[email protected]</from> ya que el primer parametro es el nombre que llevara el tag y el segundo es el valor de ese tag , si observan la parte de adjuntos esta un poquito diferente ya que inicio de nuevo un elemento asi como mensaje y dentro de el coloco el attachment de mi curriculum. Cierro el Elemento y luego el documento, al final con el metodo flush descargo la informacion al archivo y lo cierro, simpel no?

 

Hasta ahorita este metodo me regresa un archivo XML como el siguiente:

<?xml version="1.0"?>

<Mensaje>

<from>[email protected]</from>

<to>E-mail: [email protected]@autos.com.mx </to>

<subject>Empleo</subject>

<mensaje>le anexo mi curriculo para que sea considerado para el puesto:Descripci&amp;oacute;n: 12 tiempo, horario flexible</mensaje>

<Adjuntos>

<atachemment>micurriculo.doc</atachemment>

</Adjuntos>

</Mensaje>

si corto y pego estas instrucciones en un archivo llamado "comoyoquiera.xml" y lo abrimos con internet explorer veremos lo siguiente:

Si observas internet explorer tiene el soporte adecuado para hacer un parsing sobre el XML I agregar los signos de - a la izquierda de los elementos , signos que si los presionamos veremos como se contrae o se expande el contenido del elemento. Preso bueno asi la verdad no me sirve de nada , solamente para analisis y para otras aplicaciones pero a mi humano no me dice mucho y hasta se ve fellito no?

 

Aqui ya tenemos que todos los avisos estan en un XML para que sea mas facil su procesamiento, pero que tal si quiero saber a que anuncios le contesto por mi el sistema? Que mejor que tener un reporte diario no?

 

 

Hosted by www.Geocities.ws

1