phpで禁止ワードチェック機能を実装してみた

適当にプログラム作って勢いでリリースすると、運営を始めてからそういえばこれ無いと運用上不味いよねと後から気づくのが、IPアドレス弾きや禁止ワードチェックの機能。

特に禁止ワードチェックで、この間つい勢いでリリースしてしまって大失敗した。
Feedでのまとめ系のandroidアプリを公開しようと、Googleプレイにデベロッパー登録してアプリをとりあえずβ版としてアップロードしたら、なんと、ものの数分で公開を停止させられた(笑)
停止の理由は、「コンテンツ ポリシーの露骨な性表現を含むコンテンツ条項への違反。」とのこと。

健全なごく普通のアプリであって18禁のいやらしい内容なんて含んだアプリでもないし、その時は訳が分からなくて、なんで削除されてしまうの?間違いじゃない?とメールで抗議してみたら、「性的な表現、または露骨な描写を含むコンテンツやタイトル文があります。」らと指摘されて返信がきた。
改めてFeedで取得してきている記事内容を念入りに確認してみると、色んなサイトからリンクを引っ張ってきているので、中には確かに下劣な広告や文章、画像などあってビックリしたことがある。
こんな短時間で引っかかってアプリを削除されてしまうなんて、そういうのに引っ掛ける検知ツールみたいなのが動いているのだろうか。以前はGoogleプレイは無法地帯な感じだったのに、今はずいぶんと厳しくなったものです。
今年くらいからどうやら人的チェックもするようになってドンドン厳しくなっているようです。これからアプリ作って登録する方は、GoogleプレイでもApple並に気を付けてから登録するようにしましょう。

それはそうと、このままアプリ公開を断念するのもすごく悔しいし、デベロッパー登録に25ドル先払いしてしまっているので、なんとかしたい。
PHPで禁止ワードにひっかかる記事はアプリに表示させないようになんとかしました。

禁止ワードチェック機能

例えば、RSSで取得した記事のタイトルを禁止ワードチェックする場合は以下の手順になります。

まず、禁止ワードを設定するiniファイルを ngword.ini のファイル名で以下のような感じでNG_WORDSと、そのNGワードを包括してしまう用語をOK_WORDSとして作成します。

[NG_WORDS]
1 = "ロリ"
2 = "エロ"
3 = "えろ"
4 = "フェラ"
5 = "グロ"

[OK_WORDS]
1 = "ペロリ"
2 = "イエロー"
3 = "教えろ"
4 = "カフェラテ"
5 = "フェラーリ"
6 = "グローブ"

iniファイルを作ったら、PHP内で禁止ワードをパースして読み込み、チェック機能を以下のような感じで追加します。

// 禁止ワード設定ファイルをパース
$code = parse_ini_file('ngword.ini', true);
$ng_words = $code['NG_WORDS'];
$ok_words = $code['OK_WORDS'];

foreach($rssdata->item as $myEntry){
  // 禁止ワードチェックフラグを0にセット
  $ngflag = 0;

  // タイトル変数を一旦$title_tempへ
  $title_temp = $myEntry->title;

  // 文字列を一旦小文字にする
  $title_temp = mb_strtolower($title_temp, 'utf-8');

  // 文字列内の半角カナ、濁点付きの文字、全角英数字、全角スペースを変換
  $title_temp = mb_convert_kana($title_temp,'asVK','utf-8');

  // 空白スペースや、。を一旦削除
  $title_temp = preg_replace('/\s|、|。/', '', $title_temp);

  // 禁止キーワードを包括してしまう許可キーワードを一旦 * に変換
  foreach ($ok_words as $okWordsVal) {
    if (strpos($title_temp, $okWordsVal) !== false) {
      $title_temp = str_replace($okWordsVal, '*', $title_temp);
    }
  }

  // 禁止ワードチェック
  foreach ($ng_words as $ngWordsVal) {
    if (strpos($title_temp, $ngWordsVal) !== false) {
      // 禁止ワードが見つかった!
      $ngflag = 1; // フラグに1を入れる
      break; // 処理の停止
    }
  }
  
  // 禁止ワードフラグに1が入っていればループ飛ばし
  if($ngflag == 1) continue;
  
  // 以下から正常処理
  ・
  ・
  ・
  
}

以上