アンサイクロペディア bot を作った

id:phaさんが作ったウィキペディアbotに便乗して、アンサイクロペディアbot を作った。


一時間に一回アンサイクロペディアおまかせ表示 でゲットしたページを読み込んでポストします。


@AnsaiBot


冒頭の文を引用しますが、いい加減な感じなのであんまり関係ない部分を引用してしまったりします。


日本語版のアンサクロペディアは http://ja.uncyclopedia.info/ でもいいし、
http://ansaikuropedia.org でもいいんですねー。とりあえず、ローカルっぽさを重視して後者を使いました。



ソースとか

#!/usr/bin/perl
use utf8;
use strict;
use warnings;
use Encode qw(encode decode);
use LWP::Simple qw(get);
use URI::Escape qw(uri_escape);
use HTML::TagParser;
use YAML::Tiny;
use Net::Twitter;


my $MARU  = encode('utf8', '。');
my $PAREN = encode('utf8', '(.+?)');


sub omakase_ansaikuropedia
{
    my $url = shift;
    
    my $data = get($url);
    return unless $data;
    
    my $html = HTML::TagParser->new($data);
    
    my $title = $html->getElementsByTagName('title')->innerText();
    $title =~ s/^(.+?)\s.*$/$1/;
    
    my $desc = $html->getElementsByTagName('p')->innerText();
    $desc =~ s/$PAREN//g;
    $desc =~ s/\(.+?\)//g;
    $desc =~ s/^\s+//;
    $desc =~ s/\s+$//;
    
    return ( $title, $1, $2 ) if $desc =~ m/^(.+?$MARU)(.+?$MARU)?.*$/;
}


sub cre_msg
{
    my $config = shift;
    my $msg;
    my $cnt = 0;
    
    while (1) {
        $msg = '';
        my ($title, $desc1, $desc2) = omakase_ansaikuropedia($config->{randompage});
        next unless $title && $desc1;
        printlog("title = $title");
        
        my $url = $config->{baseurl} . uri_escape($title);
        my $shortUrl = bitly($url,
                             $config->{bitly_login},
                             $config->{bitly_apikey},
                             $config->{bitly_ver}
            );
        next unless $shortUrl;
        printlog("bitly = $shortUrl");
        
        $msg = "$title $shortUrl $desc1$desc2";
        last if jp_length($msg) <= 140;
        printlog("rem desc2");
        
        $msg = "$title $shortUrl $desc1";
        last if jp_length($msg) <= 140;
        printlog("rem desc1");
        
        $msg = "$title $shortUrl";
        
        last if jp_length($msg) <= 140;
        last if $cnt++ > 5;
        printlog("retry");
    }
    
    return $msg;
}


sub bitly
{
    my ($url, $login, $apikey, $ver) = @_;
    
    my $baseurl = "http://api.bit.ly/shorten";
    my $query   = "?version=$ver&longUrl=$url&login=$login&apiKey=$apikey&format=xml";
    
    my $data = get("$baseurl$query");
    
    return $1 if $data =~ /<shortUrl>(.+?)<\/shortUrl>/i;
}


sub jp_length
{
    my $line = shift;
    my @char = split //, decode('utf8', $line);
    return scalar(@char);
}


sub printlog
{
    my $line = shift;

    my $fmt = "%04d/%02d/%02d %02d:%02d:%02d: %s\n";
    my ($sec,$min,$hour,$mday,$month,$year) = localtime(time);

    printf $fmt, $year+1900, $month+1, $mday, $hour, $min, $sec, $line;
}


sub main
{
    printlog("ansaibot : begin ==========");
    
    my $config = (YAML::Tiny->read('./config.yml'))->[0];
    
    if ( my $msg = cre_msg($config) ) {
        # twitter
        my $twit = Net::Twitter->new( username => $config->{username},
                                      password => $config->{password} );
    
        $twit->update( decode('utf8', $msg) );
    
        printlog("POST => $msg");
    }
}

main();


config.yml

username: <twitterのユーザID>
password: <twitterのパスワード>
baseurl: "http://ansaikuropedia.org/wiki/"
randompage: "http://ansaikuropedia.org/wiki/Special:Randompage"
bitly_login: <bitlyのlogin ID>
bitly_apikey: <bitlyのapikey>
bitly_ver: "2.0.1"