Mecabなど形態素解析で使うIPA品詞体系(品詞ID|pos-id)

Mecab茶筅など形態素解析で使う辞書のIPA品詞体系をまとめてみました。

Mecabでは::getPosId()で品詞IDを取得できます。

[amazonjs asin=“4873114705” locale=“JP” title=“入門 自然言語処理”]

IPA品詞体系

品詞ID 分類 説明
0 その他,間投 「あ」「ア」のみ 「そんなぁ」
1 フィラー 「えーと」「なんか」など
2 感動詞 「うむ」「お疲れさま」「トホホ」
3 記号,アルファベット 「A-z」
4 記号,一般 「?」「!」「¥」
5 記号,括弧開 「(」「【」など
6 記号,括弧閉 「 )」「】」など
7 記号,句点 「。」「.」のみ
8 記号,空白 「 」のみ
9 記号,読点 「、」「,」のみ
10 形容詞,自立 「美しい」「楽しい」
11 形容詞,接尾 「ったらしい」「っぽい」
12 形容詞,非自立 「づらい」「がたい」「よい」 「見づらい」
13 助詞,格助詞,一般 「の」「から」「を」
14 助詞,格助詞,引用 「と」のみ
15 助詞,格助詞,連語 「について」「とかいう」
16 助詞,係助詞 「は」「こそ」「も」「や」
17 助詞,終助詞 「かしら」「ぞ」「っけ」「わい」
18 助詞,接続助詞 「て」「つつ」「および」「ので」
19 助詞,特殊 「かな」「けむ」「にゃ」
20 助詞,副詞化 「と」「に」のみ
21 助詞,副助詞 「くらい」「なんか」「ばっかり」
22 助詞,副助詞/並立助詞/終助詞 「か」のみ
23 助詞,並立助詞 「とか」「だの」「やら」
24 助詞,連体化 「の」のみ
25 助動詞 「ます」「らしい」「です」
26 接続詞 「だから」「しかし」
27 接頭詞,形容詞接続 「お」「まっ」 「お高い」「まっ赤」
28 接頭詞,数接続 「計」「毎分」 数値に接続するもの
29 接頭詞,動詞接続 「ぶっ」「引き」 動詞に接続するもの。「ぶったたく」
30 接頭詞,名詞接続 「最」「総」 名詞に接続するもの。「最高値」
31 動詞,自立 「投げる」
32 動詞,接尾 「しまう」「ちゃう」「願う」 「行ってしまう」
33 動詞,非自立 「しまう」「ちゃう」「願う」 「行ってしまう」「やっちゃったね」「ご遠慮願う」
34 副詞,一般 「あいかわらず」「多分」 必ず後ろで切れるもの,連体修飾が不可能なもの
35 副詞,助詞類接続 「こんなに」「そんなに」 「する」「だ」などが後続可能な副詞.
36 名詞,サ変接続 「インプット」「悪化」 後ろに「する」「できる」などがつくもの
37 名詞,ナイ形容詞語幹 「申し訳」「仕方」 助動詞「ない」の直前に現れる名詞
38 名詞,一般 「テーブル」 通名詞。
39 名詞,引用文字列 「いわく」のみ
40 名詞,形容動詞語幹 「健康」「安易」「駄目」 形容動詞語幹で「な」の前に現れるもの
41 名詞,固有名詞,一般 一般的な固有名詞
42 名詞,固有名詞,人名,一般 一般的な人名。
43 名詞,固有名詞,人名,姓 一般的な日本人の性。
44 名詞,固有名詞,人名,名 一般的な日本人の名。
45 名詞,固有名詞,組織 「株式会社◯◯」 組織を表す。
46 名詞,固有名詞,地域,一般 「東京」 国以外の地名。
47 名詞,固有名詞,地域,国 「日本」 国名。
48 名詞,数 「0」「一」 数字及び「何(回)」など。
49 名詞,接続詞的 「◯対◯」「◯兼◯」 単語と単語を接続するもの。
50 名詞,接尾,サ変接続 「(可視)化」 後ろに「する」がつく接尾語。
51 名詞,接尾,一般 「感」「観」「性」 複合名詞をつくるもの。
52 名詞,接尾,形容動詞語幹 「的」「げ」「がち」
53 名詞,接尾,助数詞 「個」「つ」「本」「冊」
参考:
ipadic version 2.7.0 ユーザーズマニュアル (*PDF)
形態素解析ツールの品詞体系

初心者がvimをカスタマイズしてプラグインを導入するまで

vimをアップデート

vimのバージョンが古くて一部のプラグインが使えなかったので、新しいバージョンのvimをインストールします。 ついでにneocompleteなどで使うので、Luaも有効化しておきます。

$ yum -y install mercurial
$ yum -y install ncurses-devel
$ cd /usr/local/src
$ hg clone https://vim.googlecode.com/hg/ vim
$ cd /usr/local/src/vim
$ ./configure --enable-multibyte --with-features=huge --disable-selinux --prefix=/usr/local --enable-luainterp=dynamic --enable-rubyinterp --enable-fail-if-missing --with-lua-prefix=/usr
$ make
$ make install

そのあとに、シンボリックリンクを貼るか.bashrcにaliasを設定します。

$ vi ~/.bashrc

以下のaliasを追記。vimまたはviで新しくインストールしたvimが起動します。

alias vi='/usr/local/bin/vim'
alias vim='/usr/local/bin/vim'
alias vimrc='vi /usr/local/share/vim/vimrc'

.bashrcに追記した内容を反映させます。

$ bash

ミニマムの設定をvimrcに追加

設定ファイルvimrcの場所を確認します。

$ vim --version

すると、vimのバージョンなどと一緒に設定ファイルの場所が以下のように表示されます。

システム vimrc: "/$VIM/vimrc"
ユーザ vimrc: "$HOME/.vimrc"

$VIMなどはvim上で:echo $VIMで確認できます。

とりあえず、下記を調べた設定ファイルvimrcに追加します。

set number
set title
set ambiwidth=double
set tabstop=4
set expandtab
set shiftwidth=4
set smartindent
set list
set listchars=tab:»-,trail:-,eol:↲,extends:»,precedes:«,nbsp:%
set nrformats-=octal
set hidden
set history=50
set virtualedit=block
set whichwrap=b,s,[,],<,>
set backspace=indent,eol,start
set wildmenu
syntax on

カラースキームを設定

次にカラースキームを設定します。今回は人気のmolokaiを設定します。 *colorsディレクトリの場所は環境に合わせて確認してください

$ cd /usr/local/share/vim/vim74/colors
$ git clone https://github.com/tomasr/molokai

colorschemeをvimrcに追加。

colorscheme molokai

NeoBundleを追加

次にvimプラグインを追加します。プラグインの管理にはNeoBundleを使います。

$ git clone https://github.com/Shougo/neobundle.vim ~/.vim/bundle/neobundle.vim
$ git clone https://github.com/Shougo/vimproc ~/.vim/bundle/vimproc
$ vi /etc/vimrc

vimrcに以下を追加

if has('vim_starting')
   set runtimepath+=~/.vim/bundle/neobundle.vim
   call neobundle#begin(expand('~/.vim/bundle/'))
       NeoBundleFetch 'Shougo/neobundle.vim'
       NeoBundle 'Shougo/vimproc'
       NeoBundle 'VimClojure'
       NeoBundle 'Shougo/vimshell'
       NeoBundle 'Shougo/unite.vim'
       NeoBundle 'Shougo/neocomplcache'
       NeoBundle 'Shougo/neosnippet'
       NeoBundle 'jpalardy/vim-slime'
       NeoBundle 'scrooloose/syntastic'
       NeoBundle 'scrooloose/nerdtree'
       call neobundle#end()
endif
NeoBundleCheck

filetype off
filetype plugin indent on
filetype indent on

vimrcを保存してからvimを再起動。NeoBundleCheckを設定しているので、起動時にインストールしていないプラグインをインストールか聞かれます。

NeoBundleCheckを設定しない場合は、vimコマンドラインで:NeoBundleInstallとすることで指定したプラグインをインストールできます。

NeoBundleコマンド

:NeoBundleInstall プラグインのインストー
:NeoBundleList プラグインのリスト
:NeoBundleClean プラグインを削除
:NeoBundleUpdate プラグインのアップデート

そのほか、キーバインドに関してなどはまたの機会に。

[amazonjs asin=“B00HWLJI3U” locale=“JP” title=“実践Vim 思考のスピードで編集しよう! (アスキー書籍)”]

リモートサーバーのファイルをSublime Textで開く方法

タイトルのままリモートサーバーのファイルをSublime Textで開く方法です。

sftpやsshfsを使ってリモートサーバーとローカルを同期させる方法もあるようですが、

・ファイル同期を待ちたくない ・ローカルにファイルがいっぱいになるのが嫌だ

ということでよりお手軽なrsubを選んでみました。

1.Sublime Text2の側の設定

以下の手順でrsubのパッケージを追加します。

  1. SublimeTextを開く
  2. Command Palettを開く(CMD + Shift + P)
  3. 「Package Control: Install Package」を選択
  4. 「rsub」を選択してインストー

2.リモートサーバー側の設定

リモートサーバーにログインしたら、rsubをインストールします。

$ sudo wget -O /usr/local/bin/rsub https://raw.github.com/aurora/rmate/master/rmate
$ sudo chmod +x /usr/local/bin/rsub

3.ローカルでsshのconfigを設定

ここで一旦、ローカルに戻りsshのconfigを設定します。

$ vi ~/.ssh/config

以下の2行をconfigに追加して保存。

Host example.com
  RemoteForward 52698 localhost:52698

これで上手くいくはず(?)だったのですが、リモートサーバーでrsubしてもエラーがでてしまいました。

$rsub sample.txt
  /usr/local/bin/rsub: connect: 接続を拒否されました
  /usr/local/bin/rsub: line 321: /dev/tcp/localhost/52698: 接続を拒否されました
  Unable to connect to TextMate on localhost:52698

なので、configを以下のように変更します。

Host example.com
  User example_user
  HostName 123.45.67.890
  Port 22
  RemoteForward 52698 localhost:52698

保存してローカルからリモートサーバーにssh接続をします。

$ ssh example.com

リモートサーバーからrsubでファイルを開いてみます。

$ rsub sample.txt

これで無事にSublime Textでファイルを開くことができました。 開いたファイルはSublime Text上で保存すればリモートサーバーでも反映されます。

[amazonjs asin=“4844335677” locale=“JP” title=“Web制作者のためのSublime Textの教科書 今すぐ最高のエディタを使いこなすプロのノウハウ”]

さくらのVPS(CentOS)にnginxリバースプロキシを入れて高速化する方法

さくらのVPSの初期設定から、nginxを入れてリバースプロキシの設定をするまでの手順を(自分用に)まとめました。

今回最も参考になったのは以下の本です。nginx以外の高速化の手法も豊富でおすすめです。

[amazonjs asin=“4844362526” locale=“JP” title=“WordPress 高速化&スマート運用必携ガイド”]

さくらのVPSの初期設定

さくらのVPSを契約したら、まずはコントロールパネルからサーバーを起動します。

起動したらrootユーザーでssh接続します。パスワードはメールで送付されているはずです。

$ ssh root@160.17.60.189

ここでたまにエラーになるのですが、そんな時はコントロールパネルからサーバーを再起動すれば接続できることが多いです。

次に、ユーザーを追加します。ここでは「username」というユーザーを新しく追加することとします。

$ passwd
$ useradd username

passwordコマンドでパスワードを設定します。

$ passwd username

次に追加したユーザーにsudo権限を与えます。

今回は「wheel」グループにsudo権限を持たせ、追加したユーザーを「wheel」に所属させます。

$ usermod -G wheel username
$ visudo

visudoコマンドで設定ファイルが開くので、#(コメントアウト)を消します。

# %wheel ALL=(ALL) ALL

ついでに最低限のファイアーウォールの設定をiptablesでします。

$ iptables -A INPUT -p tcp --tcp-flags ALL NONE -j DROP
$ iptables -A INPUT -p tcp ! --syn -m state --state NEW -j DROP
$ iptables -A INPUT -p tcp --tcp-flags ALL ALL -j DROP
$ iptables -A INPUT -i lo -j ACCEPT 
$ iptables -A INPUT -p icmp -j ACCEPT
$ iptables -A INPUT -p tcp -m tcp --dport 80 -j ACCEPT
$ iptables -A INPUT -p tcp -m tcp --dport 22 -j ACCEPT
$ iptables -I INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
$ iptables -P INPUT DROP 
$ iptables -P OUTPUT ACCEPT
$ service iptables save

この辺りの最初の設定は、さくらインターネットサーバの初期設定ガイドに載っています。

yumの準備

アップデートをして、remiやepelなどのレポジトリを追加します。

$ yum update

yum updateで「更新と設定されたパッケージがありません。」などと出てこけたら以下のコマンドを実行したらから再度アップデートしてみてください。

$ yum clean all
$ yum check
$ yum update

remiとepelを追加します。失敗したらURLを最新のものに差し替えてみてください。

$ rpm -Uvh http://rpms.famillecollet.com/enterprise/remi-release-6.rpm
$ rpm -ivh http://ftp-srv2.kddilabs.jp/Linux/distributions/fedora/epel/6/x86_64/epel-release-6-8.noarch.rpm

nginxのインストー

次にnginxをインストールします。

yumでインストールできるnginxのバージョンを確認。

$ yum info nginx

ちょっと古かったのでnginxのレポジトリを追加してから、インストールします。

$ rpm -ivh http://nginx.org/packages/centos/6/noarch/RPMS/nginx-release-centos-6-0.el6.ngx.noarch.rpm
$ yum install -y nginx

インストールできたらnginxを立ち上げてから、サーバー起動時に自動でnginxが立ち上がるように設定します。

$ service nginx start
$ sudo /sbin/chkconfig nginx on

phpのインストー

PHPをインストールしてphp.iniを編集します。

$ yum --enablerepo=remi -y install php php-cli php-devel php-mbstring php-gd php-pear php-xml
$ vi /etc/php.ini

php.iniは、とりあえず以下のように変更します。

expose_php = Off
date.timezone = "Asia/Tokyo"

nginxでPHPを動かす時に使うphp-fpmを入れて設定ファイルwww.confを編集します。

$ yum --enablerepo=remi -y install php-fpm
$ vi /etc/php-fpm.d/www.conf

細かいチューニングは後から行うとして、まずは以下のように設定します。

user = nginx
group = nginx
pm = static

php-fpmを立ち上げ、これもchkconfig onします。

$ service php-fpm start
$ sudo /sbin/chkconfig php-fpm on

mysqlのインストー

MySQLをインストールします。

$ yum --enablerepo=remi -y install mysql.x86_64 mysql-server.x86_64 php-mysql

ここでは、起動してからrootを「samplepassword」に設定します。

$ service mysqld start
$ sudo /sbin/chkconfig mysqld on
$ mysqladmin -u root password 'samplepassword'
$ mysql -u root -p

wordpressというデータベースを作成します。

create database wordpress default character set utf8 collate utf8_general_ci;

次にwordpressというユーザーを作成し、パスワードを「samplepassword」とします。

grant all privileges on wordpress.* to wordpress@localhost identified by 'samplepassword';

リバースプロキシの設定(nginx.confの編集)

リバースプロキシを設定するために、nginx.confとdefault.confを編集します。

設定ファイルはGistを参照してください。

*さくらのVPS:CentOS64、nginx 1.6.3、PHP 5.4.39で動作確認。 *その他の環境での動作は保証しかねます。

/etc/nginx/nginx.conf /etc/nginx/conf.d/default.conf

設定ファイルを編集し、nginxを再起動します。

$ service nginx restart

バックアップデータの移行

WordPressを使用していてサーバー移転する時のメモです。

htmlディレクトリ以下をすべて圧縮し、データベースはdumpしてバックアップを保存。

$ tar zcvf html.tar.gz html
$ mysqldump -u root -p wordpress > dump.sql

転送先のサーバーにsftpコマンドで接続して、dump.sqlとhtml.tar.gzを転送します。

$sftp root@123.45.67.89
  put dump.sql
  put html.tar.gz

転移先のサーバーにssh接続して、html.tar.gzを解凍&dumpファイルをインポートします。

$ tar zxvf html.tar.gz
$ mysql -u root -p wordpress < dump.sql

これで、CentOS+nginx(リバースプロキシ)+ php-fpmの環境構築は完了です(多分)。

あとはサーバーの環境に合わせてチューニングすればよいかと。

[amazonjs asin=“4048702270” locale=“JP” title=“ハイパフォーマンスHTTPサーバ Nginx入門”]

HTMLに埋め込まれた相対パスを絶対パスに変換する

スクレイピングをした時に、imgタグなどで埋め込まれている画像が相対パスで指定されている場合に絶対パスに変換する関数です。

もっとスマートなやり方がありそうですが。。。ほかの人が改善してくれることを期待して公開してみます。

相対パスのパターン

相対パスのパターンは以下の7通りを想定しています。抜けているパターンがあれば教えてください。

絶対パス

http://example.jp/sample.jpg

・http(s)の省略

//example.jp/sample.jpg

ディレクトリ以下を指定

/images/sample.jpg

・同一ディレクトリ内

./sample.jpg

・同一ディレクトリ内

sample.jpg

・親ディレクトリ内

../../sample.jpg

・並列するディレクトリ内

../../images/sample.jpg

相対パスから絶対パスに変換するPHP関数

ベースURLと変換する相対パスを引数に指定します。

ベースURLを元に、相対パス絶対パスに変換します。

/**
 * スクレイピングなどで画像URLを取得する時に使うために 
 * ベースURLを元に相対パスから絶対パスに変換する関数
 * 
 * @param string $target_path 変換する相対パス
 * @param string $base ベースとなるパス
 * @return $uri string 絶対パスに変換済みのパス
 */
function convert_to_uri($target_path, $base) {
  $component = parse_url($base);

  $directory = preg_replace('!/[^/]*$!', '/', $component["path"]);

  switch (true) {

    // [0] 絶対パスのケース(簡易版)
    case preg_match("/^http/", $target_path):
      $uri =  $target_path;
      break;

    // [1]「//exmaple.jp/aa.jpg」のようなケース
    case preg_match("/^\/\/.+/", $target_path):
      $uri =  $component["scheme"].":".$target_path;
      break;

    // [2]「/aaa/aa.jpg」のようなケース
    case preg_match("/^\/[^\/].+/", $target_path):
      $uri =  $component["scheme"]."://".$component["host"].$target_path;
      break;

    // [3]「./aa.jpg」のようなケース
    case preg_match("/^\.\/(.+)/", $target_path,$maches):
      $uri =  $component["scheme"]."://".$component["host"].$directory.$maches[1];
      break;

    // [4]「aa.jpg」のようなケース([3]と同じ)
    case preg_match("/^([^\.\/]+)(.*)/", $target_path,$maches):
      $uri =  $component["scheme"]."://".$component["host"].$directory.$maches[1].$maches[2];
      break;

    // [5]「../aa.jpg」のようなケース
    case preg_match("/^\.\.\/.+/", $target_path):
      //「../」をカウント
      preg_match_all("!\.\./!", $target_path, $matches);
      $nest =  count($matches[0]);

      //ベースURLのディレクトリを分解してカウント
      $dir = preg_replace('!/[^/]*$!', '/', $component["path"])."\n";
      $dir_array = explode("/",$dir);
      array_shift($dir_array);
      array_pop($dir_array);
      $dir_count = count($dir_array);

      $count = $dir_count - $nest;

      $pathto="";
      $i = 0;
      while ( $i < $count) {
        $pathto .= "/".$dir_array[$i];
        $i++;
      }
      $file = str_replace("../","",$target_path);
      $uri =  $component["scheme"]."://".$component["host"].$pathto."/".$file;

      break;
  }

  return $uri;
}

関数の実行結果

上記の関数を相対パス7パターンで実行してみます。

$base = "http://example.jp/posts/2015/06/convert_to_uri.html";
$pathes = array(
  "http://example.jp/sample.jpg",
  "//example.jp/sample.jpg",
  "/images/sample.jpg",
  "./sample.jpg",
  "sample.jpg",
  "../../sample.jpg",
  "../../images/sample.jpg"
);

foreach ($pathes as $key => $path) {
  echo convert_to_uri($path,$base)."\n";
}

実行結果は以下の通りです。なんとか上手くいった気がします。

http://example.jp/sample.jpg
http://example.jp/sample.jpg
http://example.jp/images/sample.jpg
http://example.jp/posts/2015/06/sample.jpg
http://example.jp/posts/2015/06/sample.jpg
http://example.jp/posts/sample.jpg
http://example.jp/posts/images/sample.jpg

フィードバックなどあればコメントなどにお願いします!

[amazonjs asin=“B00BCQ5Q96” locale=“JP” title=“Programming PHP”]

[amazonjs asin=“B00P0UDWQY” locale=“JP” title=“パーフェクトPHP”]

リロードするとFatal error: Call to undefined **となる問題

【問題】リロード時にUndefined Errorとなる

APCのオペコードキャッシュを有効化した時、サーバーを立ち上げると最初は表示されるものの、リロードすると「Fatal error: Call to undefined **」となってしまう。

apc.iniの以下の部分を「apc.enable_opcode_cache=1」とすると上記の現象になる。

; This can be set to enable the APC opcode cache
; WARNING: don't set this option if another opcode cache is enabled
apc.enable_opcode_cache=0

環境は、nginx + PHP 5.4.28(php-fpm) + APC(3.1.15dev beta)です。

【原因】APCのエラー

エラー回避の方法を調べていくと、どうやらAPCの特定バージョンで起きる不具合だったよう。詳細な再現条件は調べてないので不明ですが、APC(3.1.15dev beta)では上記不具合が起きていました。

サーバー立ち上げ時にオペコードキャッシュがAPCによって作成され、リロード時は生成されたキーを元にオペコードキャッシュを呼ぼうとするが、そこでこけてしまいFatal Errorとなるようです。

▼参照 PHP :: Bug #61219 :: method not found on 2nd request Upgrade to PHP 5.4 from PHP 5.3 - undefined method SWIFT_License::DecodeKey()

【解決策】Zend OPCacheを導入する

パッチを当てれば直るらしいのですが、オペコードのキャッシュはZend OPCacheにすることにしました。ちなみに、Zend OPCacheはPHP5.5から導入されたものですが、PHP5.4でも問題なく使えます。

理由は、ざっくり以下の2点です。

APCはすでに開発が止まっている ・Zend OPCacheのほうがパフォーマンスが良い(らしい)

Zend OPCache+APCの構成で解決

ただし、Zend OPCacheはユーザーデータのキャッシュには対応していないため、Zend OPCacheだけではWordPressのオブジェクトキャッシュが使えません。

そのため、APCはオペコードキャッシュには使わずにZend OPCache+APCという構成にすることにしました。

もしパッチを当てて直したいという人は、こちらのパッチを参照してみてください。

[amazonjs asin=“4844362526” locale=“JP” title=“WordPress 高速化&スマート運用必携ガイド”]

iframeのURLを親ウィンドウのフォームから変更するJavascript

jQueryなしのプレーンなJavascriptを使って、iframeのURLを変更するTips。

<form name="targetForm">
  <input type="text" name="query" />
  <input type="button" value="送信" onclick="SendSubmit()"/>
</form>

<iframe name="searchFrame" style="width:100%;height:650px" sandbox="allow-forms"></iframe>
<script type="text/javascript">

function SendSubmit(){
  var query = document.targetForm.elements['query'];
  var targetURL = "http://example.com/?s=";
  document.searchFrame.location.href = targetURL + query.value;
}
</script>

ちなみにGoogleFlickrなどはクリックジャッキング対策のためiframe内からの呼び出しを禁止しているそうです。

このクリックジャッキングとは、簡単に言うとiframe内に表示されたサイトにJSやCSSを使った悪意のある「なりすましボタン」を設置することを指すそうで、HTTPレスポンスヘッダにX-Frame-Optionsを追加することで対策することができます。 ▼参考 クリックジャッキングって?

[amazonjs asin=“4873115736” locale=“JP” title=“JavaScript 第6版”]