質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.50%

  • PHP

    20369questions

    PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

  • Eclipse

    1661questions

    Eclipseは、IBM社で開発された統合開発環境のひとつです。2001年11月にオープンソース化されました。 たくさんのプラグインがあり自由に機能を追加をすることができるため、開発ツールにおける共通プラットフォームとして位置づけられています。 Eclipse自体は、Javaで実装されています。

  • Mecab

    170questions

    Mecabは、オープンソースの形態素解析エンジンです。 言語、辞書、コーパスに依存しない汎用的な設計を基本方針としています。 Mecabの由来は、開発者の好物である和布蕪(めかぶ)から名づけられました。

phpでmecabを使い、特定の品詞の単語を抽出したい

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 313

agep31

score 20

 前提・実現したいこと

windows環境でphpを使い特定のurlから<title>タグを取得し、その<title>タグの中のテキストに対して形態素解析を行っています。
形態素解析にはmecabを使っているのですが、特定の品詞のみを抽出する方法がわかりません。
preg_match関数を使い正規表現で「地域」と判断された単語を抽出したいです。

<var_dumpでの出力結果>
array(31) {
[0]=>
string(41) "#★<    名詞,サ変接続,*,*,*,*,*
"
[1]=>
string(73) "成田    名詞,固有名詞,地域,一般,*,*,成田,ナリタ,ナリタ
"
[2]=>
string(63) "午前    名詞,副詞可能,*,*,*,*,午前,ゴゼン,ゴゼン
"
[3]=>
string(50) "発    名詞,接尾,一般,*,*,*,発,ハツ,ハツ
"
[4]=>
string(33) "/    名詞,サ変接続,*,*,*,*,*
"
[5]=>
string(79) "香港    名詞,固有名詞,地域,一般,*,*,香港,ホンコン,ホンコン
"
[6]=>
string(57) "午後    名詞,副詞可能,*,*,*,*,午後,ゴゴ,ゴゴ
"
[7]=>
string(50) "発    名詞,接尾,一般,*,*,*,発,ハツ,ハツ
"
[8]=>
string(42) ">    記号,括弧閉,*,*,*,*,>,>,>
"
[9]=>
string(59) "デラックスクラスホテル    名詞,一般,*,*,*,*,*
"
[10]=>
string(47) "に    助詞,格助詞,一般,*,*,*,に,ニ,ニ
"
[11]=>
string(42) "3    名詞,数,*,*,*,*,3,サン,サン
"
[12]=>
string(53) "連    名詞,接尾,助数詞,*,*,*,連,レン,レン
"
[13]=>
string(51) "泊    名詞,サ変接続,*,*,*,*,泊,ハク,ハク
"
[14]=>
string(35) "♪    名詞,サ変接続,*,*,*,*,*
"
[15]=>
string(79) "香港    名詞,固有名詞,地域,一般,*,*,香港,ホンコン,ホンコン
"
[16]=>
string(79) "マカオ    名詞,固有名詞,地域,一般,*,*,マカオ,マカオ,マカオ
"
[17]=>
string(63) "黄金    名詞,一般,*,*,*,*,黄金,オウゴン,オーゴン
"
[18]=>
string(63) "海岸    名詞,一般,*,*,*,*,海岸,カイガン,カイガン
"
[19]=>
string(69) "物語    名詞,一般,*,*,*,*,物語,モノガタリ,モノガタリ
"
[20]=>
string(28) "II    名詞,一般,*,*,*,*,*
"
[21]=>
string(24) "4    名詞,数,*,*,*,*,*
"
[22]=>
string(71) "日間    名詞,接尾,助数詞,*,*,*,日間,ニチカン,ニチカン
"
[23]=>
string(33) "(    名詞,サ変接続,*,*,*,*,*
"
[24]=>
string(28) "NT    名詞,一般,*,*,*,*,*
"
[25]=>
string(27) "2531    名詞,数,*,*,*,*,*
"
[26]=>
string(27) "A    名詞,一般,*,*,*,*,*
"
[27]=>
string(36) ")|    名詞,サ変接続,*,*,*,*,*
"
[28]=>
string(134) "阪急交通社    名詞,固有名詞,組織,*,*,*,阪急交通社,ハンキュウコウツウシャ,ハンキューコーツーシャ
"
[29]=>
string(5) "EOS
"
[30]=>
bool(false)
}

 該当のソースコード

<?php
$html = file_get_contents('http://www.hankyu-travel.com/tour/detail_i.php?p_course_id=NT2531A&p_hei=10');
// htmlをXMLに変換
$dom = new DOMDocument;
@$dom->loadHTML(
    mb_convert_encoding($html, 'HTML-ENTITIES', 'ASCII,JIS,UTF-8,eucJP-win,SJIS-win'),
    LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD
    );
/*------------タイトルの取得------------------*/
$xpath = new DOMXPath($dom);
$title = $xpath->query('//head/title[1]')->item(0)->nodeValue;
echo "タイトル:", $title, "<br>";

/*------------行先の取得mecab------------------*/
$path = '"C:\Program Files\MeCab\bin\mecab.exe"';
$input = $title;

$descriptorspec = array(
    0 => array("pipe","r"),
    1 => array("pipe","w")
);

$process = proc_open($path, $descriptorspec, $pipes);
if(is_resource($process)) {
    fwrite($pipes[0], $input);
    fclose($pipes[0]);
    while(!feof($pipes[1])){
        $output[] = fgets($pipes[1]);
    }
    fclose($pipes[1]);
    proc_close($process);
}

echo "<pre>";
print_r($output);//形態素解析の結果の出力
echo "</pre>";

?>

 補足情報(FW/ツールのバージョンなど)

php 5.6.34

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+1

単純に配列から特定のキーワードでフィルタしたいということであればこう?

<?PHP
$keyword="地域";
$a=[
  "#★<    名詞,サ変接続,*,*,*,*,*",
  "成田    名詞,固有名詞,地域,一般,*,*,成田,ナリタ,ナリタ",
  "午前    名詞,副詞可能,*,*,*,*,午前,ゴゼン,ゴゼン",
  "発    名詞,接尾,一般,*,*,*,発,ハツ,ハツ",
  "    名詞,サ変接続,*,*,*,*,*",
  "香港    名詞,固有名詞,地域,一般,*,*,香港,ホンコン,ホンコン",
  "午後    名詞,副詞可能,*,*,*,*,午後,ゴゴ,ゴゴ",
  "発    名詞,接尾,一般,*,*,*,発,ハツ,ハツ",
  ">    記号,括弧閉,*,*,*,*,>,>,>",
  "デラックスクラスホテル    名詞,一般,*,*,*,*,*",
  "に    助詞,格助詞,一般,*,*,*,に,ニ,ニ",
  "3    名詞,数,*,*,*,*,3,サン,サン",
  "連    名詞,接尾,助数詞,*,*,*,連,レン,レン",
  "泊    名詞,サ変接続,*,*,*,*,泊,ハク,ハク",
  "♪    名詞,サ変接続,*,*,*,*,*",
  "香港    名詞,固有名詞,地域,一般,*,*,香港,ホンコン,ホンコン",
  "マカオ    名詞,固有名詞,地域,一般,*,*,マカオ,マカオ,マカオ",
  "黄金    名詞,一般,*,*,*,*,黄金,オウゴン,オーゴン",
  "海岸    名詞,一般,*,*,*,*,海岸,カイガン,カイガン",
  "物語    名詞,一般,*,*,*,*,物語,モノガタリ,モノガタリ",
  "II    名詞,一般,*,*,*,*,*",
  "4    名詞,数,*,*,*,*,*",
  "日間    名詞,接尾,助数詞,*,*,*,日間,ニチカン,ニチカン",
  "(    名詞,サ変接続,*,*,*,*,*",
  "NT    名詞,一般,*,*,*,*,*",
  "2531    名詞,数,*,*,*,*,*",
  "A    名詞,一般,*,*,*,*,*",
  ")|    名詞,サ変接続,*,*,*,*,*",
  "阪急交通社    名詞,固有名詞,組織,*,*,*,阪急交通社,ハンキュウコウツウシャ,ハンキューコーツーシャ",
  "EOS",
  ];
$a=array_filter($a,function($x) use($keyword){
  return preg_match("/".preg_quote($keyword,"/")."/",$x);
});
print_r($a);

 修正

  • とりだしたあと、先頭の文字だけ抜き出す
  • キーワードは工夫が必要
  • $outputという変数を受けて処理する

もろもろ調整しました

$keyword="名詞,固有名詞,地域";
$a=array_map(function($x){
  return preg_match("/^(.+?)(?=\s)/",$x,$match)?$match[1]:"";
},array_filter($output,function($x) use($keyword){
  return preg_match("/".preg_quote($keyword,"/")."/",$x);
}));
print_r($a);

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/06/13 14:31

    ご回答ありがとうございます。ご提示されたプログラムを動かしてみたのですが、「地域」と判断された要素は取り出せたのですが、「成田」「香港」「マカオ」などの単語を取り出したいです。

    キャンセル

  • 2018/06/13 18:19

    失礼しました。地名を抜き出すんですね。
    追記しておきましたので確認ください

    キャンセル

  • 2018/06/13 18:38

    $keyword="地域";とするとそのままの「地域」(名詞)や「地域経済」のような単語も(辞書に登録されていれば)マッチしてしまうので、少し都合が悪いようです。
    正攻法で処理するなら、まずスペースで切り、後ろ半分をcsvとして処理していくことになりますが、面倒ですから
    $keyword="名詞,固有名詞,地域";
    で良いんじゃないでしょうか。

    参考
    https://hayashibe.jp/tr/mecab/dictionary/ipadic
    http://www.unixuser.org/~euske/doc/postag/

    キャンセル

  • 2018/06/13 18:38

    ご回答ありがとうございます。とても理想の形に近づいたのですが、最初の$a = [・・・];のところを、形態素解析した結果の出力である$outputにしたいのですが、どのようのすればよいのでしょうか?

    キャンセル

  • 2018/06/13 18:41

    hayataka様
    ご指摘ありがとうございます。修正しました。

    キャンセル

  • 2018/06/13 18:46

    ご指摘いただいた箇所を考慮して修正してみました。
    うまくいかないようなら再度ご指摘ください

    キャンセル

  • 2018/06/13 18:49

    ご指摘ありがとうございます。コードを修正してみたのですが、うまく取り出せません。

    キャンセル

  • 2018/06/13 18:57

    ちょっと状況がわからないのですが
    print_r($output)すると例示のようなarrayが表示されるのですよね?
    であれば、array_mapとarray_filterで普通に処理できると思いますが
    たとえば文字エンコードがちがうとかそういうレベルの間違いはありませんか?

    キャンセル

  • 2018/06/13 19:02

    $outputの中身は例示の通りです。回答にあるプログラムの通り、$a[]の中に直接形態素解析の結果を書くときちんと取り出せるのですが、$outputを使うと取り出せなくなります。

    キャンセル

  • 2018/06/13 19:04

    Array ( [1] => 成田 名詞,固有名詞,地域,一般,*,*,成田,ナリタ,ナリタ
       [5] => 香港 名詞,固有名詞,地域,一般,*,*,香港,ホンコン,ホンコン    [15] => 香港 名詞,固有名詞,地域,一般,*,*,香港,ホンコン,ホンコン [16] => マカオ 名詞,固有名詞,地域,一般,*,*,マカオ,マカオ,マカオ )

    ここまでは取り出せています。

    キャンセル

  • 2018/06/13 19:09

    フィルタはされているけど、地域名だけが抜き出せないのですね?
    地域名の後ろの空白文字はスペースかタブだと睨んでいるのですがなにか
    特殊文字が出力されているのかもしれませんね
    /^(.+)(?=\s)/
    は先頭から後ろに空白文字(半角スペースやタブ、改行マークなど)がくるまでという意味なので
    もし特殊文字が出力されているならそれに合わせないといけないと思います

    キャンセル

  • 2018/06/13 19:12

    地域名の後ろに来るのは半角スペースです。

    キャンセル

  • 2018/06/13 19:17

    たとえば「\s」を「 」(半角スペース)に変えて試してみてください

    キャンセル

  • 2018/06/13 19:23

    回答にあるプログラムだと以下のように取り出されるので、正規表現については問題のではないかと思います。

    Array ( [1] => 成田 [5] => 香港 [15] => 香港 [16] => マカオ )

    キャンセル

  • 2018/06/13 19:26

    ただ、入力の部分を直接書き込むのではなく、$outputを使って書きたいです。

    キャンセル

  • 2018/06/13 19:27

    環境によって円マークが悪さをする可能性も否定出来ないので
    chr(92)を使って明示的にするとか・・・あまり効果はないかもです

    キャンセル

  • 2018/06/13 19:29

    > $outputを使って書きたい

    追記部分がそうなっていますが、認識が異なるのでしょうか?

    キャンセル

  • 2018/06/13 19:31

    追記部分のコードでは取り出せませんでした。やはり以下のような出力になってしまいます。

    Array ( [1] => 成田 名詞,固有名詞,地域,一般,*,*,成田,ナリタ,ナリタ [5] => 香港 名詞,固有名詞,地域,一般,*,*,香港,ホンコン,ホンコン [15] => 香港 名詞,固有名詞,地域,一般,*,*,香港,ホンコン,ホンコン [16] => マカオ 名詞,固有名詞,地域,一般,*,*,マカオ,マカオ,マカオ )

    キャンセル

  • 2018/06/13 19:37

    なんでしょうね・・print_rではなくvar_dumpした結果もはれますか?

    キャンセル

  • 2018/06/13 19:41

    var_dumpでの出力結果を「前提・実現したいこと」のところに載せました。

    キャンセル

  • 2018/06/13 19:49

    申し訳ない。完全にケアレスミスでした
    単純に最短マッチがぬけていました。
    修正版のとおり/^(.+?)(?=\s)/で行けるはずです

    キャンセル

  • 2018/06/13 19:52

    うまく取り出せました。ありがとうございます。まだ理由がわかっていないのですが、教えていただけませんか?

    キャンセル

  • 2018/06/13 19:57

    /^(.+?)(?=\s)/ と /^(.+)(?=\s)/の違いは、
    前者が最初に出てくる空白文字まで(つまり最短マッチ)
    後者が最後に出てくる空白文字まで
    という意味になります
    抽出したデータは文字列の最後に改行マークがついており
    改行マークも空白文字の一種なので文字列全体がマッチしていました

    キャンセル

  • 2018/06/13 20:03

    なるほど。最後に出てくる改行マークを認識してしまたのですね。とても助かりました。どうもありがとうございました。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.50%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • PHP

    20369questions

    PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

  • Eclipse

    1661questions

    Eclipseは、IBM社で開発された統合開発環境のひとつです。2001年11月にオープンソース化されました。 たくさんのプラグインがあり自由に機能を追加をすることができるため、開発ツールにおける共通プラットフォームとして位置づけられています。 Eclipse自体は、Javaで実装されています。

  • Mecab

    170questions

    Mecabは、オープンソースの形態素解析エンジンです。 言語、辞書、コーパスに依存しない汎用的な設計を基本方針としています。 Mecabの由来は、開発者の好物である和布蕪(めかぶ)から名づけられました。