Tu propio bot para Twitter en Perl

He tenido dudas sobre si publicar mi script implemientando un bot para Twitter en mi blog SEO o en este blog sobre Linux. Finalmente me he decidido por éste. Probablemente tiene más utilidad pedagógica que para el marketing en la red social. Explicado de otra forma. Aunque tengo ciertas ideas sobre su utilidad comercial, me limito a publicarlo y a invitarte a buscar las tuyas.

La forma normal de utilizarlo es la siguiente:

  $ autoretweet -u usuario -p lksnfd -k linux
  

Se trata de los tres parámetros obligatorios. El nombre de usuario en el servicio Twitter, la contraseña, y la palabra clave que disparará el bot una vez aparezca en las búsquedas. Utilizado así, el bot simplemente hace un retweet al usuario que ha publicado un mensaje conteniendo la palabra clave. El usuario podría así identificarte como interesado en el tema para el cual dicha palabra clave es representativa y devolverte su seguimiento.

Hay no obstante formas más sofisticadas de utilizarlo, mediante los siguientes parámetros opcionales.

-s status

Utiliza una cadena de texto determinada en lugar del retweet. Dicha cadena podría contener un enlace, y utilizar así el bot para la promoción de un sitio y no para conseguir seguimientos. Utilizar con precaución dado que el uso de una cadena repetida acaba redundando en que la cuenta que lo hace es marcada como sospechosa y desactivada.

-f url

Averigua el feed XML para el sitio cuya URL se proporciona. De dicho feed toma las entradas que contienen la palabra clave indicada y presenta en cada nuevo estado el enlace y el título de dicha entrada. Eventualmente útil para promocionar un sitio. De nuevo, utilizar con precaución.

-n num_results

El número de resultados a ser devuelto en cada búsqueda.

-p poll_frequency

El tiempo entre dos búsquedas consecutivas.

-d delay_updates

El tiempo entre dos envíos al sistema Twitter. Si va a utilizarse un mensaje repetido, configurar un valor lo suficientemente alto para evitar que la cuenta sea marcada como sospechosa.

-r random

Genera para cada envío un hashtag aleatorio de la longitud indicada. Permite que la cadena de texto sea distinta en cada envío y eventualmente que la cuenta no sea marcada así como sospechosa.

-v

Salida prólija, presentando un informe completo de todas las acciones realizadas por el script.

Ante la posibilidad de que Twitter considere maliciosa la actividad del bot y marque la cuenta como sospechosa, no dudo en recomendar no utilizarlo con tu propia cuenta personal. Copia el código en un fichero llamado autoretweet. Activa el permiso de ejecución y guárdalo en un directorio en tu path actual. Crea ahora una cuenta troll. Sigue la convención de utilizar para el avatar de dicha cuenta una nariz roja. Utiliza ahora esa cuenta para probar el bot. Disfrútalo.

#!/usr/bin/perl

use strict;
use warnings;

use Data::Dumper;
use Getopt::Std;
use HTML::TokeParser;
use LWP::Simple;
use Net::Twitter;
use XML::Feed;

local $| = 1; # auto flush stdout
binmode STDOUT, ':utf8';

my $username;
my $password;
my $keyword;
my $status;

my $num_results = 5;
my $poll_frequency = 100;
my $delay_updates = 60;

my $random = 0;
my $verbose = 0;

my @feeds;
my @goods = ();

# Get command line options
my %opts=();
getopts("u:p:k:f:s:n:q:d:r:v",\%opts);

# Parse command line options, die if any not defined
if (defined $opts{u}) {
    $username = $opts{u};
}
else {
    die "username not defined!";
}

if (defined $opts{p}) {
    $password = $opts{p};
}
else {
    die "password not defined!";
}

if (defined $opts{k}) {
    $keyword = $opts{k};
}
else {
    die "keyword not defined!";
}

if (defined $opts{f}) {
    my $url = $opts{f};
    @feeds = XML::Feed->find_feeds($url);

    if ($feeds[0]) {
        my $feed = XML::Feed->parse(URI->new($feeds[0]));
        my @entries = $feed->entries();

        foreach my $entry (@entries) {
            if ($entry->link() =~ m/$keyword/) {
                push (@goods, $entry->link());
            }
        }
    }
}

if (defined $opts{s}) {
    $status = $opts{s};
    if (length($status) > 140) {
        die "status too long!";
    }
}

if (defined $opts{n}) {
    $num_results = $opts{n};
}

if (defined $opts{q}) {
    $poll_frequency = $opts{q};
}

if (defined $opts{d}) {
    $delay_updates = $opts{d};
}

if (defined $opts{r}) {
    $random = $opts{r};
}

if (defined $opts{v}) {
    $verbose = 1;
}

printf "get %d search results on keyword \"%s\" each %d seconds\n",
    $num_results, $keyword, $poll_frequency;
printf "retweet from user %s password %s each %d seconds\n",
    $username, $password, $delay_updates;
if (scalar (@goods)) {
    printf "use random status relevant for keyword \"%s\"\nfrom feed %s\n",
    $keyword, $feeds[0];
}
elsif ($status) {
    printf "use status \"%s\"\n", $status;
}
if ($verbose) {
    print "be verbose\n";
}

# Create a Net:Twitter object
my $nt = Net::Twitter->new({
    username => $username,
    password => $password,
    traits => [qw/API::REST/, qw/API::Search/]
});

# So only new search results are retweeted
my $since_id = 0;
my $max_id = 0;

while (1) {

    # Get search results on keyword
    printf "searching ";
    my $tweets = $nt->search({
        q => $keyword,
        rpp => $num_results,
        lang => 'es',
        $since_id ? (since_id => $since_id) : ()
    });

    if (defined $tweets) {
        print "ok\n";
    }
    else {
        print "failed!\n";
    }   

    # For each search result...
    for my $t (@{$tweets->{results}}) {
        next unless $t->{id} > $since_id;
        if ($t->{id} > $max_id) {
            $max_id = $t->{id};
        }
        # Don't retweet if an own tweet or from user is the keyword
        # also if already a retweet when no status is given
        if (
            ($t->{from_user} ne $username) &&
            ($t->{from_user} ne $keyword) &&
            (($status) || ($t->{text} !~ m/^RT/))
            ) {
            # Build retweet string
            my $s;
            # Prepend a random hashtag
            if ($random > 0) {
                $s .= "#";
                my @chars=('a'..'z','0'..'9');
                foreach (1..$random)
                {
                    $s .= $chars[rand @chars];
                }
                $s .= " ";
            }
            # Use feed entry with given keyword if any
            if (scalar(@goods) > 0) {
                $s .= "@" . $t->{from_user} . " ";

                my $uri = $goods [rand @goods];
                my $content = get($uri);
                utf8::decode($content);

                my $p = HTML::TokeParser->new(\$content);
                if ($p->get_tag('title')) {
                    my $title = $p->get_trimmed_text();
                    $title =~ s/&/&/g;
                    $s .= $title . ". ";
                }
                $s .= $uri;
            }
            # Use specified status if any
            elsif ($status) {
                $s .= "@" . $t->{from_user} . " " . $status;
            }
            # Use a simple retweet
            else {
                $s .= "RT @" . $t->{from_user} . ": " . $t->{text};
            }

            if ($verbose) {
                printf "%s\n", $s;
            }
            printf "%s retweet", $t->{from_user};

            # Send update
            if ($nt->update($s)) {
                print "ed ok\n";
            }
            else {
                print " failed!\n";
            }
            sleep $delay_updates;
        }
    }

    # Set last received search result and sleep for a while
    $since_id = $max_id;
    sleep $poll_frequency;
}

El usuario de Debian y Ubuntu sólo tiene que instalar el paquete libnet-twitter-perl. El bot sin embargo debería ser utilizable en otros sistemas como Windows. Instálese en ese caso ActivePerl o, mejor aún, el entorno Cygwin y obténgase la librería necesaria utilizando CPAN.

¿Te pareció interesante? Sé tan amable de menear este artículo.

bot Debian Linux perl social twitter Ubuntu

Bookmark and Share votar

3 Respuestas to “Tu propio bot para Twitter en Perl”

  1. Para pegar snippets de código viene bastante bien http://gist.github.com/

  2. Hola, quiero hacer esto con la cuenta de twitter de un cliente, pero no sé cómo, es decir, leo esto pero no entiendo dónde va el código…

    ¿Me ayudarías?
    Gracias!

  3. Lata, mándame un email y lo miramos. ¡Gracias!

Deja una Respuesta

El enlace de tu firma no es válido para los buscadores. Cualquier intento por tu parte de hacer spam no tendrá el resultado esperado. Haz un comentario interesante y contribuye a la discusión.