C#の文字列から電子メールアドレスを解析する

画像 少し前まで、顧客の1人のデータを別の準州形式にアップロードするという課題に直面しました。 特に、郵便番号、地域、地区などを含む個々の顧客の住所をアパート番号に提供するために、荷降ろしが必要です。



すべてうまくいきますが、待ち伏せは、顧客の送信元アドレスが「Kitezhgrad、22 Volgoshnaya St.、Building 15、Quarter 15」のような単純な文字列に詰められていることです。 つまり、一方では誰も郵便番号を聞いたことがありませんが、他方では、入力テキストフィールドは自己表現と応用アートの広い範囲を提供します。



ためらうことなく、私はネットでこの問題の解決策を探すために登りました。そのような状況は非常に一般的であり、誰かが間違いなく敗北するはずだと推論しました。 しかし、ソースコードや単純にコンパイルされたライブラリの代わりに、オンラインサービスは私を熱心に見つめ、APIを使用して電子メールアドレスを解析して非常にリアルな賄briを提供しました(私が見つけた最低価格はアドレスあたり10コペックでした)。

第三者組織に自発的な収入を与えるのは好きではなかったので、その時までに興奮があったので、できるだけ少ない労力で自分で解決策を集めたかったのです。 このタスクは、顧客が高精度の解析を必要としないという事実によって促進されました-あらゆる種類のエラーの存在は致命的な問題につながりません。



そもそもTomit-parserに目を向けましたが、どのページに住んでいるのか( http://api.yandex.ru/tomita/doc/dg/concept/example.xml )をテキストで判断できるようにするサンプルの複数ページ構成に精通した後、 、楽観主義は幾分減少しましたが、ある種の自転車を書きたいという欲求は強くなりました。



当然、入力データに対してかなり厳しい制限があり、その下で研究を続けます。

  1. 住所は常にタイプミスなしで書かれています:「Arphography Avenue」は紹介者の良心に残るべきです。
  2. アドレスは、最も一般的な要素(地域)から最もプライベートな(アパート番号)まで記録されます。
  3. パラグラフ2に従って、「地域」、「通り」、「大通り」、「家」などの単語プロンプトにボルトを打ち込みます。 そのため、都市にTelepuzikov Avenueとそれらにちなんで名付けられた通りがある場合、そのような細い線をキャッチすることはできません。 このような状況はまれであり、間違いを犯す権利があることを考えると、これは非常に有効な選択肢です。


次に、郵便番号に関する情報を引き出すことができるデータソースの検索に困惑しました。 判明したように、今日まで、KLADRはすでに昨日、FIASルール( http://fias.nalog.ru )です。 このデータベースのオフラインコピーをダウンロードした後、私はそれが提供する可能性を研究し始めました。



私は特に2つのテーブルに興味がありました:ADDROBJ-ロシア連邦の主題から始まり、通りで終わるすべての住所オブジェクトのツリーのようなリストと、HOUSE <region number>-ADDROBJのレコードとそのインデックスを参照して格納されているハウス番号が含まれています。 これらの2つのテーブルに格納された情報は、住所解析の正確性をチェックする(データベースで住所を見つけることができた場合、それを正しく認識した)だけでなく、郵便番号を決定するという両方の目標を達成するのに十分です。



私の頭の中でアルゴリズムが形になり始めました:

  1. 住所の行を住所要素に分割します。 住所要素とは、FIASテーブルの行の形式で見つけられるものを意味します:地区、都市、通り、家、およびアパート番号。

    1. アドレス要素の無条件の区切り文字には、ピリオド、コンマ、セミコロン、スラッシュが含まれます。
    2. ハイフンの後のアドレス要素が数字の場合、条件区切り文字にはハイフン/ダッシュが含まれます。 たとえば、「Depression Lane 38a-117」ではハイフンがセパレータであり、「g。 ウスチザゾピンスク "-いいえ。
    3. スペースは区切り文字である場合とそうでない場合があります。 そのため、「3月8日d.15」では、「8日」と「3月」の間のスペースは明らかに要素を分割するべきではなく、「3月」と「d」の間はそうすべきです。 額の最も簡単なオプションは、アドレス要素をスペースで区切るためのすべての可能なオプションを作成し、それぞれを個別に使用してアルゴリズムのさらなる作業を続けることです。
  2. 「street」(「street」)、「region」(「region」)などのアドレス可能な要素は完全に噛み付いています。

  3. 最初の要素から始めて、それらはすべてFIASに基づいて順次実行されます。
    1. 要素がベースにある場合、そのGUIDとLEVEL(階層内のレベル)は記憶されますが、次の要素はより高いLEVEL値で検索され、前の要素のGUIDと等しい固定PARENTGUIDが検索されます。
    2. 指定されたPARENTGUIDの要素が見つからない場合は、中間要素を含むチェーンを構築してください。
    3. 最初の検索はテーブルADDROBJにあり、通りの後の次の要素を探すとすぐに(通りのレベルは7)、HOUSEXXの家のテーブルに切り替えます。
    4. アドレス要素が見つからない場合は、無視してください。
  4. オプションが勝ちます(ステップ1.3の結果に応じて、それらのいくつかが存在する可能性があります)。
  5. 注文のため、最上部のADDROBJテーブルに従って完成します。 これが必要なのは、たとえば、地域と地区が元のアドレスバーに表示されず、都市が一度に表示されたためです。
  6. もう少しチートします。 アパート番号は最後の住所要素と見なされ(家番号として認識されなかった場合)、認識された家番号とアパート番号の間の住所要素は建物、建物、手紙、その他すべてと見なされます。 より詳細な分析を作成することは可能でしょう-HOUSEXX表はこれを許可します-しかし、郵便番号が家「113」と「113 st。1 building 4 lit. Zh。」で異なる可能性が低いという理由だけで、私には不必要に思えました。


アルゴリズムは経験的で素朴で、考えられるすべての状況を提供するわけではありませんでした...しかし、実装速度の制限とエラーに対する広範な権利については、非常に満足のいくものでした。 約1晩で作成して実装することができました。



習慣と利便性のために、私はADDROBJとHOUSEXXのテーブルをDBFからMS SQLに上書きしました(簡単に変換する方法をここで読みました: http : //blogs.technet.com/b/isv_team/archive/2012/05/14/3497825.aspx



結果はAddressParserクラスです。これは、入力でアドレス文字列を取得し、応答でAddressクラスのインスタンスを返します。 MS SQLによって強化された現在の実装が何かに適していない場合、IKnwonAddressComparatorの独自の実装をAddressParserコンストラクターに送信できます。



解析速度は1秒あたり2〜5アドレス程度でした。 悪いが、ペンよりはましだ。 主な問題:1.3項で生成された検証用の非常に多くのオプション。 良い方法では、この段階で既にアドレスベースを使用してアドレス要素の存在を確認し、この点を完全に書き換える必要があります。 中間オプションとして、オプションの数を特定の値に制限できます。



ランダムなサンプルによると、解析の品質は実際のデータで62%でした。 評価のために、住所が完全に認識されるか(アパートまで)認識されないかが考えられました。 ハーフトーンなし。



エラー分布は次のとおりです。



どのような結論を導き出すことができますか?



私のように、低品質の解析と低速が必要な場合は、それを使用できます。



認識の精度を大幅に向上させる必要がある場合は、あいまい検索を導入してみてください。 さらに、一般的な略語のリストを追加することにより、正常に認識された住所の割合を引き上げることもできます。



パフォーマンスは別の歌であり、初歩的および準最適な実装を考えると、取り組むこともできます。 ここでの最初の候補は、スマートスペースブレイクです。



しかし、これはまったく別の話です。



ソースコードはこちらからダウンロードできます: https : //yadi.sk/d/muzi9b6qZ8DWh

38および78の地域にある家でのMS SQLデータベースのテストは、 https//yadi.sk/d/ERXyDXv7Z8Dabから取得できます



All Articles