instagramって写真撮影をすごくカジュアルにしてくれた素晴らしいサービスだと思っていて、instagramの写真をmixiでも共有したい!ということでスクリプトを書いてみました。
実は、最初はinstagramの非公開APIを使ったスクリプトを書いていたんですが、自分の写真がFetchできなく(404が返ってくるように)なってしまったので、twitterを経由してmixiフォトにアップロードすることにしました。
やっていること
大きく分けて以下の3つです。
- 一日分のツイートからhttp://instagr.am/*のURLを取り出す
- http://instagr.am/* をスクレイピングして写真をダウンロード
- 600x600以上ならImage::Magickで半分にリサイズ
- mixiフォトにアップロード
- アップロード先のアルバムはinstagramという名前で事前に作成
後はcronを使って一日一回スクリプトを実行するようにしています。
スクリプト
ソースは以下の通りです。gist: 755514 - GitHubでも公開してます。
#!perl use strict; use warnings; use URI; use Web::Scraper; use Net::Twitter; use Config::Pit; use DateTime; use Encode qw(encode_utf8); use File::Basename; use File::Slurp; use XML::Simple; use Image::Magick; #### ツイートを取得 ############################## my $config = pit_get("twitter.com", require => { "username" => "your username on twitter.com", "consumer_key" => "your consumer_key on twitter.com", "consumer_secret" => "your consumer_secret on twitter.com", "access_token" => "your access_token on twitter.com", "access_token_secret" => "your token_secret on twitter.com" }); my $nt = Net::Twitter->new( traits => [qw/OAuth API::REST/], consumer_key => $config->{consumer_key}, consumer_secret => $config->{consumer_secret}, access_token => $config->{access_token}, access_token_secret => $config->{access_token_secret}, ); my $dt = DateTime->now( time_zone => 'Asia/Tokyo' ); $dt->subtract( days => 1 ); my $statuses = $nt->user_timeline({ since => $dt, count => '200', id => $config->{username} }); my @urls; for my $status (@$statuses) { if( $status->{text} =~ /(http:\/\/instagr.am\/.+)/ ) { push(@urls, $1); } } if( @urls == 0 ) { print "No new upload image to instagr.am\n"; exit(0); } #### インスタグラムのページをスクレイピング ############## my @photos; print "### Download Photos ###\n"; for my $url (@urls) { my $instagram = scraper { process ".photo", link => '@src'; }; my $res = $instagram->scrape(URI->new($url)); # ファイルをダウンロードする my $ua = LWP::UserAgent->new; my $file = basename($res->{link}); if( -e $file ) { print "Download skip : $file\n"; } else { $ua->mirror($res->{link}, $file); print "Downloaded : $file\n"; push(@photos, $file); } } # リサイズ my @r_photos; my $th_x = 600; my $th_y = 600; my $im = Image::Magick->new; for my $photo (@photos) { $im->Read($photo); my ($x, $y) = $im->Get('width', 'height'); if( $x >= $th_x && $y >= $th_y ) { $im->Resize( width => $x / 2, height => $y / 2 ); $im->Write( filename => "r_$photo" ); push(@r_photos, "r_$photo"); } else { push(@r_photos, $photo); } } ###### mixiに画像をアップロード ####################### my $config2 = pit_get("mixi.jp", require => { "mailaddress" => "your mailaddress on mixi.jp", "password" => "your password on mixi.jp" }); my $ua2 = LWP::UserAgent->new; $ua2->credentials('photo.mixi.jp:80', '', $config2->{mailaddress}, $config2->{password}); my $res2 = $ua2->get('http://photo.mixi.jp/atom/r=3'); die "Album Info can't get... : $res2->status_line\n" if $res2->is_error; ## アップロードするアルバムIDを取得 ## 事前に'instagram'というアルバムを作成しておく my $ref2 = XMLin($res2->content); my $href; my $title; foreach my $c (@{$ref2->{workspace}->{collection}}) { $title = encode_utf8($c->{'atom:title'}); if( ($title eq 'instagram') && ($c->{accept} eq 'image/jpeg') ) { $href = $c->{href}; } } die "Album not found...\n" . $title unless defined($href); ## 画像をアップロード print "### Upload Photos ###\n"; foreach my $r_image (@r_photos) { # アップロードするファイル my $f = read_file($r_image, binmode => ":raw"); my $r = $ua2->post($href, 'Content-Type' => 'image/jpeg', 'content' => join "", $f); if( $r->is_success ) { print "Upload done! : $r_image\n"; } else { print "Upload failed... : $r_image\;n"; } }