Mostrando entradas con la etiqueta perl. Mostrar todas las entradas
Mostrando entradas con la etiqueta perl. Mostrar todas las entradas

martes, marzo 25, 2014

Perl, consultar el directorio activo (active directory de Windows)

Para consultas del directorio activo tendremos que instalar el módulo NET::Ldap.
Hay muchas referencias en Internet para el acceso a servidores LDAP, pero pocas se refieren al Directorio Activo de Microsoft (Active Directory).

Me he descargado el DWIMPerl para Windows, y voy a utilizar el editor perl que trae el mismo, que se llama PADRE.

Lo primero es conseguir conectarse al servidor.


Si el resultado es SUCCESS, ya podemos continuar con las consultas.

En este momento deberíamos conectarnos al directorio activo y mirar en una de las entradas que nos interesan cómo se llaman los ATRIBUTOS por lo que podemos preguntar.


Ahora que ya tenemos claro eso, podemos terminar el programa que aplica un filtro a la consulta, y luego recorre las entradas devueltas imprimiendo en pantalla los atributos que nos interesen:


Así queda el programa:


#!/usr/bin/perl

 use Net::LDAP;

 my $usuario = "dominio\\usuarioAdministrador";
 my $password = "password";
 
 my $servidorLdap = "ldap://servidor.dominio.es";

 # conexion al servidor
 $ldap = Net::LDAP -> new ($servidorLdap) || die "No me he podido conectar al servidor\n";

 # validarnos en el servidor
 $mensaje = $ldap -> bind($usuario, password => $password);
 $resultado = sprintf("%s",$mensaje->error);
 
 # Establecemos el filtro que nos interesa: 
 $filtro = "objectClass=group";

 # Lanzamos la consulta:
 $resultado = $ldap -> search(filter => "(&($filtro))", base => "DC=dominio,DC=es");
 
 # Miramos el numero de entradas que cumplen el filtro:
 my $numero = $resultado -> count;
 
 # Por cada respuesta escribimos en una linea el nombre y cuando ha cambiado la entrada:
 my $count = $resultado -> count;
 for (my $i=0; $i<$count; $i++) {
     $entry = $resultado->entry($i);
     print $entry->get_value('CN').", ".
           $entry->get_value('whenChanged')."\n";
}

 # Nos desconectamos:
 $mensaje = $ldap->unbind;

martes, noviembre 13, 2012

Calcular distancia entre dos ciudades con PERL

Como decía el otro día, necesito un programa que calcule distancias entre ciudades. No puedo ir a GOOGLE MAPS y hacerlo a mano porque hablamos de una tabla completa.

Hoy vamos a utilizar PERL.

Necesitamos descargar e instalar el módulo JSON. El sitio de descarga éste. Descargamos el fichero JSON-2.53.tar.gz. Con gunzip fichero.gz obtenemos el fichero JSON-2.53.tar. Luego con tar -xvf fichero.tar obtenemos el directorio que contiene los ficheros del módulo.

Luego compilamos el módulo:
  1. perl Makefile.PL
  2. make
  3. make test
  4. make install
 Y ahora podemos utilizarlo de la siguiente forma para acceder al API de GOOGLE MAPS:

#!/usr/bin/perl

use strict;
use warnings;

use JSON;

use LWP::UserAgent;
my $ua = LWP::UserAgent->new();

my $origin = "Vitoria-Gasteiz";
my $destination = "Bilbao";

my $site = 'http://maps.googleapis.com/maps/api/directions/';
my $mode = 'json';

my $page = $site . $mode . '?origin="' . $origin . '"&destination="' . $destination . '"&sensor=false';

my $response = $ua->get( $page );
my $json = $response->content();

my $data = decode_json $json;

my @legs = @{ $data->{'routes'}[0]{'legs'} };
my $distance_meters = 0;
foreach my $leg (@legs) {
    $distance_meters += $leg->{'distance'}{'value'};
}

my $distance_kilometers = $distance_meters / 1000;
print $distance_kilometers . " kilometros\n";

El resultado de la ejecución:

perl distancia.pl
65.311 kilometros



Código fuente descargado de aquí, aunque se han hecho un par de modificaciones.

Más información y ejemplos en la documentación de Google aquí.

Saludos,

lunes, noviembre 05, 2012

Problema del módulo Geo-Google (PERL)


CPAN es el repositorio de módulos de PERL (entre otras cosas). Ayer quería hacer un programita PERL que interrogue a Google Maps para calcular distancias entre dos ciudades.

Encontré un módulo que precisamente para hacer eso. Se llamaba GEO::GOOGLE

El caso es que para "coger destreza" en el desempaquetado (gunzip y tar), y el compilado de módulos:

perl Makefile.PL
make
make test
make install

Y sobre todo para saber identificar los errores y warnings que surgen a lo largo del proceso, decidí instalar cada dependencia a mano. En total instalé 23 módulos:

[root@xekun perl]# ls -la
total 100
drwxr-xr-x. 25 root  root  4096 Nov  5 09:04 .
drwxr-xr-x.  3 aitor aitor 4096 Nov  5 00:31 ..
drwxr-xr-x.  8 aitor aitor 4096 Nov  5 00:15 Compress-Raw-Bzip2-2.055
drwxr-xr-x.  9 aitor aitor 4096 Nov  5 00:06 Compress-Raw-Zlib-2.056
drwxr-xr-x.  5   501 games 4096 Nov  4 22:15 Digest-MD5-2.52
drwxr-xr-x.  5   501 games 4096 Nov  4 23:48 Encode-Locale-1.03
drwxr-xr-x.  5   501 games 4096 Nov  4 23:46 File-Listing-6.04
drwxr-xr-x.  5 root  root  4096 Nov  5 00:39 Geo-Google
drwxr-xr-x.  7   501 games 4096 Nov  5 00:22 HTML-Parser-3.69
drwxr-xr-x.  4   500   500 4096 Nov  4 23:08 HTML-Tagset-3.20
drwxr-xr-x.  5   501 games 4096 Nov  4 23:44 HTTP-Cookies-6.01
drwxr-xr-x.  5   501 games 4096 Nov  4 23:33 HTTP-Daemon-6.01
drwxr-xr-x.  5   501 games 4096 Nov  4 23:09 HTTP-Date-6.02
drwxr-xr-x.  5   501 games 4096 Nov  5 00:18 HTTP-Message-6.06
drwxr-xr-x.  5   501 games 4096 Nov  4 23:45 HTTP-Negotiate-6.01
drwxr-xr-x.  8 aitor aitor 4096 Nov  5 00:17 IO-Compress-2.055
drwxr-xr-x.  5 aitor aitor 4096 Nov  5 00:09 IO-HTML-0.04
drwx------.  5  1006   513 4096 Nov  5 00:27 JSON-1.12
drwxr-xr-x.  6   500   500 4096 Nov  5 00:29 JSON-2.53
drwxr-xr-x.  6   500   500 4096 Nov  5 00:32 JSON-PP-2.27200
drwxr-xr-x.  6   501 games 4096 Nov  4 23:47 libwww-perl-6.04
drwxr-xr-x.  5   501 games 4096 Nov  4 23:35 LWP-MediaTypes-6.02
drwxr-xr-x.  5   501 games 4096 Nov  4 23:46 Net-HTTP-6.03
drwxr-xr-x.  5   501 games 4096 Nov  5 00:19 URI-1.60
drwxr-xr-x.  5   501 games 4096 Nov  4 23:30 WWW-RobotRules-6.02


Bueno, total que quedó todo perfectamente instalado y funcionando, menos el dichoso módulo GEO::GOOGLE

Entonces se me ocurrió mirar los resultados de los testers del módulo y me encontré con esta desagradable sorpresa:



Como se puede ver en el enlace, no funciona prácticamente en ningun S.O. ni versión de PERL.

Lección aprendida: Antes de usar un módulo CPAN comprobar los resultados de los Testers.

Saludos,

sábado, enero 14, 2012

Perl, buscar texto dentro de ficheros


Utilizaremos las variables especiales $ARG y $ARGV.

Queremos pasarle como argumentos a nuestro programa el nombre de varios ficheros de texto, y él nos dirá si encuentra el texto en alguno de ellos.


use English;
while(<>){
if($ARG=~/texto de prueba/){
print " Encontrado\n $ARG\n en $ARGV\n\n\n";
}
}

Para que nos reconozca correctamente los términos $ARG y $ARGV tenemos que indicar el "use English". Es para poder usar el módulo English.pm.

$ARG es la entrada y patrón de búsqueda por defecto. En el sitio dónde lo hemos puesto va cogiendo el nombre de cada argumento que le hemos pasado de esta forma:
$buscar.pl fichero1 fichero2 fichero3

$ARGV contiene el nombre del fichero actual que está tratando el bucle.

El bucle recorrerá todos los ficheros que pasemos como argumento. En la IF preguntamos si el fichero cumple la condición de tener ese texto dentro (patrón). Si lo tiene indicamos lo que ha encontrado, y también en qué fichero lo ha hecho.

La ejecución:

$ perl buscar.pl fichero1 fichero2 fichero3
Encontrado
texto de prueba
en fichero2

Saludos.

viernes, noviembre 04, 2011

Crear un fichero .doc por programación

A veces puede interesar automatizar por programación la creación de un fichero .doc (Word).

Esto te puede ayudar en dos casos:


  1. Si generas periódicamente, o frecuentemente, el mismo tipo de documento con ligeras variaciones (facturas, informes, etc.)



  2. Si tienes que crear un documento a partir de un montón de imágenes, ficheros, otros documentos...

Por ejemplo organismos que generan miles de de documentos diarios como los tribunales de Ginebra utilizan un módulo Perl: MsOffice-Word-HTML-Writer-1.01

Para usar ese módulo Perl no hace falta ni Windows, ni tener el Word instalado.

Código fuente copiado del enlace indicado:


use MsOffice::Word::HTML::Writer;
my $doc = MsOffice::Word::HTML::Writer->new(
title => "My new doc",
WordDocument => {View => 'Print'},
);

$doc->write("<p>hello, world</p>",
$doc->page_break,
"<p>hello from another page</p>");

$doc->create_section(
page => {size => "21.0cm 29.7cm",
margin => "1.2cm 2.4cm 2.3cm 2.4cm"},
header => sprintf("Section 2, page %s of %s",
$doc->field('PAGE'),
$doc->field('NUMPAGES')),
footer => sprintf("printed at %s",
$doc->field('PRINTDATE')),
new_page => 1, # or 'left', or 'right'
);
$doc->write("this is the second section, look at header/footer");

$doc->attach("my_image.gif", $path_to_my_image);
$doc->write("<img src='files/my_image.gif'>");

$doc->save_as("/path/to/some/file");


Si tenemos que hacerlo en un PC Windows va a ser más sencillo utilizar VB.NET como nos explican aquí: Cómo automatizar Word desde Visual Basic .NET para crear un nuevo documento


Código fuente copiado del enlace:
Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click

Dim oWord As Word.Application
Dim oDoc As Word.Document
Dim oTable As Word.Table
Dim oPara1 As Word.Paragraph, oPara2 As Word.Paragraph
Dim oPara3 As Word.Paragraph, oPara4 As Word.Paragraph
Dim oRng As Word.Range
Dim oShape As Word.InlineShape
Dim oChart As Object
Dim Pos As Double

'Start Word and open the document template.
oWord = CreateObject("Word.Application")
oWord.Visible = True
oDoc = oWord.Documents.Add

'Insert a paragraph at the beginning of the document.
oPara1 = oDoc.Content.Paragraphs.Add
oPara1.Range.Text = "Heading 1"
oPara1.Range.Font.Bold = True
oPara1.Format.SpaceAfter = 24 '24 pt spacing after paragraph.
oPara1.Range.InsertParagraphAfter()

'Insert a paragraph at the end of the document.
'** \endofdoc is a predefined bookmark.
oPara2 = oDoc.Content.Paragraphs.Add(oDoc.Bookmarks.Item("\endofdoc").Range)
oPara2.Range.Text = "Heading 2"
oPara2.Format.SpaceAfter = 6
oPara2.Range.InsertParagraphAfter()

'Insert another paragraph.
oPara3 = oDoc.Content.Paragraphs.Add(oDoc.Bookmarks.Item("\endofdoc").Range)
oPara3.Range.Text = "This is a sentence of normal text. Now here is a table:"
oPara3.Range.Font.Bold = False
oPara3.Format.SpaceAfter = 24
oPara3.Range.InsertParagraphAfter()

'Insert a 3 x 5 table, fill it with data, and make the first row
'bold and italic.
Dim r As Integer, c As Integer
oTable = oDoc.Tables.Add(oDoc.Bookmarks.Item("\endofdoc").Range, 3, 5)
oTable.Range.ParagraphFormat.SpaceAfter = 6
For r = 1 To 3
For c = 1 To 5
oTable.Cell(r, c).Range.Text = "r" & r & "c" & c
Next
Next
oTable.Rows.Item(1).Range.Font.Bold = True
oTable.Rows.Item(1).Range.Font.Italic = True

'Add some text after the table.
'oTable.Range.InsertParagraphAfter()
oPara4 = oDoc.Content.Paragraphs.Add(oDoc.Bookmarks.Item("\endofdoc").Range)
oPara4.Range.InsertParagraphBefore()
oPara4.Range.Text = "And here's another table:"
oPara4.Format.SpaceAfter = 24
oPara4.Range.InsertParagraphAfter()

'Insert a 5 x 2 table, fill it with data, and change the column widths.
oTable = oDoc.Tables.Add(oDoc.Bookmarks.Item("\endofdoc").Range, 5, 2)
oTable.Range.ParagraphFormat.SpaceAfter = 6
For r = 1 To 5
For c = 1 To 2
oTable.Cell(r, c).Range.Text = "r" & r & "c" & c
Next
Next
oTable.Columns.Item(1).Width = oWord.InchesToPoints(2) 'Change width of columns 1 & 2
oTable.Columns.Item(2).Width = oWord.InchesToPoints(3)

'Keep inserting text. When you get to 7 inches from top of the
'document, insert a hard page break.
Pos = oWord.InchesToPoints(7)
oDoc.Bookmarks.Item("\endofdoc").Range.InsertParagraphAfter()
Do
oRng = oDoc.Bookmarks.Item("\endofdoc").Range
oRng.ParagraphFormat.SpaceAfter = 6
oRng.InsertAfter("A line of text")
oRng.InsertParagraphAfter()
Loop While Pos >= oRng.Information(Word.WdInformation.wdVerticalPositionRelativeToPage)
oRng.Collapse(Word.WdCollapseDirection.wdCollapseEnd)
oRng.InsertBreak(Word.WdBreakType.wdPageBreak)
oRng.Collapse(Word.WdCollapseDirection.wdCollapseEnd)
oRng.InsertAfter("We're now on page 2. Here's my chart:")
oRng.InsertParagraphAfter()

'Insert a chart and change the chart.
oShape = oDoc.Bookmarks.Item("\endofdoc").Range.InlineShapes.AddOLEObject( _
ClassType:="MSGraph.Chart.8", FileName _
:="", LinkToFile:=False, DisplayAsIcon:=False)
oChart = oShape.OLEFormat.Object
oChart.charttype = 4 'xlLine = 4
oChart.Application.Update()
oChart.Application.Quit()
'If desired, you can proceed from here using the Microsoft Graph
'Object model on the oChart object to make additional changes to the
'chart.
oShape.Width = oWord.InchesToPoints(6.25)
oShape.Height = oWord.InchesToPoints(3.57)

'Add text after the chart.
oRng = oDoc.Bookmarks.Item("\endofdoc").Range
oRng.InsertParagraphAfter()
oRng.InsertAfter("THE END.")

'All done. Close this form.
Me.Close()

End Sub


Saludos.

lunes, junio 27, 2011

Como quitar columnas de un fichero de texto

Supongamos que tenemos un gran fichero de texto y queremos quitarle unas columnas (me ha ocurrido hoy mismo).

Creo que la forma más sencilla es con Perl:

Leemos el fichero de entrada línea a línea, pero escribimos en el fichero de salida todo menos las columnas que no nos interesan.



$fichero="origen.txt";
open(FICH, $fichero) or die("Error al abrir el fichero");
open(SALIDA, ">destino.txt");
while(<FICH>){
$linea=$_;
$basura=substr($linea, 0, 10);
$texto=substr($linea, 10, 100);
printf SALIDA $texto;
}
close FICH;
close SALIDA;

Saludos.


jueves, mayo 05, 2011

Perl para monitorizar la red


Estábamos sufriendo pequeños cortes de red muy esporádicos (digamos que 3 ó 4 al día).
Necesitaba registrar la fecha y hora para que los técnicos de comunicaciones supieran dónde buscar...

Podría haber utilizado cualquier software comercial pero preferí hacer el siguiente script PERL:

Funciona perfectamente con la instalación por defecto de ActivePerl para Windows:
#!/usr/bin/perl -w
use Net::Ping;

my $p = Net::Ping->new("icmp");
my @servidores=('servidor1','servidor2','servidor3','servidor4');
open(FICHERO, ">>errores.txt")||die "error!!!";
print FICHERO "EMPEZAMOS ANALISIS\n";
fechaHora();
print FICHERO "----------------------------------\n";
close(FICHERO);
for(;;) {
foreach my $host (@servidores)
{
if ($p->ping($host, 2)) {
print "$host OK!\n"
}
else {
open(FICHERO, ">>errores.txt")||die "error!!!";
print FICHERO "FALLO en $host. ";
fechaHora();
close(FICHERO);
}
sleep(1);
}
}
$p->close();

sub fechaHora {
my ($sec,$min,$hour,$day,$month,$yr20,@rest) = localtime(time);
print FICHERO "$day-".++$month. "-".($yr20+1900)." ";
print FICHERO sprintf("%02d",$hour).":".sprintf("%02d",$min).":".sprintf("%02d",$sec)."\n";
}


El funcionamiento es muy sencillo:

Creamos un array con los nombres de los servidores a los que el programa va a hacer continuamente PING.

Luego se intenta el PING. Si el servidor responde escribimos SERVIDOR OK. Si no responde abrimos el fichero ERRORES.TXT y escribimos la fecha y hora.

Curiosidades:

Cada vez que falla un PING abrimos el fichero, escribimos y volvemos a cerrar.
Lo tuve que hacer así porque el bucle infinito hay que terminarlo con Control+C o cerrando la ventana. Al interrumpir el programa antes de cerrar el fichero resulta que te encuentras con un ERRORES.TXT vacío.

Saludos.




lunes, marzo 15, 2010

Ataque por diccionario en Perl II

Teniendo en cuenta esto que decía el otro día, así quedaría el programita Perl para el ataque por diccionario:

Nota: También es recomendable la forma que propone Nemo en los comentarios del primer post.

Este programa se ejecuta a toda leche, aunque obviamente es muy mejorable (por ejemplo quitando la visualización de las palabras).

Explicación rápida:

Abrimos el diccionario y por cada palabra hacemos el siguiente tratamiento:

1.-Quitamos el retorno de carro a la palabra con el chop.
2.-Preparamos el comando gpg con sus parámetros para la ejecución pasándole la password. MUY IMPORTANTE: Terminamos con un PIPE o tubería (la rayita vertical). Esto hace que se le pase a nuestro programita Perl la salida del gpg.
3.-Ponemos el contador a 0. Con este contador contamos las líneas que genera el gpg en la salida.
Cuando falla la contraseña el GPG devuelve 2 líneas indicando el error. Cuando acierta devuelve un mínimo de 3. El máximo es variable porque muestra todo el mensaje en claro.
4.-Sin más. Si hay más de 2 líneas muestra la contraseña y termina.
5.-Si llega al final del programa es que no ha encontrado la contraseña válida.

Saludos.

martes, marzo 09, 2010

Ataque por diccionario en Perl

En la charleta que tuve que dar el otro día quería que la gente supiera lo importante que es elegir bien una contraseña. Sobre todo cuando no hay posibilidad de bloquear el acceso después de un número determinado de intentos.

Este es el caso de un envío de datos encriptados. Una vez que el envio ha sido interceptado el atacante tiene todo el tiempo de mundo para probar contraseñas.

Les enseñé este bonito sitio con diccionarios. Da igual lo original que pretendas ser que siempre habrá un diccionario temático preparado:

Descargué unos cuantos diccionarios y los junté:

cat actores_cine_usa.txt > diccionario.txt
cat numeros.txt >> diccionario.txt

Tuve que cambiar los caracteres windows de la forma que expliqué el otro día.

Luego preparo un fichero datos.txt que encripto con clave simétrica utilizando GPG:

gpg --symmetric datos.txt

Le pongo como password aitoreus.

Y este es el programita Perl que preparé...

La ejecución es algo así... hasta que encuentra la password que descifra.


use Expect;
$fichPalabras="diccionario.txt";
open(FICH, $fichPalabras) or die ("Error al abrir el fichero de palabras.\n");
while($palabra=){
$comando="gpg --decrypt datos.txt.gpg";
my $exp = Expect->spawn($comando, @params)
or die "No puede ejecutar $comando: $!\n";
$exp->expect(1);
$exp->send("$palabra\n");
$exp->expect(1);
$read = $exp->before();
if ($read!~/failed/){
print("Encontrado. La password es $palabra\n");
$exp->soft_close();
exit;
}
$exp->hard_close();
};
print("Esta vez no ha habido suerte\n");
$exp->soft_close();

Sobre el Expect:

Al ser el GPG un programa interactivo (que en su ejecución espera que tecleemos algo), no se puede ejecutar y pasarle como parámetro la contraseña (vaya, lo que son las cosas, ahora tengo mis dudas. Mañana confirmo o desmiento).

Suponiendo que era un programa interactivo, lo que hice fue bajarme el módulo Expect que me permite ejecutar en modo batch un programa interactivo. Expect te permite esperar una pregunta del programa y mandarle tu propia respuesta, pero todo automatizado claro.

Me bajé el Expect-1.21.tar.gz de CPAN y por un tema de dependencias también tuve que bajarme el módulo IO-Tty-1.03.tar.gz.

Mañana hablaré un poco más de Expect y sus aplicaciones.

Saludos.

miércoles, febrero 10, 2010

Pequeños fallos de Perl


Perl me gusta mucho, pero a veces tiene cosas que te pueden volver loco.

Hoy quería sacar un listado a partir de la salida del comando cacls en un servidor Windows. Era un servidor que ofrece una carpeta compartida. Este comando sirve entre otras cosas para obtener un fichero con todas las carpetas y ficheros de una unidad y los usuarios que tienen permisos de acceso.

La especialidad del lenguaje Perl es el tratamiento de ficheros de texto para listados. Recordad que PERL se ha asociado en algunos momentos a Practical Extraction and Report Language. Vamos, que es el lenguaje adecuado para lo que quería.

En 1998 compré un libro de PERL5 llamado "Perl al descubierto".
En ese libro explicaban la forma de utilizar la función split de la siguiente forma:

"La función split se usa para separar los elementos que es´tan en la cadena $cita y ponerlos en el arrray @palabras":

@palabras = split(' ',$cita);

A ver, en condiciones "normales" la cosa funciona bien, pero yo quería separar las líneas del fichero por un texto que incluía un carácter especial que era la contrabarra: \

Pues os puedo asegurar que la contrabarra no iba ni por el forro. Lógicamente al ser un carácter especial para Perl, hay que poner por delante otra contrabarra (dos contrabarras). La cosa más o menos era así:

@cachos = split(' texto1\\texto2',$linea);

Pues esto no funciona. Tanto en la versión vieja del curro, como en mi mac mini el error es parecido: "Trailing \ in regex m/\/ at cachos.pl line 2". (regex se refiere a Regular Expresion).

En Perl, cuando se utilizan cadenas en expresiones regulares hay que utilizar las dobles comillas en lugar de la comilla simple. Sobre todo es imprescindible lo de las comillas dobles para que reconozca los caracteres especiales. Pero la siguiente instrucción devuelve exactamente el mismo error:

@cachos = split("texto1\\texto2",$linea);

Al final, buscando en la red, que era lo primero que tenía que haber hecho, encuentro la solución que es una sintaxis diferente de la misma función:

@cachos = split(/texto1\\texto2/, $linea);

La versión de Perl utilizada en el servidor era la 5.8.0. La versión de Perl de mi mini mac (Mac OSX Leopard comprado el año pasado) es 5.8.8. (¡¡¡En 10 años casi no ha evolucionado!!!). Los resultados han sido iguales tanto en el servidor como en el mac OSX.

Si se mantiene la anterior sintaxis por compatibilidad hacia atrás, el interprete podría haber mostrado un warning como hacen otros lenguajes.

Si se mantiene para tener diferentes formas de llamada a esa función, pues muy bien, pero que la funcionalidad ofrecida sea la misma en los dos casos.

Saludos.

martes, noviembre 10, 2009

Cálculo de calorias al correr

Hola amig@s,

Llevo ya varias semanas corriendo con cierta regularidad. Veo mejoría pero la verdad es que no bajo peso.

¡¡¡Hoy además me he llevado un gran disgusto!!! Me han asegurado que mi báscula no funciona y MARCA DE MENOS :-(

Ya va siendo hora de calcular si realmente quemo las calorías que como.

Lo primero obtener la formulita dichosa de las calorías. Me voy a fiar de este sitio que es bastante famoso:


Está claro: calorías = km x kg x 1,036


Teniendo en cuenta que entrenaré a unos 5 minutos el kilómetro diremos que...


calorías = (minutos/5) x kg x 1,036


Para hacer esta tontería y conseguir que el programa vaya almacenando un histórico de nuestro entrenamiento lo más rápido y divertido es Perl:


La ejecución del programa:


Y el resultado es un fichero llamado ENTRENA.TXT con los datos diarios en un formato que se puede leer desde Excel.

Saludos.

sábado, septiembre 26, 2009

Búsquedas por la web con PERL

El otro día quise ayudar a mi colega Castrol con un tema. Concretamente escribió un post sobre bibliotecas clásicas, y cómo el uso de Google parecía sustituirlo todo.

También contó alguna anécdota como un problema que tuvo al deletrear una palabra inglesa. No sabía si se escribía de una forma o de otra. Al final abrió Google y supuso que la versión con más respuestas era la correcta y la otra era la mala.

Como yo sabía que utiliza un portátil mac pensé en un pequeñito script Perl para facilitar este tipo de dudas. Mac OS X, como la mayoría de GNU/Linux, UNIX, etc. trae el interprete PERL incorporado.

La forma de ejecución es $buscar palabra1 palabra2 y el resultado:

palabra1: 1.200.000 resultados.
palabra2: 10.000 resultados.

El programa Perl es éste, pero lo más importante es que NO FUNCIONA.


Ahora bien, ¿POR QUÉ NO FUNCIONA?

Me he vuelto un poco loco hasta darme cuenta. No es que las sentencias estén mal ni nada de eso. Si en lugar de Google buscáramos en un documento de nuestro PC, en un blog, en un diario, etc. funcionaría sin problemas, pero no en GOOGLE, ni en YAHOO, y me imagino que tampoco funciona en otros muchos buscadores.

Hace años habría funcionado pero hoy en día ya no.

El problema es que estos buscadores están bloqueado la utilización de LWP.

Cuando accedemos al servidor de Google con nuestro programita PERL utilizando LWP, se le informa también de cual es la librería y versión con la que accedemos.

En mi instalación, el "UserAgent" se pasa por defecto con el valor "libwww-perl/5.805". A los buscadores no les gusta que accedamos (LWP) de esta forma y simplemente nos ignoran.

De esta forma podemos ver cómo accedemos:
use LWP::UserAgent;
my $ua=LWP::UserAgent->new;
print $ua->_agent;

¿UNA SOLUCIÓN RÁPIDA?

Bueno, podemos modificar el "default agent identifier" para que ponga que accedemos con Mozilla por ejemplo y asunto solucionado.

Para eso hay que utilizar el módulo LWP::UserAgent en lugar de LWP::Simple. En la imagen siguiente está el código fuente:



Ahora sí, si ejecutamos:

perl buscar.pl aciendo haciendo

Nos da la siguiente respuesta:

aciendo: 778.000 encontrados
haciendo: 51.000.000 encontrados

pd1: Utilizar este programa de esta forma incumple la condición 5.3 que Google establece para el acceso a su servicio (Condiciones de servicio de Google). Para evitar incumplir nada, en el próximo post explicaré la forma de acceso a través del interfaz (API) de Google.

pd2: No se si te será muy útil Castrol, pero espero que tengas suficiente curiosidad para probarlo e incluso que te conviertas en un PERL HACKER.

viernes, septiembre 18, 2009

Utiliza perl para controlar tus sitios preferidos


Hola,

El lenguaje del camello es un lenguaje que siempre me ha gustado (por cierto, en los libros suelen poner un dromedario en lugar de un camello).

Posiblemente PERL no esté en su mejor momento, pero tiene unas ventajas claras:


  • Está por defecto en la mayoría de los UNIX.
  • Disponible con licencia GPL (software libre).
  • Disponible para Windows.
  • Preinstalado en la mayoría de las distribuciones GNU/Linux.
  • Preinstalado en Mac OSX como buen UNIX que es.
  • Es un lenguaje moderno y muy actualizado. Me refiero a que tiene cientos de módulos para hacer cualquier cosa (conexión a bases de datos, encriptación, web, etc. etc.). Este es el motivo por el cual lo he elegido hoy, en lugar del querido Pascal.
¿Por qué digo que no está en su mejor momento?

Bueno, Perl nace en 1987 como lenguaje de generación de informes. O sea, se trataba de un animal de carga no demasiado bonito pero que hacía maravillas en la Administración de hosts con gran capacidad para manejo de strings.

Luego evolucionó con la incorporación de múltiples mejoras. Conoció el boom de Internet con las CGI y finalmente llegó el declive por el crecimiento de Java, .NET, Python, PHP, etc. etc.

Perl nació y creció de una forma algo desordenada. Se le añadió la orientación a objetos con calzador, así como otras muchas historias. Al final resulta un lenguaje muy especial. Casi críptico, y eso en sí mismo también es bonito.

Desde 1994 la versión utilizada ha sido la 5. Sobre el año 2000 hubo calientes debates sobre cómo debería ser Perl 6. El caso es que todavía hoy creo que la versión estable es la 5.8.9. Como curiosidad, el Perl instalado en mi Mac OS X Leopard 10.5 es el 5.8.8

Vale ya de charletas, ¿Por qué se dice que Perl es tan potente?

Es por la gran cantidad de módulos que tiene. Hay módulos PARA TODO lo que se os pueda ocurrir y están disponibles en CPAN.

UN EJEMPLO

Supongamos que queremos hacer un programita Perl que nos diga si en alguno de los periódicos se habla de un determinado tema. Son por ejemplo 20 periódicos, y lo queremos mirar todos los días por lo que de alguna forma hay que automatizar el trabajo.

O supongamos que en nuestra empresa nos han encargado leer unos cuantos boletines oficiales para buscar subvenciones o algo así.

Un trabajo así de pesado es lo ideal para Perl.

Editamos el siguiente programa (en mi caso con el TextEdit de mac):



El que no haya visto nunca Perl creo que me entiende ahora cuando digo que es un poco críptico.


LA EXPLICACIÓN DEL PROGRAMITA

use LWP::Simple;
indica que utilice el módulo LWP::Simple (The World Wide Web module for Perl).
cuando se instala un módulo (en mi caso ya estaba instalado), también se instala la documentación.
Podemos hacer perldoc LWP para verla.

use strict;
es una directiva que es bastante recomendable para forzarnos a inicializar variables, etc.

my $contenido = get('http://aitoreus.blogspot.com');
inicializamos la variable "contenido" con la captura de la web que nos interese.

die "no consigo ver el sitio" unless defined $contenido;
esto es un poco enrevesado. Le pide al programa que "muera" escribiendo "no consigo ver el sitio", a no ser que la variable $contenido esté definida.

print "Hola chavalote. Estoy analizando http://aitoreus.blogspot.com";
escribe el texto sin más.

foreach my $palabrita (qw( pascal programacion program begin end))
El comando qw símplemente sirve para crear una lista con las palabras.
El foreach es una de las construcciones más divertidas de Perl.
Es un bucle for que además del bucle va asignando a la variable $palabrita cada término de la lista.
Lo que está entre llaves es lo que se ejecuta en cada iteración del bucle.

print "$palabrita\n" if $contenido=~ m/\b\Q$palabrita/;
Esto es otra muestra de la potencia de Perl. Son los patrones de búsqueda. Escribe la palabrita con un retorno de carro, si se cumple que la palabrita está en el contenido.

print "\n[Escaneo terminado el", scalar( localtime ), "]\n";
Escribe que ha terminado y pone la fecha y hora.

exit;
Y con esto yo también me despido.

Saludos.