IQ Bot：チェックボックスの抽出　応用編

[IQ Bot](https://qiita.com/IQBotter/items/fab5f59230ff38a98bbd)によるチェックボックスの抽出について、先日[基本編](https://qiita.com/IQBotter/items/113da6610773151ae137)を公開しました。

ですが、[カスタムロジック](https://qiita.com/IQBotter/items/1d8e7c77ad47e838476c)を使うことで、より実用的な形でチェックボックスの抽出ができる！　ということで、この記事ではそのやりかたを説明します。

IQ Bot的には応用編ですが、Pythonのコードはそんなに難しくないのと、初心者の方にもわかるように解説していますので、初心者向けのタグもつけておきました。

#応用編で抽出できるチェックボックスの種類

以下のタイプのチェックボックスに対応できます。

- レ点チェック
- 四角の中に×でチェックがしてあるタイプのチェックボックス
- 黒四角（■）でチェックがしてあるタイプのチェックボックス

ラジオボタンは検証していませんが、ロジックを変えればできるんじゃないかと思っています。
サンプルが入手できて検証できたらまたお知らせします。

また、今回の応用編では、**ひとつの質問項目に対し、チェックボックスがひとつだけチェックされるというパターンのみ扱っています。**
複数選択を許容するチェックボックスであれば、[基本編](https://qiita.com/IQBotter/items/113da6610773151ae137)のやりかたのほうがおすすめです。

#IQ Botによるチェックボックスの抽出　応用編

以下のサンプル帳票から以下のような出力結果を得るための、マッピング設定のしかたとカスタムロジックの組み方を説明します。
![サンプル帳票と出力結果.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587845/365f43cd-63cf-813c-8afc-fa397f629e85.jpeg)


##マッピング設定のしかた

マッピング設定のしかたは以下のように、取得したい項目の選択肢全体をフィールド値の範囲に指定します。
![学習のさせかた.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587845/cb096764-f0ee-4571-4652-1a59004993d1.jpeg)

上の図では「性別」というラベルに対して、選択肢の全体をフィールド値として選択しています。
以下のカスタムロジックも、「性別」を例に見ていきます。

##カスタムロジックの組み方

上記の「性別」に対して、以下のようなカスタムロジックを組みます。

```python:カスタムロジック

#カタカナの「ろ」や漢字の「くち」を記号の「しかく」に揃える
field_value = field_value.replace("ロ","□") #カタカナのロ　→　記号の四角
field_value = field_value.replace("口","□") #漢字のくち　　→　記号の四角
field_value = field_value.replace("囗","□") #漢字のくにがまえ　→　記号の四角

cnt = 0
option = ("男性","女性")    #このタプルの中身をチェックボックスの選択肢にする

for i in option:
  x = "□" + i
  if x not in field_value:
    cnt = cnt + 1
    result = i
    
if cnt != 1:
  result = "エラー"

field_value = result
```

項目によって変える必要があるのは、 `option = ` に続くタプルの中身だけです。

```python:工事種別の場合
option = ("新築","増築","増築を伴わないリフォーム","その他") 
```

```python:アンケート結果の場合
option = ("非常に満足","おおむね満足","やや不満","非常に不満") 
```

ここまででもう仕組みがわかってしまった人や、仕組みはわからなくてもとりあえず動けばいいやーという人は、ここから先の説明は読まなくても大丈夫です。

#解説

OCRでチェックボックスを読み取った場合、**チェックされなかったチェックボックスは比較的安定的に読み取れますが、チェックされたチェックボックスはハイフン、アンスコ、中黒など多種多様の読まれ方をしてパターンが推測できません。**

上記のカスタムロジックは、その性質を利用しています。

今回の場合でいうと、`field_value` の素の読み取り結果は  `ロ男性 _女性` となっています。
これはチェックされた女性側の「■女性」のうち「■」の部分を、OCRが記号の「■」として認識できずにアンスコとして読んでいるためです。

##チェックされなかったチェックボックスを揃える

チェックされなかったチェックボックスは比較的安定的に読み取れるとはいえ、こちらもカタカナの「ろ」や漢字の「くち」として読まれる場合はあります。

今回の読み取り結果の`ロ男性 _女性`も、男性の前についている`ロ`はカタカナの「ろ」です。

以下のロジックを使って、カタカナの「ろ」や漢字の「くち」を記号の「しかく」になるように揃えます。

```python:１～２行目

#カタカナの「ろ」や漢字の「くち」を記号の「しかく」に揃える
field_value = field_value.replace("ロ","□") #カタカナのロ　→　記号の四角
field_value = field_value.replace("口","□") #漢字のくち　　→　記号の四角
field_value = field_value.replace("囗","□") #漢字のくにがまえ　→　記号の四角
```

これにより、field_valueの値が `□男性 _女性` になりました。

##メイン処理

次にメインの部分です。

以下の処理では、`option = ` のタプルの中身をループでひとつひとつ処理し、`x = "□" + i` のところで１回目のループでは`□男性`、２回目のループでは`□女性`という文字列を作って、if文のところでその文字列が`field_value`、つまり読み取った値（１～２行目のロジックでカタカナの「ろ」や漢字の「くち」を揃えた後の状態）の中に**含まれていない**かどうかをチェックします。

```python:メインの処理
cnt = 0
option = ("男性","女性")    #このタプルの中身をチェックボックスの選択肢にする

for i in option:
  x = "□" + i
  if x not in field_value:
    cnt = cnt + 1
    result = i
```

今回処理している `field_value` の値は `□男性 _女性` です。
つまり`□男性`は`field_value`に含まれていますが、チェックされた女性側、つまり`□女性`は`field_value`に含まれていません。

ということで、`"女性"`をループしているときにif文の中に入っていきます。

ここでカウンターの`cnt`をカウントアップし、`result` に `i` 、つまり今ループしているタプルの中身である `"女性"` が入ります。

##エラー処理

ループの次のif文はエラー処理です。
`cnt` が1以外、つまりループの中のif文の条件に１個もヒットしなかったり、２つ以上ヒットしたものがある場合は、`result` の中身を `"エラー"`としておくことで検知を可能にします。

```python:エラー処理
if cnt != 1:
  result = "エラー"
```

##field_valueへの代入

以下はもう説明不要かもしれませんが、`result` の値を `field_value` に代入します。

```python:field_valueへの代入
field_value = result
```

これをやらないと、IQ Botに結果を渡せません。

#このカスタムロジックと組み合わせて使いたい検証パターンの指定

このカスタムロジックを組んだ場合に、使っておきたいIQ Bot側の機能が、パターン検証のListです。

「フィールドオプション」のところで以下のように指定しておくと、「List」に入力された「男性」または「女性」という文字列のみを許容し、それ以外は合エラーとします。（フィールドオプションが「任意」の場合は、空欄は許容）

![検証パターン.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587845/2486a9d6-1bb2-34bc-1af0-735479b49200.jpeg)

つまりこれをやっておくことで、`field_value` に `"エラー"`が返ってきた場合にIQ Botが検知して、人間による検証に回せるというわけです。

<font color="Red">**※ただし、Listによる検証の機能はA2019系統では、日本語に対して使うとうまく機能しないことがわかっています。
　ワークアラウンドとしては、結果に"エラー"と入れるかわりに空欄を代入(エラー処理の`result = "エラー"`を`result = ""`に変更)して、必須チェックをかける（フィールドオプションを「必須」にする）方法があります。
　製品側の修正が確認でき次第お知らせします。**</font>

誤り検知については、[こちらの記事](https://qiita.com/IQ_Bocchi/items/4e220a9bd6e337de4508)をご参照ください。