住所パーサーは1つの文字列を構造化フィールドに変換します。すなわち、1行目、2行目、市区町村、都道府県・州、郵便番号、国です。これはカンマで分割するだけのように聞こえますが、郵便番号が市区町村より前に来るドイツの住所、最大単位から書く日本の住所、あるいは「St」が通りの接尾辞ではなく市区町村名の一部である米国の行に遭遇するまでは。
本ガイドでは、曖昧性に対して正直なパーサーについて説明します。設計原則はシンプルです。文法が対応するものだけを解析し、解析した結果にスコアを付け、信頼度が低い場合は元の文字列をそのまま返します。誤ったフィールドを黙って返すパーサーは、拒否するパーサーより悪いです。誤ったフィールドが保存され、元の情報が捨てられてしまうからです。
解析で復元できることとできないこと
解析はテキストに存在していた構造を復元します。郵便番号、地域コード、市区町村、番地行を、その信頼性の順に復元します。しかし、書かれていない情報は復元できません。ユニット番号の指定がない文字列にはユニット番号は含まれておらず、どれだけ推論しても捏造すべきではありません。
また、フィールドが真実であることを確認することもできません。「123 Main St, Springfield, IL 62701」を解析すると一貫したフィールドが得られますが、その住所が架空である可能性や、市区町村がZIPと一致しない可能性もあります。解析はテキスト操作です。検証はデータ操作であり、この2つは関数名や成功メッセージを共有すべきではありません。
- 復元可能:郵便番号、地域、市区町村、番地行、ユニット指定
- 復元不可能:欠落したユニット、欠落した国、誤った市区町村
- 電話の国番号や言語から国を推測しない
- 空のフィールドをもっともらしいデフォルトで埋めない
4段階のパイプライン
第1段階は正規化です。前後の空白を除去し、内部の空白をまとめ、ノーブレークスペースを置換し、句読点の異体を正規化し、大文字化するかどうかを決定します。フォールバック用に元の文字列はそのまま保持します。第2段階は分割です。カンマがあればカンマで分割し、なければ国の文法で分割します。第3段階は分類です。国のルールセットを使って各セグメントを郵便番号、地域、市区町村、番地、ユニットとしてラベル付けします。第4段階は割り当てです。ラベルをフィールドにマッピングし、競合を解決し、結果にスコアを付けます。
各段階を分離しておくことで、失敗モードも分離できます。分割のバグは分類のバグとは異なる見え方をし、各段階を独自のコーパスで単体テストできます。また、早期に停止することも可能です。国が不明な場合は分類を完全にスキップし、各フィールドの信頼度を不明としてセグメントを返します。
- 元の文字列を破壊せずに正規化する
- まずカンマで分割し、次に文法で分割する
- 国別のルールセットで分類する
- 割り当て、スコア付け、受け入れるかどうかの判断
国別のフィールド順序
フィールド順序は誤解析の最大の原因です。同じトークンが場所によって移動するからです。米国、カナダ、英国、オーストラリアでは郵便番号が市区町村の後に来ます。ドイツ、フランス、オランダ、ベルギーでは市区町村の前に来ます。日本では都道府県の前に最初に来ます。ブラジルでは州の後に区切り文字を挟んで郵便番号が来ます。
だからこそ、パーサーは何かを分類する前に国を知っている必要があります。文字列自体から国を推測するのは循環論法です。郵便番号のパターンから示唆されることはありますが、多くのパターンが重複しています。フォーム、ロケール、または明示的なセレクターから国を取得し、州や国のどちらかである可能性のある2文字のトークンから推測するのではなく、国が欠落している場合は解析を低信頼度としてマークしてください。
| 国 | 順序 | 例 |
|---|---|---|
| 米国 | 番地、市区町村、ST ZIP | 1420 SW Alder St, Portland, OR 97205 |
| カナダ | 番地、市区町村、ST A1A 1A1 | 88 Queen St W, Toronto, ON M5H 2M5 |
| ドイツ | 番地、ZIP 市区町村 | Unter den Linden 77, 10117 Berlin |
| フランス | 番号 通り、ZIP 市区町村 | 12 Rue de Rivoli, 75004 Paris |
| オランダ | 通り 番号、ZIP 市区町村 | Damrak 1, 1012 LG Amsterdam |
| 日本 | ZIP、都道府県、市区町村、番地 | 100-0001 Tokyo, Chiyoda, Chiyoda 1-1 |
| ブラジル | 番地、市区町村 - ST、ZIP | Av. Paulista 1000, Sao Paulo - SP, 01310-100 |
対処する価値のある曖昧なケース
二次ユニット指定子は最も一般的な曖昧性です。「Apt」「Ste」「Unit」「Fl」「Rm」は識別子が続く場合は信頼できますが、「Unit 5」は通りの名前であることもあり、「Building 3」はキャンパスの主住所であることもあります。パーサーは、指定子の後に数字または短い英数字トークンが続き、番地番号の後に現れる場合にのみユニットを抽出すべきです。
通りの接尾辞は2つ目の罠です。「Way」「Court」「Park」のようなトークンは、接尾辞、通りの名前、または市区町村になり得ます。方向指示語も同じ問題を抱えています。「N」は前置方向指示語、通りの名前の略語、または地域になり得ます。番地番号とカンマ構造に対する位置を使用し、2つの読み方が両方とももっともらしい場合は、選択するのではなく元のセグメントを保持して信頼度を下げてください。
| 入力 | もっともらしい読み方 | 安全な処理 |
|---|---|---|
| 12 Court St | 通りの接尾辞または名前の一部 | 番地行全体を保持 |
| Unit 5, 100 Main St | 通りの前のユニット | ユニットを割り当て、通りを保持 |
| 100 N Park Ave | 方向指示語と接尾辞 | 通りのトークンを順序どおりに保持 |
| Springfield Rd, Springfield | 市区町村名に接尾辞 | カンマ境界を優先 |
| Tokyo, Chiyoda 1-1 | 市区町村と街区 | 国の文法を使用 |
| Apt 4B 12 Main | カンマなしのユニット | 抽出して再スコア付け |
信頼度スコアとしきい値
各フィールドにスコアを付け、次にレコードにスコアを付けます。フィールドは、国の固定パターンに一致し、その位置が期待される順序と一致した場合に高信頼度です。パターンは一致したが位置が推測された場合は中程度、消去法で割り当てられた場合は低信頼度です。レコードは、すべての必須フィールドが高信頼度で、未配置のセグメントがない場合にのみ高信頼度となります。
しきい値を設定し、それを強制します。しきい値を超えた場合は受け入れて保存します。下回る場合は、推測を構造化カラムに書き込むのではなく、元の文字列を保持してレコードをレビュー用にフラグ付けします。APIレスポンスでスコアと理由を公開してください。レビュー担当者は何かが失敗したことだけでなく、どのフィールドが失敗したかを知る必要があるからです。
| フィールド | 高信頼度のシグナル | 低信頼度のシグナル |
|---|---|---|
| 郵便番号 | 固定パターンに一致、正しい位置 | パターンは一致したが移動した |
| 地域 | その国の既知のコード | 一致しない2文字トークン |
| 市区町村 | 郵便番号の左または通りの右 | 消去法で割り当てられた |
| 番地 | 番地番号と名前を含む | 番号のない名前のみ |
| ユニット | 通りの後の指定子と識別子 | 通りの名前内の指定子 |
返すべきエラー状態
解析結果にはブール値ではなく、明示的な結果が必要です。国が欠落している場合は文法を実行できません。郵便番号の欠落は、郵便番号がある国では問題であり、香港やUAEでは正常です。配置できないセグメントは、カンマ構造と文法が一致していないことを意味し、レコードには人間の目が必要です。
各結果に安定したコードを付与し、呼び出し元が散文を解析せずに分岐できるようにします。正規化された入力、元の入力、信頼度付きのフィールド値、および未配置セグメントのリストを返します。このペイロードにより、UIはフォームの上部に一般的なエラーを表示するのではなく、失敗した正確なトークンをハイライトできます。
- MISSING_COUNTRY:利用可能な文法がない、推測しない
- MISSING_POSTAL:国にコードがある場合はエラー、ない場合は正常
- UNPLACED_SEGMENT:カンマ区切りの部分がどのフィールドにも一致しなかった
- AMBIGUOUS_UNIT:複数の読み方があるユニット指定子
- REGION_MISMATCH:指定された国に対して地域コードが無効
ゴールデンコーパスの構築と変異
国ごとに1〜3件の手動検証済み住所からなる小さなコーパスから始めます。各住所には、その国の郵便物を読める人が書いた期待フィールド値が付きます。20〜40件のケースで構造的なリグレッションを捉えるのに十分であり、プルリクエストでレビューするのに十分小さいです。テストコードに埋め込まれたアサーションではなく、データとして保存してください。
次に、各ケースを機械的に変異させます。カンマを削除し、大文字小文字を変更し、二重スペースをまとめ、ノーブレークスペースを挿入し、2行を入れ替え、接尾辞を省略し、ユニットを追加します。変異に対する期待出力は常に同一とは限りませんが、定義された許容範囲内に収まるべきであり、フィールドが黙って変わるのではなく信頼度が下がるべきです。フィールドごとに適合率と再現率を追跡し、市区町村の修正が郵便番号を静かに壊さないようにします。
| 変異 | 変更例 | 期待される動作 |
|---|---|---|
| カンマを削除 | 1420 SW Alder St Portland OR 97205 | 同じフィールド、信頼度は低下 |
| 小文字化 | portland, or 97205 | 正規化後に同じフィールド |
| 二重スペース | Portland, OR 97205 | 同じフィールド、空白はまとめられる |
| 市区町村と州の間にNBSP | Portland, OR with U+00A0 | 同じフィールド、NBSPは正規化 |
| 市区町村と地域を入れ替え | OR Portland 97205 | フラグ付け、黙って入れ替えない |
| 番地を切り詰め | 1420 SW Alder | 番地は保持、市区町村は依然として検出 |
まったく解析しない方がよい場合
自由形式のメモ、配達指示、または人間が散文として書いたものは解析しないでください。「Leave at the side gate, second house after the blue one」にはフィールドがなく、そこからトークンを抽出すると自信に満ちたゴミが生成されます。注文に添付されたテキストブロブとして保持してください。
ルールセットが対応していないスクリプトは解析しないでください。漢字の日本の住所には日本語の文法が必要です。ラテン文字のトークナイザーを実行すると誤った境界で分割され、都道府県が失われます。番地番号がない住所や、アジアの一部やキャンパスの住所で一般的な建物名を主要な位置指定子として使用する住所は解析しないでください。これらすべての場合において、正しい出力は元の文字列と明確な「未解析」ステータスです。
- 配達指示:テキストとして保存し、フィールドとして保存しない
- 未対応のスクリプト:明示的なステータスとともに元の文字列を返す
- 建物名の住所:番地番号を強制しない
- 私書箱と地方配送路:汎用ルールではなく国別ルールで解析する
- すでに構造化されているもの:再解析するのではなく検証する
よくある質問
- いいえ。テキストに存在する構造を復元し、自身の信頼度にスコアを付けるだけです。書かれていないフィールドは復元できず、解析によって住所が実在することが証明されるわけでもありません。
- フィールド順序が異なるからです。ドイツと日本は郵便番号を市区町村の前に置き、日本は最初に置き、米国は最後に置きます。国のルールセットがなければ、同じトークンが誤ったフィールドに割り当てられます。
- 元の文字列を保持し、部分的なフィールドをスコアとともに返し、レコードをレビュー用にフラグ付けします。推測を構造化カラムに書き込むと、入力の唯一の信頼できるコピーが失われます。
- 国ごとに1〜3件の手動検証済みケースを20〜40件、加えて機械的な変異です。誰もレビューしないコーパスを作成せずに、構造的なリグレッションを捉えるのに十分です。
- 住所パーサーツールはフィールドモデルとフォーマットルールを公開します。配達可能性を検証するものではなく、解析されたフィールドが実在の場所を表すと主張するものでもありません。
住所パーサーは正しいフィールドを保証できますか?+
なぜ解析の前に国が重要なのですか?+
信頼度が低い場合、パーサーはどうすべきですか?+
テスト用の住所はいくつ必要ですか?+
このサイトは私の代わりに住所を解析しますか?+
例は合成データです。生成された住所を本人確認、アカウント登録、配送に使用しないでください。