tohokuaikiのチラシの裏

技術的ネタとか。

mixiボイスの1日分をまとめてmixi日記に自動投稿するスクリプト

最近、twitterより流量が適当なmixiボイスの方を使うようになってきたんだけど、

みたいな意見もあって、そりゃそうだと思ってPHPスクリプト書いた。

これを毎日午前0時にcronで起動させればバッチリ!

DOMDocumentとPEAR::HTTP_Requestが必要。もう正規表現スクレイピングなんてしてられないですよねー。DOMDocumentってPHP5必須だっけ?

文字コードUTF-8にしてファイル保存。
あとは、コマンドラインからおもむろに実行させれば。・・・多分。

ま、とりあえず自分が使えれば。あと、イイネ!とコメントを全部とるとか面倒すぎてパス。

それと、1日に5ページ以上mixiボイス使うようなヒトは足りない。ページ設定はどっかにあるので見つける。$loop_pageだけど。

<?php
require_once 'HTTP/Request.php';
// 公開範囲設定
$diary_level_type = "friend_friend";
# $diary_level_type = "open";
# $diary_level_type = "close";

$mixi = new ITT_Mixi(自分のmixiID。123456とか、654とか);
if ($mixi->login(ログインのためのメールアドレス, ログインパスワード)){
    $mixi->getTodayVoice();
    $mixi->postTodayVoice($diary_level_type);
}

//////////////////////////////////////////////
class ITT_Mixi
{
    
    /**
     * 
     */
    private $req ;
    
    
    private $cookie;
    
    
    private $dom;
     
     
    private $id ;
    
    private $yesterday;

     
    /**
     * @brief 
     * @param 
     * @retval
     */
    function __construct($id)
    {
        $this->req = new HTTP_Request();
        $this->req->setURL('http://mixi.jp/');
        $this->dom = new DOMDocument();
        $this->id = $id;
        $this->yesterday = strtotime("-1 day");
    }
    
    

    
    /**
     * @brief 
     * @param 
     * @retval
     */
    function login($email, $pass)
    {
        $this->req->setURL('http://mixi.jp/login.pl?from=login0');
        $this->req->setMethod(HTTP_REQUEST_METHOD_POST);
        $this->req->addPostData('email', $email);
        $this->req->addPostData('password', $pass);
        $this->req->addPostData('next_url', '/home.pl');
        
        if ($this->req->sendRequest() === true){
            return $this->saveCookie();
        }
        
        return false;
    }
    
    
    
    private $my_voices = array();
    
    /**
     * @brief 
     * @param 
     * @retval
     */
    function getTodayVoice()
    {
        $yesterday = date('Ymd', $this->yesterday);
        
        $start_page = 1;
        $loop_page = 5;
        
        for ($page=$start_page; $page<=$loop_page; $page++)
        {
            $my_voices = array();
            $this->req->setURL('http://mixi.jp/list_voice.pl?page='.$page);
            $this->setCookie();
            if ($this->req->sendRequest() === true){
                if ($e =@$this->dom->loadHTML($this->req->getResponseBody())){
                    // <div class="voiced"><p>voice<span><a href></a></span></p></div>
                    $div = $this->dom->getElementsByTagName('div');
                    for ($i = 0; $i<$div->length; $i++){
                        $di = $div->item($i);
                        if ($di->getAttribute('class') == 'voiced'){
                            $p = $di->getElementsByTagName('p')->item(0);
                            $link = $p->getElementsByTagName('a');
                            if ($link->length > 0){
                                $href = $link->item($link->length -1)->getAttribute('href');
                                if (preg_match('/post_time=(\d+)/', $href, $m)){
                                    if (strncmp($yesterday, $m[1], 8) === 0){
                                        $span = $p->getElementsByTagName('span');
                                        $p->removeChild($span->item($span->length -1));
                                        $iine = array();
                                        $comment = array();
                                        if ($div->item($i+1)->getAttribute('class') == 'resArea'){
                                            $iine = $this->getIINE($div->item($i+1));
                                            $comment = $this->getComment($div->item($i+1)->getElementsByTagName('dl')->item(1));
                                        }
                                        $my_voices[] = array(
                                            'text' => trim($p->textContent),
                                            'date' => date('Y年n月j日 H時i分s秒', strtotime($m[1])),
                                            'iine' => $iine,
                                            'comment' => $comment,
                                            );
                                    }
                                }
                            }
                        }
                    }
                }
            }
            if (!$my_voices){
                break;
            }
            else {
                foreach ($my_voices as $voice){
                    $this->my_voices[] = $voice;
                }
            }
            sleep(5);
        }
    }
    
    
    
    /**
     * @brief 
     * @param 
     * @retval
     */
    function postTodayVoice($diary_level_type)
    {
        if (!count($this->my_voices)){
            return ;
        }
        
        $context = "";
        $this->my_voices = array_reverse($this->my_voices);
        foreach ($this->my_voices as $voice){
            $context .= sprintf("[m:80][%sのつぶやき]\n%s\n",
                                $voice['date'],
                                $voice['text']);
            if ($voice['iine']){
                $context .= "\n[m:87][イイネ!] ";
                foreach ($voice['iine'] as $iine){
                    $context .= sprintf("%s(id=%d), ", $iine['nickname'], $iine['userid']);
                }
                $context = rtrim($context, ", ");
            }
            if ($voice['comment']){
                $context .= "\n[m:96][コメント]\n";
                foreach ($voice['comment'] as $com){
                    $context .= sprintf("   %s(id=%d) %s\n", $com['nickname'], $com['userid'], trim($com['comment']));
                }
                $context = rtrim($context, ", ");
            }
            $context .= "\n-----\n";
        }

        $post_key = $this->preparePostDiary($diary_level_type);
        $title = sprintf("%d月%d日のmixiボイス寄せ集め", 
                         date('n', $this->yesterday),
                         date('j', $this->yesterday));
        
        $title   = mb_convert_encoding($title, 'EUC-JP', 'UTF-8');
        $context = mb_convert_encoding($context, 'EUC-JP', 'UTF-8');
        
        $this->req->setURL('http://mixi.jp/add_diary.pl');
        $this->req->setMethod(HTTP_REQUEST_METHOD_POST);
        $this->req->addPostData('diary_title', $title);
        $this->req->addPostData('diary_body',  $context);
        $this->req->addPostData('id', $this->id);
        $this->req->addPostData('post_key', $post_key);
        $this->req->addPostData('submit', 'confirm');
        $this->req->addPostData('tag_id', '0');
        $this->req->addPostData('viewer_list_hide_flag', '1');
        $this->setCookie();
        
        if ($r = $this->req->sendRequest() === true){
            $check_reg = mb_convert_encoding('/書き込みが完了しました。反映に時間がかかることがあります。/',
                                             'EUC-JP', 'UTF-8');
            $response = $this->req->getResponseBody();
            if (preg_match($check_reg, $response )){
                echo date('Y年n月j日')." [success]\n";
                return ;
            }
            else {
                echo date('Y年n月j日')." [failed]\n";
            }
        }
        else {
            echo $r->getMessage();
        }
        
//        echo $response;
        return ;
    }
    
    
    
    /**
     * @brief 
     * @param 
     * @retval
     */
    function preparePostDiary($diary_level_type)
    {
        $this->req->setURL('http://mixi.jp/add_diary.pl');
        $this->req->setMethod(HTTP_REQUEST_METHOD_POST);
        $this->req->addPostData('diary_title', 'test###');
        $this->req->addPostData('diary_body',  'textarea####testaaa');
        $this->req->addPostData('diary_level_type', $diary_level_type);
        $this->req->addPostData('id', $this->id);
        $this->req->addPostData('submit', 'main');
        $this->setCookie();
        
        if ($this->req->sendRequest()){
            if ($e =@$this->dom->loadHTML($this->req->getResponseBody())){
                $input = $this->dom->getElementsByTagName('input');
                for ($i = 0; $i<$input->length; $i++){
                    if ($input->item($i)->getAttribute('name') == "post_key"){
                        return $input->item($i)->getAttribute('value'); 
                    }
                }
            }
        }
        
        return false;
    }
    

    /**
     * @brief 
     * @param 
     * @retval
     */
    private function getIINE($div)
    {
        $iine = array();
        
        $dd = $div->getElementsByTagName('dd');
        for ($i = 0; $i<$dd->length; $i++){
            if ($dd->item($i)->getAttribute('class') == "feedback"){
                $a = $dd->item($i)->getElementsByTagName('a');
                for ($j = 0; $j<$a->length; $j++){
                    $iine[] = array(
                        'nickname' => trim($a->item($j)->textContent),
                        'userid'   => substr($a->item($j)->getAttribute('href'),
                                             strlen('show_friend.pl?id='))
                        );
                }
            }
        }
        
        return $iine;
    }
    
    

    /**
     * @brief 
     * @param 
     * @retval
     */
    private function getComment($dl)
    {
        $comment = array();
        
        $div = $dl->getElementsByTagName('div');
        for ($i = 0; $i<$div->length; $i++){
            if (!$div->item($i)->getAttribute('class')){
                $com_a = $div->item($i)->getElementsByTagName('a')->item(0);
                $com_p = $div->item($i)->getElementsByTagName('p')->item(0);
                $comment[] = array(
                    'nickname' => trim($com_a->textContent),
                    'userid'   => substr($com_a->getAttribute('href'),
                                         strlen('show_friend.pl?id=')),
                    'comment'  => $com_p->textContent,
                    );
            }
        }
        
        return $comment;
    }
    
    
    
    /**
     * @brief 
     * @param 
     * @retval
     */
    private function saveCookie()
    {
        $cookie = $this->req->getResponseCookies();
        foreach ($cookie as $c){
            $this->cookie[$c['name']] = $c['value'];
        }
        if (isset($this->cookie['BF_STAMP']) &&
            isset($this->cookie['BF_SESSION'])){
            return true;
        }
        
        return false;
    }
    
    
    /**
     * @brief 
     * @param 
     * @retval
     */
    private function setCookie()
    {
        foreach ($this->cookie as $name => $value){
            $this->req->addCookie($name, $value);
        }
    }
}
?>