Facebook にシェア
[`evernote` not found]
LINEで送る

Twitterのfeedが取得できるようになったので何か面白いことができないかと思い色々探していたらマルコフ連鎖という面白い仕組みがみつかりました。
Yahooの形態素解析を利用して文章を作成するみたいです。
早速TwitterのツイートをRSSから取得して自動文章を作成する関数を作ってみました。

参考
http://dogmap.jp/2008/08/27/markov-text-generator/

Twitter自動文章作成

<?php
function Tweet_to_markov($max_length = 120){

//APIキーを登録。取得はhttps://e.developer.yahoo.co.jp/webservices/register_applicationから
$aid = 'YahooAPI KEY';

//検索キーワード。Twitterの検索条件が使えます。
$seachword = "TwitterSearchWord";
$query = "q=" . $seachword;

//一度に読み込む件数
$rpp  = "20";
	if($rpp){$query .= '&rpp=' . $rpp;}
	$uri = "http://search.twitter.com/search.atom?{$query}";
	include_once(ABSPATH . WPINC . '/feed.php');
	$rss = fetch_feed($uri);
	$content="";
	if ( !is_wp_error( $rss ) ){
		//feach_feedの初期設定 キャッシュ5分
		$rss->set_cache_duration(300);
		$rss->init();
		$maxitems = $rss->get_item_quantity($rpp);	
		$rss_items = $rss->get_items(0, $maxitems);
		
		//title部分(Twitterの整形前のソース)を件数分取得
		foreach ( $rss_items as $item ) {	
			$content .= $item->get_title() . "\n";
		}
		
		//ハッシュタグとリプライとリンクは削除。
		$content = preg_replace('/(#)(\w+)/','',$content);
		$content = preg_replace('/(@)(\w+)/','',$content);
		$content = preg_replace('/(https?|ftp)(:\/\/[-_.!~*\'()a-zA-Z0-9;\/?:\@&=+\$,%#]+)/','',$content);
		
		//テキストの合計文字数を制限
		$content = substr( $content, 0, 35500 );
		
		//yahoo日本語形態素解析の設定
		$url = "http://jlp.yahooapis.jp/MAService/V1/parse";
		$data = array('appid' => $aid,'sentence' => $content,'results' => 'ma,uniq');
		$options = array('http' => array(
			'method' => 'POST',
			'content' => http_build_query($data)
		));
		
		//日本語形態素解析開始
		$word_xml = file_get_contents($url, false, stream_context_create($options));
		$xml = simplexml_load_string($word_xml);
		
		//ワードが存在し、かつ半角全角スペースでない場合ワード登録
		foreach($xml->ma_result->word_list->word as $value){
			if(preg_match("/(.+)/",$value->surface) && !preg_match("/(\s| )/",$value->surface)){$words[] = (string)$value->surface;}
		}
		
		//よく出るワードTOP10を設定
		$rank=0;
		$pattern = "/(";
		foreach($xml->uniq_result->word_list->word as $value){
			if($value->pos == "名詞"){
				$pattern .= $value->surface;$rank++;
				if($rank==10){break;}else{$pattern .= "|";}
			}
		}
		$pattern .= ")/";
		$words[] = "\n";
		

	if ($words) { //分かち書きデータがあれば
		$head   = array();
		$word   = array(null, null, null);
		$markov = array();
		
		for ($i=0 ; $i<count($words) ; $i++) {
			if ($word[0] === null) {
		      $word[0] = $words[$i];
		    } elseif ($word[1] === null) {
		      $word[1] = $words[$i];
		    } else {
			
			//頻出単語 Top10 を文頭候補にする
			
      		if(preg_match($pattern,$word[0])) {
		    	$head[] = array("",$word[0], $word[1]);
			}
			
		      //マルコフ連鎖用テーブル
		      if (!(isset($markov[$word[0]][$word[1]]) && is_array($markov[$word[0]][$word[1]]))) {
		        $markov[$word[0]][$word[1]] = array();
		      }
		      $markov[$word[0]][$word[1]][] = array($word[0], $word[1], $words[$i]);
		      $word[0] = $words[$i - 1];
		      $word[1] = $words[$i];
		    }
		}
		  //頻出単語 Top10 の内のどれかを文頭にする		
		  $word = $head[array_rand($head)];
		  $create_text = $word[0].$word[1].$word[2];
		  unset($head);
		  // マルコフ連鎖で文章生成
		  $break_flag=0;
		  for ($i=0 ; $i<500 ; $i++) { //無限ループ回避
		    // つながりは選択できる中からランダムに選択
		    if (isset($markov[$word[1]][$word[2]]) && is_array($markov[$word[1]][$word[2]])) {
		      $word = $markov[$word[1]][$word[2]][array_rand($markov[$word[1]][$word[2]])];
			  //連鎖した結果最大文字数を超えそうなら強制終了
			  if (mb_strlen($create_text . $word[2]) >= $max_length){$break_flag=1;break;}
		      $create_text .= $word[2];
		      $create_text = preg_replace('/[[^]]*]/', "", $create_text);
		    } else {
		      break;
		    }
		    //文章終わり
		    if ($break_flag) break;
		  }
		  unset($word);
		  unset($markov);  
		
		return $create_text;
	} else {
		return "データがありませんでした";
	}		
		
	}

}

?>

使用にはYahooデベロッパーAPIが必要です。
検索ワードとAPIキーを設定したら出力をしたい場所で
echo Tweet_to_markov()
で自動生成された文章が出力されます。

しかし適当に作ったせいかどうも読み込む速度が遅い。もう少しちゃんとカスタマイズする必要がありそうですね。