自分の運営している「ダメ系ライブカレンダー」の情報を前から定期的にツイートしたいな、と思っていたんですが、ようやく実装できました。
なので、その実装をするためにやったことをまとめておきたいと思います。
定期ツイートに必要なもの
・cron:決まった時間にCGIを実行してくれる機能。ロリポップサーバの場合ユーザーページで設定できる。
・Twitterアカウント:定期ツイート用のアカウント。すでにあるアカウント(@dameLive_info)を使用。
・Easybotter:TwitterのBotを簡単に作成できるように作られたスクリプト。phpで書かれている。詳細はEasybotterのサイトへ
・ツイート用テキストの作成プログラム:これを自作。これが今回大変だった。
定期ツイートの手順
今回定期ツイートさせるためにいろいろ考えて試して、落ち着いた手順は以下の通り。
1)0:00にcronでテキスト生成PGをたたく
2)その日にツイートする用のテキストファイルを生成
3)cronで5分毎にEasyBotterをたたき、決まった時間であればツイートさせる
こんな感じで動かすようにしました。
EasyBotterは1回たたかれたら1回しかツイートしないらしい。
ツイートしたい内容が1つ以上なら、cronで何分毎に実行、と指定しないといけないようです。
今回は、夜中朝昼晩にツイートをしたかったので、EasyBotterのほうで「この時間帯にはこのファイルの内容をツイート」という指定をし、それ以外はツイートしない、という形をとりました。
テキスト生成について
今回大変だったのは、ツイート内容を作るためのファイル作成。
ダメ系ライブカレンダーはWordPressで作ってるんですが、ライブ情報を表示させる部分はカスタム投稿で作っているんですね。
最初は、WPだしRSSをとってきて、ファイルを作ろうとしたんです。
RSSをとってきて作る場合はこんな感じですね。
<?php $html = file_get_contents('https://memo.ark-under.net/feed'); $xmlObject = simplexml_load_string($html); $dataline = array(); foreach ( $xmlObject as $channel ) { foreach ( $channel as $item ) { $title = $item->title; // タイトル $link = $item->link; // リンク $date = $item->pubDate; // 日付 $date = date('Y.n.j', strtotime($date)); $itemData = $title.'('.$link.')- '.$date; // 文字化けするので変換 $itemData = mb_convert_encoding($itemData, 'HTML-ENTITIES', 'UTF-8'); if($title){echo "<p>$itemData<p>";} } } ?>
そしたら、カスタム投稿のRSSをうまく表示させることができない…!
いろいろ試してみるものの、全然できなくて。さて困った。
次に試したのは、RSSがなくても表示されている状態(つまりHTML)をとってきて解析、という方法。
参考)PHPでHTMLをパースして解析する簡単な方法 | 三度の飯とエレクトロン
<?php $html = file_get_contents('http://dame-live.info/'); $html = mb_convert_encoding($html, 'HTML-ENTITIES', 'ASCII, JIS, UTF-8, EUC-JP, SJIS'); $domDocument = new DOMDocument(); $domDocument->loadHTML($html); $xmlString = $domDocument->saveXML(); $xmlObject = simplexml_load_string($xmlString); $array = json_decode(json_encode($xmlObject), true); $title = $array['head']['title']; $title = mb_convert_encoding($title, 'HTML-ENTITIES', 'UTF-8'); header("Content-type: text/plain; charset=UTF-8"); echo $title; //var_dump($array); ?>
・サンプル2(バージョンのせいかエラーが出てます…)
上記のサンプルコードのようにheadのtitleが取れてるから、後も同じ感じでできるだろ、と思ってたんです。
それがどっこい。
body以下となると配列の配列の配列の(ry…中に必要な情報がある、という状態で、これがまた、全くもってできませんでした_(:3 」∠ )_
(その状態が見たい人は、上記コードの最後のコメントアウトを消して実行してみるといいですよ…)
やべー詰んだ/(^o^)\ とか思ってたんですが、ググってたらこんな記事に遭遇。
・PHPでHTMLをパースして解析、編集して保存する方法 – さとうさんのキロク
この記事で紹介されている「PHP Simple HTML DOM Parser」これがすごい。
まるでjQueryのように必要なタグやクラスを探しだし、情報を抜き出せるのだ。
これなら配列の配列の配列の(ry…中を探さなくていいんだ!
で、できたのがこんな感じ。
<?php require_once 'simple_html_dom.php'; $ENTI = 'HTML-ENTITIES'; $CODE = 'ASCII, JIS, UTF-8, EUC-JP, SJIS'; $linedata = 'data.txt'; //ファイル形式で読み込む $dom = file_get_html('http://dame-live.info/'); foreach($dom->find('div.box-list-live') as $article) { $item['title'] = $article->find('h3', 0)->plaintext; $item['link'] = $article->find('h3 a', 0)->href; $item['link'] = mb_convert_encoding($item['link'], $ENTI, $CODE); $item['date'] = $article->find('p.date', 0)->innertext; $item['date'] = mb_convert_encoding($item['date'], $ENTI, $CODE); $articles[] = $item; } $datalines = array(); foreach($articles as $value){ $AdateY = substr($value['date'], 58,4); $AdateM = substr($value['date'], 70,2); $AdateD = substr($value['date'], 80,2); $Adate = $AdateY.'-'.$AdateM.'-'.$AdateD; $Vdate = $AdateY.'年'.$AdateM.'月'.$AdateD.'日'; $LiveDateTime = strtotime($Adate); $nowDateTime = strtotime(date('Y-m-d')); $interval = ($LiveDateTime - $nowDateTime) / ( 60 * 60 * 24); if($interval == 0){ $valueData = '【本日開催!】'.$Vdate.' '.$value['title'].' '.$value['link']."\n"; array_push($datalines, $valueData); }elseif($interval == 1){ $valueData = '【明日開催!】'.$Vdate.' '.$value['title'].' '.$value['link']."\n"; array_push($datalines, $valueData); }elseif(($interval == 2) || ($interval == 6)){ $valueData = '【近日開催!】'.$Vdate.' '.$value['title'].' '.$value['link']."\n"; array_push($datalines, $valueData); }elseif(($interval == 13)){ $valueData = '[2週間前]'.$Vdate.' '.$value['title'].' '.$value['link']."\n"; array_push($datalines, $valueData); }elseif(($interval == 29)){ $valueData = '[1ヶ月前]'.$Vdate.' '.$value['title'].' '.$value['link']."\n"; array_push($datalines, $valueData); } } $lnlines = $lnext ? file($linedata) : array(); unset($lnlines); $lnlines = $datalines; $fk = @fopen( $linedata, 'w' ); foreach( $lnlines as $lnline ) fputs( $fk, $lnline ); fclose( $fk ); chmod($linedata, 0606); $dom->clear(); header("Content-type: text/html; charset=UTF-8"); foreach($datalines as $text){ echo $text.'<br>'; } echo '<br><a href="'.$linedata.'">テキストデータ('.$linedata.')を見る</a>'; ?>
これはサンプルなので1つのファイルしか書き出してませんが、実際には時間帯別にツイートさせるためにファイルを4つ書き出してます。
ファイルごとにツイート内容のテンプレが少し変えて(!の数とか)書き出しました。全く同じ内容だと10post後か24時間以上たたないとツイートできないから、です。
また、最後にファイルのパーミッションを「0606」にしてますが、こうしないとEasyBotterが1つのファイルの最初の行しかツイートしないんですって。
そんなこんなで定期ツイート機能ができました
ダメ系ライブカレンダーは、ダメ系ライブをやりたい人たちのライブ宣伝のお手伝いがしたい!ダメ系ライブがみたい人たちに情報をお知らせしたい!というのが目的で始めたので、ようやく本来の役割を果たせるようになったかな、という感じです。
まだまだツイート頻度や時間帯などを調整するので、様子見ながら落ち着くとこに落ち着けたいな。
そんなわけで、今後とも「ダメ系ライブカレンダー」をよろしくお願いします。