人力検索はてな
モバイル版を表示しています。PC版はこちら
i-mobile

HTMLでマークアップされている、長い文章を上手くPHPで小分けに分割する方法を教えてください。

GoogleのtranslateAPIキーを取得し、下記サイトなどを参考にPHPにて翻訳を試しています。 Add Star
http://kaedetrans.blogspot.jp/2011/12/google-translate-api-rest-7.html

しかしAPIのコール一回あたりGETであれば2Kほど、POSTでも5K程が上限です。

その際、文字を分割したりコードを途中で区切り、分割翻訳、最後に結合したいと思います。
しかし制限文字範囲内で一番近い句点(。)で区切るところまでは出来たのですが、HTMLなども入ってくるとよく分からず…

HTML混じりの文章を、
・タグが途中で切れない
・文章が途中で切れない
・指定文字範囲内に日本語がない(長いHTMLしかない)場合、及び日本語しかないもエラーを起こさない
という分割をPHPで実現する方法はありますでしょうか。

コピペで使えるような具体的なPHPコードを教えてください。


●質問者: maintour15
●カテゴリ:コンピュータ ウェブ制作
○ 状態 :キャンセル
└ 回答数 : 4/4件

▽最新の回答へ

1 ● LLマン

GoogleのtranslateAPI

その細かい仕様を知らないので、質問にある仕様の範囲内で回答します。
(申し訳ないですが、難しい仕様がある場合、お助けできないかもしれません)

また、ご質問の前提の確認ですが、テキストにHTMLのタグが入ったまま、
先方のAPIに渡してもタグが破壊されず、あらかじめタグを除去する必要がない仕様ですね?
以下その前提で回答します。

制限文字範囲内で一番近い句点(。)で区切るところまでは出来た

句点だとタグの中に入ってしまう場合がありますね。

それ以外の方法で、パッと思いついた中で一番単純なのは、
「<」「>」(HTMLならエスケープされているはず)を文字列探索する方法です。

具体的には、文字列を先頭から2千字とか、上限範囲となる末尾から探索して、
「<」が先に見つかればその左側、「>」が先に見つかればその右側で切れば、

・タグが途中で切れない ・文章が途中で切れない

の要件は満たします(正しいタグ付けの場合)。

・指定文字範囲内に日本語がない

そのときは(日本語→英語の場合)翻訳する必要がないので、
タグが終わるまでの部分をAPIに渡さず、直接表示します。

日本語しかない

その場合は句点で区切ることになります。

また、上述の「>」を先に見つけた場合、
右側を句点で探すと、より長く区切れます。


>具体的なPHPコード
以下のサンプルコードは、HTMLのタグを探すサンプルになります。
オンラインコードサービスでですが、動作を確認しました。

要点をイメージするための叩き台で、
句点探索の追加など、ご使用に合う形でのコーディングは、
恐縮ですがご質問者様にお願いします。

単純なコードなので詳しい解説は省略しますが、
不明な点があればご質問ください。

<?php
//文字列中からHTMLタグを検索するサンプル

$separate = -1;
//テスト用 左側のタグが先に来るパターン
//$separate = -5;

$mystring = 'abc<1def>ghi<2jkl>mno';

//テスト用 両方見つからないパターン
//$mystring = 'abc1defghi2jklmno';

echo "検索対象文字列は'$mystring'\n";

$findL = '<';
$findR = '>';

//文字列の後方から探索
$posL = strrpos($mystring, $findL, $separate);
$posR = strrpos($mystring, $findR, $separate);

if (($posL === false) and ($posR === false)) {
 echo "検索文字は、対象文字列の中で見つかりませんでした。\n";
 
} else {

 if ($posL > $posR) {
 echo "検索文字 '$findL' を対象文字列から発見。\n";
 echo "位置は $posL 文字目";
 }
 
 if ($posR > $posL) {
 echo "検索文字 '$findR' を対象文字列から発見。\n";
 echo "位置は $posR 文字目";
 }
}
?>

maintour15さんのコメント
ご回答ありがとうございます。 句点又はタグ自体はなんとなく切り良くカット出来るのですが、両方となると頭がごっちゃになってわからないので、具体的なコードで両方を満たすものを教えて欲しいのです。

maintour15さんのコメント
頼り過ぎで大変恐縮とは思っております。。

2 ● muranet

回答になっているかどうか分かりませんが、PHPではタグを除去する strip_tags という命令があります。

http://php.net/manual/ja/function.strip-tags.php

>HTML混じりの文章を、
>・タグが途中で切れない
>・文章が途中で切れない
>・指定文字範囲内に日本語がない(長いHTMLしかない)場合、及び日本語しかないもエラーを起こさない

のそれぞれの分割前・分割後の例を示していただけると回答しやすくなると思います。


maintour15さんのコメント
ご回答ありがとうございます。 質問がわかりずらくて申し訳ありません。 APIに対し、HTML自体を送信して翻訳された文章のHTMLを受け取りたいのですが、タグが途中ですと崩れた状態になりますし、文章の途中ですと意味が変わってくるため、両方を満たすコードがほしいのです。 例えば下記の場合、 http://headlines.yahoo.co.jp/hl?a=20150715-00003389-bengocom-soci <p class="ynDetailText"> 集団的自衛権の行使を可能にする安全保障関連法案が7月15日、衆議院の特別委員会で採決され、自民、公明両党の賛成多数で可決された。与党は16日の衆院本会議で可決、参議院に送付する方針だ。<br> <br> 民主、維新、共産の野党3党が採決に反発。「強行採決反対」と浜田靖一委員長に詰め寄り、怒号が飛び交う中、法案は可決された。<br> <br> 国会前には、炎天下にもかかわらず、午前中から多くの人たちが集まり、正午すぎには数百人の規模となった。「安倍たおせ」などののぼりが翻る中、可決の一報を聞き、「絶対に許さない」「強行採決徹底糾弾」「戦争法案今すぐ廃案」などと怒りの声をあげていた。<br> <br> 国会前で民主党の枝野幸男幹事長は「民主主義を破壊する安倍内閣の暴走を防ぎたい。世論の声を広げてともに戦いましょう」と呼び掛けていた。<br> <br> 同党の徳永エリ参議院議員は「強行採決には、腹が立って腹が立って泣きそうになった。日本を戦争にする国にしてはいけない。これから参議院で新たな戦いが始まる」と力説していた。<br> <br> 共産党の山下芳生書記局長は「憲法違反であることは明白だ」と安倍政権の対応を強く批判していた。<br> <br> 夕方からは若者たちによるデモも開催される予定。</p> となっていますが、 改行タグなどはちゃんと<>の前後で終わるように分割しなければなりませんし、テキスト部分は句点が最後となるように分割したいのです。 そうすればAPIで翻訳したあとも綺麗にHTMLがついたままテキストだけが翻訳されるので、後で結合することにより数千?数万文字の文章(HTML)でもレイアウトは維持したまま翻訳出来るというイメージなのですが・・・

muranetさんのコメント
日本語で書かれたWebサイトを、ページレイアウトを維持したまま英語に翻訳したい ということでしたら、 Google翻訳 https://translate.google.com/ の左側の枠に URL を入力し、「翻訳」ボタンを押したら、それっぽいページが出てきます。 https://translate.google.com/translate?sl=ja&tl=en&js=y&prev=_t&hl=ja&ie=UTF-8&u=http%3A%2F%2Fheadlines.yahoo.co.jp%2Fhl%3Fa%3D20150715-00003389-bengocom-soci&edit-text= ・・でどうでしょうか?

maintour15さんのコメント
ありがとうございます。 大量に(数万記事)行う必要があるので、APIを使いたいのです。。

3 ● pmint

HTMLの構造に沿って分割する方法もあります。
スクレイピングに使われるコードですね。
DOMDocumentクラスを使ったコードを紹介します。

<?php

$src_url = '';// ファイルパスも可

$html = file_get_contents($src_url);
$html = mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8');// &#160;などを文字コード化

$doc = new DOMDocument();
$doc->loadHTML($html);

$text = $doc->textContent;

// 特定要素のみを扱う場合(一例)
$body = $doc->getElementsByTagName('body')->item(0);
$text = $body->textContent;

print_r($text);

?>

<p>などの要素単位でテキストを得れば、タグの切れっぱしに悩まされることはありません。


4 ● gizmo5

別のコメントにある Yahoo!ニュースですと、ニュース記事は class="ynDetailText" の属性が付いた P タグに囲まれていて <BR> でパラグラフが分割されています。
以下のようなコードで一文ずつ取り出せるので、逐次翻訳APIを呼び出して結果を結合すれば良いでしょう。

<?php

$url = 'http://headlines.yahoo.co.jp/hl?a=20150715-00003389-bengocom-soci';
$html = file_get_contents($url);

$doc = new DOMDocument();
$doc->loadHTML($html);

$array = $doc->getElementsByTagName('p');
foreach ($array as $p) {
 if ($p->getAttribute('class') == 'ynDetailText') {
 $children = $p->childNodes;
 foreach ($children as $child) {
 if ($child->nodeType == 3) {
 // 記事のパラグラフが $child->nodeValue で取り出せる
 echo $child->nodeValue . "\n";
 }
 }
 }
}
?>

maintour15さんのコメント
ご回答ありがとうございます。 HTMLタグは常に同様の形式ではなく、いろいろな形式があっても、大丈夫なようにしたいのです。
関連質問

●質問をもっと探す●



0.人力検索はてなトップ
8.このページを友達に紹介
9.このページの先頭へ
対応機種一覧
お問い合わせ
ヘルプ/お知らせ
ログイン
無料ユーザー登録
はてなトップ