Usuario:JoaquinFerrero/Medallero2012P

Programa para la actualización automática del Medallero de los Juegos Paralímpicos Londres 2012

editar
#!/usr/bin/env perl
#
# medalleroLondres2012P.pl
#
# Autor:
#       Joaquín Ferrero
#
# Descripción:
#       Actualización automática del medallero olímpico en Wikipedia
#       para los Juegos Paralímpicos Londres 2012.
#
# Entrada: ninguna
# Salida:  ninguna
#
# Historial:
#   2012.08.31 : Versión para Londres 2012 Paralímpicos
#   2012.07.31 : Versión para Londres 2012
#   2010.03.20 : Versión para Sudamericanos Medellin 2010
#   2010.03.13 : Versión para Vancouver 2010 Paralimpicos
#   2010.02.16 : Versión para Vancouver 2010
#   2008.09.07 : Versión inicial para Pekín 2008
#

### Bibliotecas -------------------------------------------------------------
use Modern::Perl 2012;  # Programamos en Perl moderno
use autodie;            # «Es mejor morir que regresar con deshonor» --proverbio Klingon
use utf8::all;          # Activar todo el soporte para UTF-8. Realmente todo

use Mojo::UserAgent;    # Un poco de mojo...
use MediaWiki::API;     # Y mucha Wikipedia

### Configuración -----------------------------------------------------------
my $COUNTRY             = 'GBR';
my $MEDALLERO_OFICIAL   = 'http://www.london2012.com/paralympics/medals/medal-count/';
my $WIKIPEDIA_MEDALLERO = 'Anexo:Medallero de los Juegos Paralímpicos de Londres 2012';
my $WIKIPEDIA_TEST_PAGE = 'Wikipedia:Zona de pruebas/5';
my $WIKIPEDIA_USER_LOG  = 'JoaquinFerrero';
my $WIKIPEDIA_USER_PAS  = 'contraseña';
my $WIKIPEDIA_API_URL   = 'http://es.wikipedia.org/w/api.php';
my $DEBUG               = 0; #0 (sin avisos) o 1 (con avisos)

## Obtención de los resultados ----------------------------------------------
my $medallero_html;

for my $retry (0 .. 2) {

    my $ua = Mojo::UserAgent->new(
        name            => 'Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:14.0) Mojolicious/2012 Wikipedia/es',
        request_timeout => 5,
    );

    $medallero_html = $ua->get(
        $MEDALLERO_OFICIAL,
        {
            'Accept'            => 'text/html',
            'Referer'           => 'http://www.london2012.com/',
            'Accept-Encoding'   => 'none',
            'DNT'               => 1,
            'Accept-Language'   => 'es,es-es;q=0.8,en;q=0.5,en-us;q=0.3',
        }
    )->res->dom->find("div[id=lgc-main]")->[0];

    last if defined $medallero_html;

    sleep 30;
}

die "ERROR: No he podido leer la página del medallero oficial\n"
    if not defined $medallero_html;

## Extracción de resultados -------------------------------------------------
my @tabla_medallero_oficial;            # $tabla_medallero_oficial[$i] = [$posicion,$pais,@medallas,$total]

my %attr_to_pos = (
    position    => 0,
    country     => 1,
    gold        => 2,
    silver      => 3,
    bronze      => 4,
    total       => 5,
);

my @filas = $medallero_html->find("tr")->each;

for my $fila (@filas) {
    next if $fila !~ /<td class="position/;

    my @celdas = $fila->find("td")->each;
    my @resultado_pais;

    for my $celda (@celdas) {
        my($clase)= $celda =~ /class="(\w+)/;
        my $contenido = $celda->text;

        if ($clase eq 'athleteInfo') {          # código del país
            $clase = 'country';
            ($contenido) = $celda =~ m{([^/]+?)\.png};
        }

        if (exists $attr_to_pos{$clase}) {
            $resultado_pais[ $attr_to_pos{$clase} ]  =  $contenido;
        }
    }

    push @tabla_medallero_oficial, [ @resultado_pais ] if @resultado_pais;
}

die "ERROR: No he leído la tabla del medallero oficial"
    if ! @tabla_medallero_oficial;

## Conexión con Wikipedia ---------------------------------------------------
my $Wikipedia = MediaWiki::API->new({
    api_url     => $WIKIPEDIA_API_URL,
    retries     => 3,
    retry_delay => 30,
});

$Wikipedia->login({
    lgname      => $WIKIPEDIA_USER_LOG,
    lgpassword  => $WIKIPEDIA_USER_PAS,
})
or die $Wikipedia->{error}->{code} . ': ' . $Wikipedia->{error}->{details};

## Medallero en formato wiki ------------------------------------------------
my @totales_medallero;                                          # Almacena la suma de las medallas
my $se_ha_puesto_el_aviso = 0;
my $medallero_wiki        = <<"EOF";
== Medallero ==
<!--
        ATENCIÓN: La tabla se actualiza de forma automática cada 5 min. durante el periodo de los juegos.

                         CUALQUIER cambio realizado de forma manual se perderá.

                                AVISAR de incidencias a JoaquinFerrero.

--></noinclude>
{| {{Medallero|tipo = 1|ancho = 60%}}
EOF

foreach my $fila (@tabla_medallero_oficial) {

    my @medallas = @{$fila}[2 .. 5];                            # Desde Oro a total

    map { $totales_medallero[$_-2] += $fila->[$_] } 2 .. 5;     # Cálculo de los totales

    if ($fila->[0] > 10  and  ! $se_ha_puesto_el_aviso++) {     # Poner nota de corte a los diez primeros clasificados
        $medallero_wiki .= qq(<includeonly><!-- Para cerrar la tabla en el artículo principal -->|}</includeonly><noinclude>\n);
    }

    $medallero_wiki .= '|-';                                    # Nueva fila del medallero
    $medallero_wiki .= '-bgcolor=ccccff' if $fila->[1] eq $COUNTRY;     # País orgnizador
    $medallero_wiki .= "\n"
                    .  qq(|'''$fila->[0]'''\n)
                    .  '|' . join(' || ', "{{BanderaPL|$fila->[1]|Londres 2012}}", @{$fila}[2 .. 5] ) . "\n"
                    ;
}

# Totales y fin de la tabla
$medallero_wiki .= "|-\n" . join(' || ', '! colspan="2" | Total', @totales_medallero) . "\n|}";
$medallero_wiki .= '<noinclude>' if not $se_ha_puesto_el_aviso;
$medallero_wiki .= "\n\n";

## Actualización de la página del medallero ---------------------------------
my $pagina_wiki;                # Contenido de la página wiki actual
my $pagina_antes_wiki;          # Contenido de la página wiki anterior

my $titulo_pagina_wiki = $WIKIPEDIA_MEDALLERO;  # $WIKIPEDIA_TEST_PAGE

my $pagina_wiki_ref = $Wikipedia->get_page({
    title => $titulo_pagina_wiki,
});

die "ERROR: No conseguí la página del medallero\n"
    if $pagina_wiki_ref->{missing};

$pagina_wiki = $pagina_antes_wiki = $pagina_wiki_ref->{'*'};    # Cómo es la página ahora

# Intentamos hacer un cambio
if ($pagina_wiki =~ s/^=+ Medallero =+.+?(?=^=)/$medallero_wiki/sm) {

    if ($pagina_wiki ne $pagina_antes_wiki) {                   # Si hay realmente un cambio, la editamos
        $Wikipedia->edit({
             action        => 'edit',
             title         => $titulo_pagina_wiki,
             basetimestamp => $pagina_wiki_ref->{timestamp},
             text          => $pagina_wiki,
             summary       => 'Actualización automática del medallero',
        })
        or die $Wikipedia->{error}->{code} . ': ' . $Wikipedia->{error}->{details}
        ;

        say 'Actualizado medallero'  if $DEBUG;
    }
    else {
        say 'No hay cambios' if $DEBUG;
    }
}
else {
    die 'ERROR: no encuentro la sección del medallero en la página';
}

__END__