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コードを教えてください。

回答の条件
  • 1人1回まで
  • 登録:
  • 終了:2015/07/21 03:06:27
※ 有料アンケート・ポイント付き質問機能は2023年2月28日に終了しました。

回答4件)

id:dev2 No.1

回答回数67ベストアンサー獲得回数26

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 文字目";
    }
}
?>
id:iori753

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

2015/07/15 14:31:08
id:iori753

頼り過ぎで大変恐縮とは思っております。。

2015/07/15 14:31:38
id:muranet No.2

回答回数8ベストアンサー獲得回数0

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

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

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

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

他1件のコメントを見る
id: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=

・・でどうでしょうか?

2015/07/15 21:50:32
id:iori753

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

2015/07/16 01:41:35
id:pmint No.3

回答回数41ベストアンサー獲得回数6

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

id:gizmo5 No.4

回答回数504ベストアンサー獲得回数141

別のコメントにある 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";
      }
    }
  }
}
?>
id:iori753

ご回答ありがとうございます。
HTMLタグは常に同様の形式ではなく、いろいろな形式があっても、大丈夫なようにしたいのです。

2015/07/21 03:05:20

コメントはまだありません

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

回答リクエストを送信したユーザーはいません