■
なんだかmixiが変わったようで、書き込みが出来なくなってたので、ちょびっと修正。
#!/usr/bin/perl use strict; use warnings; use Jcode; use LWP::UserAgent; use HTTP::Cookies; use URI; $| = 1; # formを含んだhtmlをgetするためのurl。 my $login_url = 'https://mixi.jp'; # ホームのURL。 my $home_url = 'http://mixi.jp/home.pl'; # 日記入力フォームのurl # my $add_form_url = 'http://mixi.jp/add_diary.pl'; my $pre_add_form_url = 'http://mixi.jp/list_diary.pl'; # データの保存先ディレクトリ。 my $data_dir = './'; ################################################## # cookieの保存先。 my $cookie_file = $data_dir . 'cookies.txt'; # 「読んだ」の保存先。 my $read_file = $data_dir . 'read.txt'; # 待ち時間。 my $sleep_time = 1; # 文字コード。 my $mixi_code = 'euc'; # あっち側の文字コード。 my($term_code)= getcode( 'こっち側' ); # こっち側の文字コード。 # w3mを使うか。 my $use_w3m = 1; my $w3m_command = "w3m -I $mixi_code -O $term_code -dump -T text/html"; # idとパス。 my $id = ''; my $pass = ''; ################################################## unless( $id ){ print "id : "; $id = <STDIN>; } unless( $pass ){ print "pass : "; $pass = <STDIN>; } # mixiの文字コードに変更。 my ${oshirase} = jcode('お知らせ')->$mixi_code; my ${kanryoushimashita} = jcode('作成が完了しました。')->$mixi_code; my ${ikanonaiyou} = jcode('以下の内容で作成します。よろしいですか?')->$mixi_code; my ${sakuseigakannryou} = jcode('作成が完了しました。')->$mixi_code; ################################################## # UA準備。 my $ua = new LWP::UserAgent; # $ua->cookie_jar( new HTTP::Cookies ); $ua->cookie_jar( HTTP::Cookies->new( file => $cookie_file, autosave => 1, ignore_discard => 1, ) ); # LWP::UserAgentのProxyを使うか、Crypt::SSLeayのProxyを使うか。 # JEDのproxyは、LWP::UserAgentのプロキシサポートだとうまくいかないようだ。 my $use_LWP_proxy_http = 1; # よく考えたら、Crypt::SSLeayは、httpsだけだ。 my $use_LWP_proxy_https = 0; if( $use_LWP_proxy_http ){ $ua->proxy( 'http', $ENV{http_proxy} ) if $ENV{http_proxy}; }else{ } if( $use_LWP_proxy_https ){ $ua->proxy( 'https', $ENV{http_proxy} ) if $ENV{http_proxy}; }else{ $ENV{https_proxy} = $ENV{http_proxy} if $ENV{http_proxy}; } # $ua->env_proxy; # LWP::UserAgentのproxyの設定を表示。 # print 'http => ', $ua->proxy( 'http' ), "\n"; # print 'https => ', $ua->proxy( 'https' ), "\n"; if( @ARGV == 0 ){ &main_get_login_page( $ua ); }elsif( $ARGV[0] =~ /home/i ){ &main_home( $ua ); }elsif( $ARGV[0] =~ /all/i ){ &main_home( $ua, undef, 'all' ); }elsif( $ARGV[0] =~ /read/i ){ &main_home( $ua, undef, 'read' ); }elsif( $ARGV[0] =~ /add/i and 2 == @ARGV ){ &main_get_add_form( $ua, $ARGV[1] ); # 書き込み。 }elsif( 1 == @ARGV and -e $ARGV[0] ){ # 引数1個の最後に。 &main_get_add_form( $ua, $ARGV[0] ); # 書き込み。 }else{ die "ARGV = @ARGV\n"; } sub main_get_login_page{ # ログインページを取ってくる。 my( $ua ) = @_; my $res = &get( $ua, $login_url ); # ほんとにmixiのログインページか、軽くチェック。 if( not &is_mixi_login( $res->content ) ){ if( &is_mixi_home( $res->content ) ){ print STDERR "ログイン済み。\n"; &main_home( $ua, $res ); exit; } print STDERR $res->content; die "ログインページじゃない。"; } &main_login( $ua, $res ); } sub main_login{ # ログインする。 my( $ua, $res ) = @_; my %form = &get_form_values( $res->content ); die 'postじゃないよ。' unless $form{method} =~ /post/i; my $action_url = URI->new_abs( $form{action}, $res->base ); delete $form{method}; delete $form{action}; # IDとパスワードの挿入。 $form{email} = $id; $form{password} = $pass; $res = &get( $ua, $action_url, %form ); if( not &is_mixi_login_ok( $res->content ) ){ die "ログイン失敗。\n"; } &main_home( $ua, $res ); } sub main_home{ my( $ua, $res, $type ) = @_; # $uaは必須。 # $type は、'all'や'read' unless( defined $res and &is_mixi_home( $res->content ) ){ $res = &get( $ua, $home_url ); die 'ホームが表示できない?' unless &is_mixi_home( $res->content ); } my( $info ) = ( $res->content =~ m{<!-- start: ${oshirase} -->(.*)<!-- end: ${oshirase} -->}s ); die 'お知らせが切り取れんかった。' unless $info; &print_html( $info ) if( $type and $type eq 'all' ); my( $update ) = ( $res->content =~ m{<!-- start: update information -->(.*)<!-- end: update information -->}s ); die '最新情報が切り取れんかった。' unless $update; &print_html( $update ) if( $type and $type eq 'all' ); # 最新情報の中の、マイミクシィ最新日記を表示。 my( %read, %new_read ); if( -e $read_file ){ # read_fileから既読タイトルを読み込み。 open READ, "<", $read_file or die "${read_file}が開けんかった。"; while( <READ> ){ chomp; $read{ $_ } = 1; } close READ; } for my $message ( $update =~ m{(<img[^>]*>.*?<br[^>]*>)}sg ){ next unless $message =~ /pen\.gif/; $message =~ s/<[^>]+>//g; # タグ除去。 $message =~ s/\s//g; # 空白(主に改行)除去。 next if $read{ $message }; # 既読は表示しない。 $new_read{ $message } = 1 if $type and $type eq 'read'; print '-'x50, "\n${message}\n", '-'x50, "\n"; } if( $type and $type eq 'read' and %new_read ){ # read_fileへの追加。 print "${read_file}に追加。\n"; open READ, ">>", $read_file or die "${read_file}が開けんかった。"; for my $message ( keys %new_read ){ print '-'x50, "\n${message}\n", '-'x50, "\n"; print READ $message, "\n"; } close READ; } # お知らせの中の、赤文字を表示。 for my $message ( $info =~ m{<font color=red>(.*?)</font>}g ){ $message =~ s/<[^>]+>//g; # タグ除去。 print '='x50, "\n${message}\n", '='x50, "\n"; } } sub main_get_add_form{ my( $ua, $inputfile ) = @_; # my $res = &get( $ua, $add_form_url ); my $res = &get( $ua, $pre_add_form_url ); my %form = &get_form_values( $res->content ); die 'postじゃないよ。' unless $form{method} =~ /post/i; my $action_url = URI->new_abs( $form{action}, $res->base ); delete $form{method}; delete $form{action}; # こんどこそ、日記の入力ページ。 $res = &get( $ua, $action_url, %form ); # ほんとに日記の入力ページか、軽くチェック。 if( not &is_mixi_add_form( $res->content ) ){ if( &is_mixi_login( $res->content ) ){ print STDERR "未ログインです。\n"; exit; } print STDERR $res->content; die "入力ページじゃない。"; } &main_add_diary( $ua, $res, $inputfile ); } sub main_add_diary{ my( $ua, $res, $inputfile ) = @_; my %form = &get_form_values( $res->content ); die 'postじゃないよ。' unless $form{method} =~ /post/i; my $action_url = URI->new_abs( $form{action}, $res->base ); delete $form{method}; delete $form{action}; delete $form{photo1}; delete $form{photo2}; delete $form{photo3}; ( $form{diary_title}, $form{diary_body} ) = &diary_text( $inputfile ); # プレビュー。 $res = &get( $ua, $action_url, %form ); # プレビューページに行けてるかチェック。 if( not &is_mixi_preview( $res->content ) ){ if( &is_mixi_alert( $res->content ) ){ my( $alert ) = ( $res->content =~ m{<!-- start: alert -->(.*)<!-- end: alert -->}s ); &print_html( $alert ); die '入力失敗。'; } die '入力失敗。'; } %form = &get_form_values( $res->content ); die 'postじゃないよ。' unless $form{method} =~ /post/i; $action_url = URI->new_abs( $form{action}, $res->base ); delete $form{method}; delete $form{action}; # 書き込み。 $res = &get( $ua, $action_url, %form ); # 書き込みチェック。 if( &is_mixi_add_success( $res->content ) ){ my( $message ) = ( $res->content =~ m|(<b>${kanryoushimashita}.*?</b>)| ); &print_html( $message ); exit; }else{ die '書き込み失敗?'; } } use URI::Escape; sub get { my( $ua, $url, %form ) = @_; my $req; if( %form ){ # POST $req = HTTP::Request->new( POST => $url ); $req->content_type( 'application/x-www-form-urlencoded' ); $req->content( join '&', map { uri_escape( $_ ) . '=' . uri_escape( $form{ $_ } ) } keys %form ); # $req->content( join '&', map { enc( $_ ) . '=' . enc( $form{ $_ } ) } keys %form ); sub enc{ my( $txt ) = @_; return join '', map { sprintf "%%%02X", $_ } unpack( "C*", $txt ); } }else{ # GET $req = HTTP::Request->new( GET => $url ); } print STDERR '受信中(', $req->uri, ')'; sleep $sleep_time; my $res = $ua->request( $req ); print STDERR "。\n"; die $res->error_as_HTML if $res->is_error; return $res; } sub get_form_values{ my( $content ) = @_; my %form_values; my $tag; ( $tag, $content ) = ( $content =~ m|(<form[^>]*>)(.*)|is ); $form_values{ action } = &get_value( $tag, 'action' ); $form_values{ method } = &get_value( $tag, 'method' ); sub get_value{ my( $tag, $name ) = @_; my $value; if( $tag =~ /${name}=([\'\"])/i ){ #" my $quot = $1; ( $value ) = ( $tag =~ /${name}=${quot}(.*?)${quot}/si ); }else{ ( $value ) = ( $tag =~ /${name}=(.*?)[\s>]/si ); } return $value; } while( $content =~ m{(<(input|textarea|/form)[^>]*>)}gis ){ $tag = $1; last if $tag =~ m{</form>}i; my $name = &get_value( $tag, 'name' ); next if not defined $name; my $value = &get_value( $tag, 'value' ); $value = '' if not defined $value; $form_values{ $name } = $value; } return %form_values; } sub print_html{ # html(の断片)を、見やすく表示。 my( $html ) = @_; if( $use_w3m ){ #w3m使用。 open my $w3m, "| ${w3m_command}"; print $w3m $html; close $w3m; }else{ # w3m不使用。 $html =~ s/<[^>]*>//g; $html =~ s/\n+/<br>/g; $html =~ s/\s+/ /g; $html =~ s/<br>/\n/g; $html =~ s/[\n ]+/\n/g; print jcode("\n$html\n")->sjis; } } sub is_mixi_login{ # ログインページかどうか。 local( $_ ) = @_; return 0 unless /loginbtn.gif/; return 1; } sub is_mixi_login_ok{ # ログインに成功したかどうか。 return 0 unless @_; return not &is_mixi_login_fail( @_ ); } sub is_mixi_login_fail{ # ログインに失敗したかどうか。 local( $_ ) = @_; return 0 unless m|remind_password.pl|; return 1; } sub is_mixi_home{ # homeかどうか。 local( $_ ) = @_; return 0 unless m|http://img.mixi.jp/img/info2.gif|; return 1; } sub is_mixi_add_form{ # 日記の入力画面かどうか。 local( $_ ) = @_; return 0 unless m|<textarea name="diary_body"|; return 1; } sub is_mixi_preview{ # プレビューの画面まで行けたかどうか。 local( $_ ) = @_; return 0 unless m|${ikanonaiyou}|; return 1; } sub is_mixi_alert{ # [!]の画面。 local( $_ ) = @_; return 0 unless m|start: alert|; return 1; } sub is_mixi_add_success{ # 書き込みに成功したか。 local( $_ ) = @_; return 0 unless m|${sakuseigakannryou}|; return 1; } sub diary_text{ # 何をタイトルにし、何を本文にするのか。 my $filename = shift; my( $title, $body ); open DATA, $filename or die $filename . 'が開けない。'; my @input = <DATA>; close DATA; if( ( 3 < @input ) and ( $input[1] =~ /^$/ ) ){ # 3行以上で、2行目が空行の場合、1行目をタイトルに、3行目以降を本文にする。 $title = $input[0]; $body = join '', splice @input, 2; }else{ # それ以外の場合は、タイトルは、「_」で、入力すべてを本文にする。 $title = '_'; $body = join '', @input; } return ( $title, $body ); }