品詞分解してWordPressで検索するまで(その2、投稿編)
その1で作成したテキストを使ってWordPressへ一括で投稿するまでをやります。
XML-RPCの準備
WordPressへの投稿はXML-RPCを使う。 JSON REST APIはよくわからなかったので次の課題(汗。
XML-RPCを使うとWordPressの外側から投稿やカテゴリーの操作など一通りの作業ができる。 すべてのAPIは下記参照。
XML-RPC WordPress API « WordPress Codex
XML-RPCのライブラリはいくつかあるらしいけどincutioが使いやすそうだったのでこれを使う。
The Incutio XML-RPC Library for PHP
上記からIXR_Library.phpをダウンロードしてサイトの任意の場所へコピーする。
IXR_Library.phpの使い方
wp.newPostで投稿する場合。
<?php /* inctioのライブラリ呼び出し */ include_once(‘IXR_Library.php'); /* 対象とするWordPressのサイト */ $client = new IXR_Client(“http://sample.co.jp/xmlrpc.php”); $status = $client->query( "wp.newPost", //使うAPIを指定(wp.newPostは、新規投稿) 1, // blog ID: 通常は1、マルチサイト時変更 $wp_username, // ユーザー名 $wp_password, // パスワード array( 'post_author' => 2, // 投稿者ID 未設定の場合投稿者名なしになる。 'post_status' => 'publish', // 投稿状態 'post_title' => 'タイトル', // タイトル 'post_content' => '投稿本文', // 本文 'terms' => array('category' => array(1)) // カテゴリ追加 ) ); if(!$status){ die('Something went wrong - '.$client->getErrorCode().' : '.$client->getErrorMessage()); } else { $post_id = $client->getResponse(); //返り値は投稿ID }
post.phpを作成する
投稿用のphp(post.php)を作成する。このphpをC#から呼び出して使う。
作成したpost.phpはWordPressのサイトの任意のフォルダにコピーする。
今回はWordPressのサイトの下のxmlrpcフォルダを作成してそこにコピーする。
- フォルダ構成 www.sample.co.jp(WordPressのサイト)
xmlrpc.php
xmlrpcフォルダ
IXR_Library.php
post.php
- 全部のソース(post.php)
<?php /** 品詞分解されたデータを投稿する */ include_once('IXR_Library.php'); //inctioのライブラリ呼び出し //WordPressのサイトのルートにはxmlrpc.phpがある(初めから?) $client = new IXR_Client("http://" . $_SERVER['SERVER_NAME'] . "/xmlrpc.php"); $user = $_POST['user']; //ユーザー名 $pass = $_POST['pass']; //パスワード $data = array( 'post_author' => 1, // 投稿者ID 未設定の場合投稿者名なしになる。 'post_status' => 'publish', // 投稿状態 'post_title' => $_POST['title'], 'post_content' => $_POST['content'], ); $honbunlst = mb_split( ",", $_POST['honbun'] ); $katsuyolst = mb_split( ",", $_POST['katsuyo'] ); $hinshilst = mb_split( ",", $_POST['hinshi'] ); //本文、品詞、活用を一つずつカスタムフィールドとして登録する for( $i=0; $i<count($honbunlst); $i++ ){ $data['custom_fields'][] = array( 'key' => 'honbun', 'value' => $honbunlst[$i] ); $data['custom_fields'][] = array( 'key' => 'katsuyo', 'value' => $katsuyolst[$i] ); $data['custom_fields'][] = array( 'key' => 'hinshi', 'value' => $hinshilst[$i] ); } $status = $client->query( "wp.newPost", //wp.newPostは、新規投稿 1, // blog ID: 通常は1、マルチサイト時変更 $user, // ユーザー名 $pass, // パスワード $data //追加するデータ ); if(!$status){ $res = array ( 'status' => 'error', 'msg' => $client->getErrorMessage(), 'code' => $client->getErrorCode(), ); echo json_encode( $res ); //JSONで返す return; } $post_id = $client->getResponse(); //返り値は投稿ID $res = array( 'status' => 'ok', 'postid' => $post_id, ); echo json_encode( $res ); //JSONで返す
mecabのテキストを読み込んで「。」ごとに本文と品詞・活用のデータを抽出しpost.phpを呼び出すC#を作成する。
C#の全部のソースは下記参照してください。
masatoru/xmlrpcsample · GitHub
CreateTextCore.cs(抜粋) PostStatus postHonbun (string title, List<string> honbunlst, List<string> hinshilst, List<string> katsuyolst) { try { string url = string.Format ("{0}/xmlrpc/post.php", url_); //上記で作成したpost.phpへPOSTする //Console.WriteLine("POST={0}",url); var client = new System.Net.Http.HttpClient (); Dictionary<string, string> dict = new Dictionary<string, string>{ { "user", user_ },//ユーザー名 { "pass", pass_ },//パスワード { "title", title },//タイトル { "content", string.Join("",honbunlst.ToArray()) },//本文 //mecabでばらした本文、品詞、活用形はカンマ区切りでPHPに渡す //PHP(post.php)側で配列で受け取ってカスタムフィールドとして登録する { "honbun", string.Join(",",honbunlst.ToArray()) }, { "hinshi", string.Join(",",hinshilst.ToArray()) }, { "katsuyo", string.Join(",",katsuyolst.ToArray()) }, }; //Dictionaryの値の文字列が長いとエラーになるので注意 var content = new FormUrlEncodedContent (dict); var response = client.PostAsync (url, content).Result; string json = response.Content.ReadAsStringAsync ().Result; return Newtonsoft.Json.JsonConvert.DeserializeObject<PostStatus> (json); } catch (Exception ex) { throw new Exception ("POSTできない MSG=" + ex.Message); } }
品詞分解してWordPressで検索するまで(その1、mecab編)
古典のテキストをmecabで品詞分解するところまでやります。
mecabのインストール
$ brew install mecab $ brew install mecab-ipadic
動作確認。
$ mecab おでんにはんぺんをいれるかなやみます <==入力してEnter(またはコピペ) おでん 名詞,一般,*,*,*,*,おでん,オデン,オデン に 助詞,格助詞,一般,*,*,*,に,ニ,ニ はんぺん 名詞,一般,*,*,*,*,はんぺん,ハンペン,ハンペン を 助詞,格助詞,一般,*,*,*,を,ヲ,ヲ いれる 動詞,自立,*,*,一段,基本形,いれる,イレル,イレル か 助詞,副助詞/並立助詞/終助詞,*,*,*,*,か,カ,カ なやみ 動詞,自立,*,*,五段・マ行,連用形,なやむ,ナヤミ,ナヤミ ます 助動詞,*,*,*,特殊・マス,基本形,ます,マス,マス EOS
設定ファイルの場所。
vim /usr/local/Cellar/mecab/0.996/etc/mecabrc
出力形式を変更できる。
$ mecab -O wakati おでんにはんぺんをいれるかなやみます おでん に はんぺん を いれる か なやみ ます
- よみ
$ mecab -O yomi おでんにはんぺんを入れるか悩みます オデンニハンペンヲイレルカナヤミマス
古典の辞書を取得する
下記から中古和文用の辞書をダウンロード。
UniDic/中古和文UniDic - 言語データベースとソフトウェア
これを解凍して/usr/local/unidic-mecab/にコピー。
適当にテキストを持ってくる
Shift-JIS形式なのでこれをUTF-8形式で保存。
mecabで変換する
先ほどの中古和文の辞書に切り替えて、ダウンロードしたテキスト(tosa_nikki.txt)を変換する。 -dオプションを使わないで上記の設定ファイルを切り替えてももちろん可。
$ mecab -d /usr/local/unidic-mecab/ ./tosa_nikki.txt -o ./tosa_hinshi.txt
変換結果(tosa_hinshi.txt)。
男 名詞,普通名詞,一般,*,*,*,オトコ,男,男,オトコ,オトコ,和,男,オトコ,オトコ,オトコ,*,*,*,*,*,*,3,C2,* も 助詞,係助詞,*,*,*,*,モ,も,も,モ,モ,和,も,モ,モ,モ,*,*,*,*,*,*,*,"動詞%F2@-1,形容詞%F4@-2,名詞%F1",* す 動詞,非自立可能,*,*,文語サ行変格,終止形-一般,スル,為る,す,ス,ス,和,す,ス,ス,ス,*,*,*,*,*,*,1,C4,* なる 助動詞,*,*,*,文語助動詞-ナリ-伝聞,連体形-一般,ナリ,なり-伝聞,なる,ナル,ナル,和,なり,ナリ,ナリ,ナリ,*,*,*,*,*,*,*,"名詞%F2@1,形容詞%F2@-1動詞%F2@0",* 日記 名詞,普通名詞,一般,*,*,*,ニッキ,日記,日記,ニッキ,ニッキ,漢,日記,ニッキ,ニッキ,ニッキ,*,*,*,*,*,*,0,C2,* ...
次はこのテキストをC#で読み込んでWordPressに投げるとこまでをやります。
参考記事
バイナリファイルを文字列でサーバーへ転送する
バイナリファイルを添付でなく文字列でサーバーへ転送する方法を調べたのでメモ。
バイナリファイルを文字列に変換するのはunpackを使用する。
$str = unpack("H*", $binary);
試しにZIPファイルを読み込んで文字列に変換してみる。
$binary = file_get_contents('sample.zip'); $str = unpack("H*", $binary); echo $str;
こんな感じ。
504b0304140008000800a6b86a420000000000000000000000000800 10006c6973742e786d6c55580c006fe6a95418933c ...略
これをバイナリに戻すのは、
$binary_string = pack("H*" , $str[1]); //配列になっているので注意
これをファイルに保存すれば復元される。
if ( !$handle = fopen('new.zip', 'w') ){ echo "Cannot create file"; //権限注意(777とか) exit; } if ( fwrite($handle, $binary_string ) === FALSE ){ echo "Cannot write file"; exit; } fclose( $handle );
ここまでできればPOSTでバイナリの文字列を渡せば転送できるはず。
次はこれを使ってC#からサーバーへバイナルファイルを転送してみる。
参考: バイナリ データの処理
Excel/C#でdynamic型からWorksheet型へキャストができない
はまったのでメモ。
ExcelをC#で扱ってて.Net Framework4.0に上げたら、
Workbook book; ... ((Worksheet)book.Sheets[1]).SaveAs(path);
はコンパイル通らないけど、
book.(Sheets[1] as Worksheet).SaveAs(path);
は通る。
error CS1969: 動的な式のコンパイルに必要な 1 つ以上の型が見つかりません。参照が指定されていることを確認してください。
そもそもキャストしないでも動くはずなのだけど、SheetとWorksheetと_Worksheetの型があるからこれが原因でキャストが必要なのか?
dynamicの仕組みがよくわからないのでまた後日調べる。
参考:
読ませてもらったけど難しい。
Excel遅延バインディング : ヒロの趣味ブログ
HTTPWebRequest.Createがネットワーク上で動かない(ことがあるらしい)
HTTPWebRequest.Createが動作せずどっぷりはまってしまったのでメモ。
System.Net.HttpWebRequest req = (System.Net.HttpWebRequest) System.Net.WebRequest.Create("http://www.yahoo.co.jp");
これを実行すると例外が発生。
以下が出力されたエラー。
Message='system.net/defaultProxy' 構成セクションで指定された Web プロキシの作成中にエラーが発生しました。 data=System.Collections.ListDictionaryInternal Source=System StackTrace= 場所 System.Net.Configuration.DefaultProxySectionInternal.GetSection() 場所 System.Net.WebRequest.get_InternalDefaultWebProxy() 場所 System.Net.HttpWebRequest..ctor(Uri uri, ServicePoint servicePoint) 場所 System.Net.HttpRequestCreator.Create(Uri Uri) 場所 System.Net.WebRequest.Create(Uri requestUri, Boolean useUriBase) 場所 System.Net.WebRequest.Create(Uri requestUri) 場所 System.Net.SafeCloseSocketAndEvent.CreateWSASocketWithEvent(AddressFamily addressFamily, SocketType socketType, ProtocolType protocolType, Boolean autoReset, Boolean signaled) 場所 System.Net.NetworkAddressChangePolled..ctor() 場所 System.Net.AutoWebProxyScriptEngine.AutoDetector.Initialize() 場所 System.Net.AutoWebProxyScriptEngine.AutoDetector.get_CurrentAutoDetector() 場所 System.Net.AutoWebProxyScriptEngine..ctor(WebProxy proxy, Boolean useRegistry) 場所 System.Net.WebProxy.UnsafeUpdateFromRegistry() 場所 System.Net.WebProxy..ctor(Boolean enableAutoproxy) 場所 System.Net.Configuration.DefaultProxySectionInternal..ctor(DefaultProxySection section) 場所 System.Net.Configuration.DefaultProxySectionInternal.GetSection() msg=無効な引数が提供されました。<br />
プロキシは設定してないし、無効な引数ってのはArgumentExceptionかと調べたけどそれも違う。
そしたらなんてことはないプログラムを動作させているマイドキュメントのフォルダがネットワーク上にあり、これをローカルに移動したらまさかまさか動いた。
シンクライアントなので権限が足りないのかそこらへんが理由っぽい(そこまでつきとめられず)。
参考にしたサイト:
WebRequest.Create defaultproxy exception - Google 検索
マイクロソフトの仕様なのかバグなのか。
追伸:Xenappとかシンクライアントってほんと嫌い。