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

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

新規登録して質問してみよう
ただいま回答率
85.50%
PHP

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

正規表現

正規表現とは特定の文字列によるパターンマッチングを行う際に用いられる宣言型プログラミングです。

Q&A

解決済

2回答

1747閲覧

[正規表現]英語の文章だけを排除したい

kalon

総合スコア198

PHP

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

正規表現

正規表現とは特定の文字列によるパターンマッチングを行う際に用いられる宣言型プログラミングです。

0グッド

0クリップ

投稿2016/09/19 19:00

編集2016/09/19 19:16

皆様、平素よりお世話になっております。

<div class="en_text"><br />に囲われた英語の文章」だけを除外して表示したいのですが、以下のように自分なりのコードを書いてみたのですが、どうしても実現できません。

php

1ini_set('display_errors',1); 2header("Content-Type: text/html; charset=UTF-8");//文字化け防止 3 4 5require_once('phpQuery.php'); //phpQueryというモジュールを使う 6 7// HTMLデータを取得する 8$html = file_get_contents('http://www.meigensyu.com/quotations/index/page1.html'); //ターゲットのURL 9 10// HTMLをオブジェクトとして扱う 11$doc = phpQuery::newDocument($html); 12$messages= $doc['div.text']; //これだけでトリミングしたい要素が<html><header><body>付きで代入される 13 14preg_match_all('|<div class="text">(.*)(</div>)|', $messages, $match); //$matchは<div>だけのきれいな配列になる。 15 16/*$matchの「$match[0]にはHTML要素付き」、「$match[1]には平文」が入る。 17平文の文章を抽出したい場合は$match[1][0]からのスタートになる*/ 18$singulerExpression = '<div class="text">'; //名言の入っている要素を指定 19$singulerExpression_noEng ='|<div class="text">(.*)(<br />)|'; 20 21for($i=0;$i<count($match[1]);$i++){ 22 if(!preg_match($singulerExpression, $match[1][$i])){ 23 if(!preg_match($singulerExpression_noEng,$match[1][$i])) 24 echo $match[1][$i].'<br/>'; 25 } 26}

出力部分を以下のようにしても同じ出力結果でした。

php

1for($i=0;$i<count($match[1]);$i++){ 2 echo preg_replace('|<div class="en_text">.*<br />|', '', $match[1][$i]).'<br />'; 3}

上記の出力結果

html

1 2人間はひとくきの葦にすぎない。自然の中で最も弱いものである。だが、それは考える葦である。<div class="en_text">Human being is a reed of one stalk. It is the weakest existence naturally. However , it is a thinking reed .<br/>その日その日が一年中の最善の日である。<br/>チャンスは貯蓄できない。<br/>希望さえあればどんな所にでも たどりつけると決心している。<br/>死者にたいする最高の手向けは、悲しみではなく感謝だ。<br/>人生は道路のようなものだ。 一番の近道は、たいてい一番悪い道だ。<br/>世の中は、君の理解する以上に栄光に満ちている。<br/>人付き合いがうまいというのは、人を許せるということだ。<br/>生きるとは呼吸することではない。行動することだ。<br/>人生は学校である。 そこでは幸福より不幸の方が良い教師である。<br/>若い女は美しい。しかし、老いた女はもっと美しい。<br/>今日という日は、残りの人生の最初の一日。<br/>卵を割らなければ、オムレツは作れない。<div class="en_text">You can't make omelet without breaking eggs.<br/>至上の処世術は、 妥協することなく適応することである。<br/>人間、志を立てるのに遅すぎるということはない。<br/>太陽が輝くかぎり、希望もまた輝く。<br/>行動は必ずしも幸福をもたらさないかも知れないが、 行動のない所に、幸福は、生まれない。<br/>成し遂げんとした志をただ一回の敗北によって捨ててはいけない。<br/>

私の正規表現の書き方か、ロジックに間違えがあると思います。どうかアドバイスやご指摘のほどをお願いいたします。

以上です。よろしくお願いします。

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kei344

2016/09/19 19:17

過去の質問について、「解決済」になっていないものがいくつか見受けられます。解決したものは「ベストアンサー」を選び、自力で解決した場合はその方法を解答欄に書き、もし万が一解決していないのであれば質問を編集するなどしてみてください。
kalon

2016/09/19 19:22

ご指摘ありがとうございます。ご指摘の通り解決済みになっていない質問を解決済みにすることを失念しておりました。 しかしながら、それら回答頂いた方法を今回のコードにも応用してみたのですが、自力で解決に至らなかったので今回このように質問させて頂きました。
guest

回答2

0

ベストアンサー

DomDocumentとXPathを使って抽出してみました。
コメントを書いてあるので、参考にしてください。

php

1<?php 2ini_set('display_errors',1); 3 4// HTMLデータを取得する 5$html = file_get_contents('http://www.meigensyu.com/quotations/index/page1.html'); //ターゲットのURL 6 7$dom = new DomDocument; // DomDocumentオブジェクトを作る 8@$dom->loadHTML($html); // ターゲットのHTMLをDomDocumentに読み込ませる 9$xpath = new DOMXPath($dom); // XPathオブジェクトを作る 10$divs = $xpath->query('//div[@class="text"]'); // classがtextの<div>を探す 11foreach($divs as $div) { // 見つかった<div>が配列になっているのでループで回す 12 $en_divs = $xpath->query('div[@class="en_text"]', $div); // そのdivからclassがen_textの<div>を探す 13 if($en_divs->length) { // divがあったら 14 $div->removeChild($en_divs->item(0)); // en_textのdivを消す 15 } 16 echo $div->nodeValue ."\n"; // <div>内の値をechoで出力する 17}

DomDocumentを使うと、HTMLを構造解析して、XPathでほしい情報を抽出できます。詳しくは、ここを読んで下さい。多くの場合、正規表現より正確かつ簡単に抽出できます。
phpQueryは、内部的にはDomDocumentとXPathを使ったスクレイピングライブラリですが、DomDocumentに比べて情報も少ないので、まずはPHP標準機能であるDomDocumentを素直に使うことをおすすめします。

投稿2016/09/19 20:30

編集2016/09/20 13:12
popobot

総合スコア6586

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kalon

2016/09/20 03:58

素晴らしいアドバイスをありがとうございました。しかしながら、ご教授頂いたコードですと英語の文章だけが抽出されてしまい、私の実現したい「英語の文章だけの排除」とは違います。 今理解できている限りで頂いたコードを応用してみたのですが、やはり英語の文章の排除が実現できませんでした。 ```php <?php ini_set('display_errors',1); // HTMLデータを取得する $html = file_get_contents('http://www.meigensyu.com/quotations/index/page1.html'); //ターゲットのURL $dom = new DomDocument; // DomDocumentオブジェクトを作る @$dom->loadHTML($html); // ターゲットのHTMLをDomDocumentに読み込ませる $xpath = new DOMXPath($dom); // XPathオブジェクトを作る $divs = $xpath->query('//div[@class="text"]'); // classがen_textの<div>を探す foreach($divs as $div) { // 見つかった<div>が配列になっているのでループで回す echo $div->nodeValue ."<br />"; // <div>内の値をechoで出力する } ``` どうしたら.textだけを抽出して.en_textを除外できるのでしょうか? 以上質問です。よろしくお願いします。
popobot

2016/09/20 04:51

ごめんなさい!! マジボケしてました... 直してみたので、試してみてください
kalon

2016/09/20 12:41

コードの修正ありがとうございました。 ですが、foreach文が"}"で終わっていなかったことを恐れながらご指摘させて頂きます。コードとして正しいのは以下のようです。 ```php <?php ini_set('display_errors',1); // HTMLデータを取得する $html = file_get_contents('http://www.meigensyu.com/quotations/index/page1.html'); //ターゲットのURL $dom = new DomDocument; // DomDocumentオブジェクトを作る @$dom->loadHTML($html); // ターゲットのHTMLをDomDocumentに読み込ませる $xpath = new DOMXPath($dom); // XPathオブジェクトを作る $divs = $xpath->query('//div[@class="text"]'); // classがtextの<div>を探す foreach($divs as $div) { // 見つかった<div>が配列になっているのでループで回す $en_divs = $xpath->query('div[@class="en_text"]', $div); // そのdivからclassがen_textの<div>を探す if($en_divs->length) { // divがあったら $div->removeChild($en_divs[0]); // en_textのdivを消す } echo $div->nodeValue ."\n"; // <div>内の値をechoで出力する } ``` そしてこちら頂いたコードを上記のように修正して、実行すると以下のエラーを吐きます Fatal error: Cannot use object of type DOMNodeList as array in /myphp.php on line 14 もう少しどのようなロジックで英語を除去しているのか読み込ませて頂き自分で解決できるように努力してみますが、引き続きご指導のほどよろしくお願いします。
popobot

2016/09/20 13:13 編集

すみません... 最後の}が抜けてましたね。 自分の環境ではこれで動くのですが、なんででしょうね...phpのバージョンでしょうか。 ちなみにmyphp.phpの14行って以下ですよね? $div->removeChild($en_divs[0]); // en_textのdivを消す 回答のPHPを直して見たので、もう一度やってみてください
kalon

2016/09/21 02:48

ありがとうございました。頂いたコードで動きました。懇切丁寧なアドバイスの上に、コードまで書いてくださってありがとうございました。
popobot

2016/09/21 02:58

うまく行ってホッとしてます。DomDocumentと正規表現をうまく使い分けながらスクレイピングするのがいいと思います。
guest

0

英語だけの文書ってstrlenとmb_strlenが一緒だって判断していいなら例えばこう

PHP

1$str=<<<eof 2<div class="en_text">hoge hoge hoge<br />hoge hoge</div> 3<div class="en_text">hoge ほげ hoge<br />hoge hoge</div> 4<div class="en_text">ほげほげ<br />hoge hoge</div> 5<div class="jp_text">hoge hoge hoge<br />hoge hoge</div> 6eof; 7$pattern="|(?<=<div class=\"en_text\">).+(?=<br />)|"; 8$replacement=function($a){return strlen($a[0])==mb_strlen($a[0])?"":$a[0];}; 9$str=preg_replace_callback($pattern,$replacement,$str); 10print nl2br(htmlspecialchars($str));

投稿2016/09/20 08:56

yambejp

総合スコア114585

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問