すこしラズベリーパイで遊んでみた。
以前にダウンロードしたことがあった、Wikipediaのデータを使って
なにかできないかと思い、
巨大なWikipediaデータからタイトルとそのよみがな、概要だけを抽出して、データベース化。
それをラズベリーパイに覚えてもらって、「しりとり」でもやってみようと思う。
Wikipediaのデータはここにあって
http://dumps.wikimedia.org/jawiki/latest/
以下のURLに説明があった。
http://www.mwsoft.jp/programming/munou/wikipedia_data_list.html
入手したのは「jawiki-latest-abstract.xml」というもので、
タイトルや概要が記載れている1.5GB程度のファイル。
xml形式になっており、ちょっと困った。
xml2csv的なものはいろいろありそうだけど、phpの勉強を兼ねて自作。
(その他に、いくつかフィルタしたいこともあったので)
先ほどのファイルはこんな感じ
<title>Wikipedia: 言語</title>
<url>http://ja.wikipedia.org/wiki/%E8%A8%80%E8%AA%9E</url>
<abstract>言語(げんご)とは、コミュニケーションのための記号の体系である。</abstract>
<links> …省略
<url>http://ja.wikipedia.org/wiki/%E8%A8%80%E8%AA%9E</url>
<abstract>言語(げんご)とは、コミュニケーションのための記号の体系である。</abstract>
<links> …省略
これの、<title>のWikipedia:以降〜</title>までを名称として、
<abstract>内を概要とした。
よみがなは、以下のルールで生成した。
1.タイトルがすべてひらがな→タイトルをよみがな
2.タイトルがすべてカタカナ→ひらがなに変換してよみがなとする
3.アブストラクトにタイトル(説明) があれば、説明をひらがなにしてみる
3−1.そのさい、スペースや-・などの区切り文字があったら、そこまでで切り取る
そのほか「〜の一覧」などのまとめページは除外した。
全容がこれ
<>
<?php
mb_language('Japanese');
mb_internal_encoding('UTF-8');
mb_regex_encoding("UTF-8");
//タイトル
$title_start_string="Wikipedia: ";
$title_start_string_len = mb_strlen($title_start_string);
$title_end_string=" ";
$title_end_string_len = mb_strlen($title_end_string);
//アブスト
$abst_start_string="";
$abst_start_string_len = mb_strlen($abst_start_string);
$abst_end_string=" ";
$abst_end_string_len = mb_strlen($abst_end_string);
//
$mode = 0;
$testval_tit = '';
$testval_abs = '';
$testval_kana = '';
$cnt_k = 0;
$cnt_r = 0;
$cnt_ng = 0;
if($argc > 1){
try {
$pdo = new PDO('mysql:dbname=test;host=192.168.4.135', 'username', 'password',array(PDO::MYSQL_ATTR_LOCAL_INFILE => true));
} catch (PDOException $e) {
exit('データベースに接続できませんでした。' . $e->getMessage());
}
$stmt = $pdo->query('SET NAMES utf8');
if (!$stmt) {
$info = $pdo->errorInfo();
exit($info[2]);
}
$stmt = $pdo->query('set character_set_database=utf8');
if (!$stmt) {
$info = $pdo->errorInfo();
exit($info[2]);
}
echo "読み取り開始・・・\n";
$time_start = microtime(true);
$fp = fopen($argv[1], "r");
$temp_file = tempnam(sys_get_temp_dir(), 'Tux');
$fpw = fopen($temp_file, "w");
while ($line = fgets($fp)) {
if($mode == 0){
//タイトル探し
$testval_tit = searchStr($line,$title_start_string,$title_start_string_len,$title_end_string,$title_end_string_len);
if($testval_tit !== ''){
//echo "->".$line;
//echo "名称=".$testval_tit."\n";
$cnt_k = $cnt_k + 1;
$mode = 1;
}
}elseif($mode == 1){
//アブスト探し
$testval_abs = searchStr($line,$abst_start_string,$abst_start_string_len,$abst_end_string,$abst_end_string_len);
if($testval_abs !== ''){
//echo "->".$line;
//echo " 概要=".$testval_abs."\n";
$testval_kana = seikei2($testval_abs,$testval_tit);
if($testval_kana !== ''){
/*echo "==============================\n";
echo "名称=".$testval_tit."\n";
echo " 概要=".$testval_abs."\n";
echo " よみがな=".$testval_kana."\n";
echo "==============================\n";*/
fwrite($fpw,$pdo->quote($testval_kana).",".$pdo->quote($testval_tit).",".$pdo->quote($testval_abs)."\n");
$cnt_r = $cnt_r + 1;
//if($cnt_r > 1000) break;
}else{
/*echo "【NG】名称=".$testval_tit."\n";
echo "【NG】よみがな=".$testval_kana."\n";
echo "【NG】概要=".$testval_abs."\n";*/
$cnt_ng = $cnt_ng + 1;
}
$mode = 0;
}
}
}
fclose($fpw);
fclose($fp);
$timelimit = microtime(true) - $time_start;
echo "\n".$timelimit." seconds\n";
echo "総数:".$cnt_k." 有効数:".$cnt_r." 無効数:".$cnt_ng." ".(100*$cnt_r/$cnt_k)."%\n";
echo "DBに書き込み開始・・・"."'".$temp_file."'\n";
$time_start = microtime(true);
$stmt = $pdo->query("LOAD DATA LOCAL INFILE ".
"'".$temp_file."' REPLACE INTO TABLE `test`.`wiki` ".
"FIELDS TERMINATED BY ',' ENCLOSED BY '\'' LINES TERMINATED BY '\n' (`kana`, `name`, `gaiyo`);");
if (!$stmt) {
$info = $pdo->errorInfo();
exit($info[2]);
}
$timelimit = microtime(true) - $time_start;
echo "\n".$timelimit." seconds\n";
$pdo = null;
}
function seikei2($abs,$title){
$retval = "";
//〜の一覧ってやつはいらない
if(!endsWith($title,"一覧")){
$t_title = mb_convert_kana(seikei($title),"c");
if(preg_match("/^[ぁ-ゞー]+$/u",$t_title)){
//タイトルが全部ひらがなだった
$retval = $t_title;
//}elseif(preg_match("/^[ァ-ヶー]+$/u",$t_title)){
// //タイトルが全部カタカタだった→ひらがなに変換
// $retval = $t_title;
}else{
$testval_k = searchStr($abs,$title."(",mb_strlen($title)+1,")",1);
if($testval_k !== ''){
//ひらがなにしてみる
$testval_kana = mb_convert_kana(seikei($testval_k),"c");
if(preg_match("/^[ぁ-ゞー・]+$/u",$testval_kana)){
$retval = $testval_kana;
}
}
}
}
return $retval;
}
function seikei($str){
//空白や-を削除、区切り文字があれば先頭を返す
$retval = "";
$str_s = mb_ereg_replace("[-\s\u00A0\u3000・]","",$str);
//$str_s = mb_ereg_replace("・","",$str_s);
//$str_s = mb_ereg_replace("-","",$str_s);
//$str_s = mb_ereg_replace(" ","",$str_s);
//$str_s = mb_ereg_replace("ー",ー",$str_s);
$ary = mb_split("[、, (,]",$str_s);
if(count($ary) > 0){
$retval = $ary[0];
}else{
$retval = $str_s;
}
return $retval;
}
function searchStr($str,$start_str,$start_str_len,$end_str,$end_str_len){
$retval ="";
$pos_s = mb_strpos($str, $start_str);
$pos_e = mb_strpos($str, $end_str);
if(($pos_s === false) || ($pos_e === false)){
//みつからず
}else{
//echo mb_strlen($str)."->s:".$pos_s."->e:".$pos_e;
//$retval = mb_substr($str,$pos_s+$start_str_len,mb_strlen($str) - $start_str_len - $end_str_len-1);
$retval = mb_substr($str, $pos_s+$start_str_len, $pos_e - $pos_s - $start_str_len);
}
return $retval;
}
/**
* endsWith
* http://blog.anoncom.net/2009/02/20/124.html
*
* @param string $haystack
* @param string $needle
* @return boolean
*/
function endsWith($haystack, $needle){
$length = (strlen($haystack) - strlen($needle));
if( $length <0 data-blogger-escaped-false="" data-blogger-escaped-haystack="" data-blogger-escaped-length="" data-blogger-escaped-needle="" data-blogger-escaped-return="" data-blogger-escaped-strpos="">
これを実行すると・・・
php wikicsv.php jawiki-latest-abstract.xml
読み取り開始・・・
29.402565956116 seconds
総数:943216 有効数:408613 無効数:534603 43.321254092382%
DBに書き込み開始・・・'/tmp/TuxUHAuGL'
768.0825881958 seconds
読み取り開始・・・
29.402565956116 seconds
総数:943216 有効数:408613 無効数:534603 43.321254092382%
DBに書き込み開始・・・'/tmp/TuxUHAuGL'
768.0825881958 seconds
PCで実行しているので、やはり生成は29秒と早い。
でも、ラズベリーパイに転送するのは、768秒・・・なんとか改善できないかな。
で、中身はこんな感じ
んでもって、サーバー側のスクリプトは、
<>
<?php
mb_language('Japanese');
mb_internal_encoding('UTF-8');
mb_regex_encoding("UTF-8");
$s_talk = htmlspecialchars($_GET['talk'], ENT_QUOTES, "utf-8");
$result = "";
try {
$pdo = new PDO('mysql:dbname=test;host=192.168.4.135', 'username', 'password');
} catch (PDOException $e) {
talk("データベースに接続できませんでした。");
exit('データベースに接続できませんでした。' . $e->getMessage());
}
$stmt = $pdo->query('SET NAMES utf8');
if (!$stmt) {
$info = $pdo->errorInfo();
exit($info[2]);
}
$stmt = $pdo->query('set character_set_database=utf8');
if (!$stmt) {
$info = $pdo->errorInfo();
exit($info[2]);
}
if(strlen($s_talk) == 0){
talk("WEBサーバーを起動しました。");
}else{
$result = "あなたの言葉は、".$s_talk."です。";
if(preg_match("/^[ぁ-ゞー]+$/u",$s_talk)){
//ひらがなだった
$stmt = $pdo->prepare("select * from wiki where wiki.kana like :word and wiki.kana not like '%ん' order by rand() limit 1");
$stmt->bindValue(':word', mb_substr($s_talk,-1).'_%');
$flag = $stmt->execute();
if (!$flag) {
$info = $stmt->errorInfo();
exit($info[2]);
}
while ($data = $stmt->fetch(PDO::FETCH_ASSOC)) {
$result=$result."
私の言葉は".$data['name']."(".$data['kana'].")です。
".$data['gaiyo'];
talk("あなたの言葉は、".$s_talk."です。そして、私の言葉は、".$data['kana']."です。");
}
}else{
$result=$result."
申し訳ありませんが、すべて「ひらがなで」入力してください。";
talk("あなたの言葉は、".$s_talk."です。申し訳ありませんが、すべて「ひらがなで」入力してください。");
}
}
$pdo = null;
function talk($kotoba){
exec('echo "'.$kotoba.'" | /home/pi/aquestalkpi/AquesTalkPi -v -f1 -f - | aplay > /dev/null &');
}
echo <<< EOD
簡易しりとり
RasPiと「しりとり」で遊ぶ!
これは、Wikipediaのダウンロード可能なデータを利用した簡易的な「しりとり」です。
EOD;
?>
そして、ブラウザからアクセス!
ちょっと楽しいかも。



