133

問題: SQL Server 2005 に変換された Access データベースの住所フィールドがあります。このフィールドにはすべてが 1 つのフィールドに含まれています。住所の個々のセクションを、正規化されたテーブルの適切なフィールドに解析する必要があります。約 4,000 レコードに対してこれを行う必要があり、繰り返し可能である必要があります。

仮定:

  1. 米国内の住所を想定する (今のところ)

  2. 入力文字列には、宛先 (宛先の人物) および/または 2 番目の番地 (すなわちスイート B) が含まれることがあると想定します。

  3. 状態は省略される場合があります

  4. 郵便番号は、標準の 5 桁または zip+4 です。

  5. 場合によってはタイプミスがあります

更新: 提起された質問に答えて、標準は普遍的に守られていませんでした。ジオコードだけでなく、個々の値を保存する必要があり、エラーはタイプミスを意味します(上記で修正)

サンプルデータ:

  • AP Croll & Son 2299 Lewes-Georgetown Hwy, Georgetown, DE 19947

  • 11522 ショーニー ロード、グリーンウッド DE 19950

  • 144 Kings Highway, SW Dover, DE 19901

  • 統合された定数。サービス 2 Penns Way Suite 405 New Castle, DE 19720

  • Humes Realty 33 Bridle Ridge Court, Lewes, DE 19958

  • Nichols Excavation 2742 Pulaski Hwy Newark, DE 19711

  • 2284 Bryn Zion Road、スマーナ、DE 19904

  • VEI Dover Crossroads, LLC 1500 Serpentine Road, Suite 100 Baltimore MD 21

  • 580 North Dupont Highway ドーバー、DE 19901

  • 私書箱 778 ドーバー、DE 19903

4

24 に答える 24

119

私はこの種の解析について多くの作業を行ってきました。エラーがあるため、100% の精度を得ることはできませんが、ほとんどの方法でそこに到達するためにできることがいくつかあり、視覚的な BS テストを実行します。ここでは、一般的な方法について説明します。これはコードではありません。これを書くのはかなり学問的であり、奇妙さはなく、文字列処理がたくさんあるだけです。

(いくつかのサンプル データを投稿したので、いくつかのマイナーな変更を加えました)

  1. 後方作業。末尾近くにある郵便番号から開始し、XXXXX または XXXXX-XXXX の 2 つの既知の形式のいずれかで入力します。これが表示されない場合は、以下の都市、州の部分にいると想定できます。
  2. zip の前の次は状態で、2 文字形式または単語のいずれかになります。これらも何になるかはご存じのとおり、わずか 50 個しかありません。また、スペルミスを補うために単語を音声化することもできます。
  3. その前は都市で、おそらく州と同じ線上にあります。郵便番号データベースを使用して、郵便番号に基づいて都市と州を確認するか、少なくとも BS 検出器として使用できます。
  4. 番地は通常、1 行または 2 行です。2 行目は通常、部屋番号がある場合は部屋番号になりますが、私書箱の場合もあります。
  5. 1 行目または 2 行目の名前を検出することはほぼ不可能ですが、先頭に数字が付けられていない場合 (または、先頭に「attn:」または「attention to:」が付けられている場合)、次のようなヒントが得られます。それが名前か住所行か。

これが多少役立つことを願っています。

于 2008-08-19T15:52:05.397 に答える
92

問題をアウトソーシングするのが最善の策だと思います。Google (または Yahoo) のジオコーダーに送信してください。ジオコーダーは、緯度/経度 (ここでは重要ではありません) だけでなく、送信しなかったフィールド (ZIP+4 と郡を含む) が入力された、住所の豊富な解析も返します。

たとえば、「1600 Amphitheatre Parkway, Mountain View, CA」を解析すると、

{
  "name": "1600 Amphitheatre Parkway, Mountain View, CA, USA",
  "Status": {
    "code": 200,
    "request": "geocode"
  },
  "Placemark": [
    {
      "address": "1600 Amphitheatre Pkwy, Mountain View, CA 94043, USA",
      "AddressDetails": {
        "Country": {
          "CountryNameCode": "US",
          "AdministrativeArea": {
            "AdministrativeAreaName": "CA",
            "SubAdministrativeArea": {
              "SubAdministrativeAreaName": "Santa Clara",
              "Locality": {
                "LocalityName": "Mountain View",
                "Thoroughfare": {
                  "ThoroughfareName": "1600 Amphitheatre Pkwy"
                },
                "PostalCode": {
                  "PostalCodeNumber": "94043"
                }
              }
            }
          }
        },
        "Accuracy": 8
      },
      "Point": {
        "coordinates": [-122.083739, 37.423021, 0]
      }
    }
  ]
}

これで解析可能になりました!

于 2008-08-19T20:30:52.027 に答える
25

元のポスターはおそらくずっと前に進んでいますが、geocoder.usで使用されている Perl のGeo::StreetAddress:USモジュールを C# に移植することに挑戦し、CodePlex にダンプしました。将来この質問に出くわす人は、便利だと思います:

米国住所パーサー

プロジェクトのホームページで、私はその (非常に現実的な) 制限について話そうとしています。有効な住所の USPS データベースに裏打ちされていないため、解析があいまいになる可能性があり、特定の住所の有効性を確認したり否定したりすることはできません。文字列からデータを取り出そうとするだけです。

これは、主に適切なフィールドで一連のデータを取得する必要がある場合、またはデータ入力へのショートカットを提供したい場合 (ユーザーが複数のフィールド間でタブ移動するのではなく、アドレスをテキスト ボックスに貼り付けられるようにする場合) を対象としています。アドレスの配信可能性を検証するためのものではありません。

番地より上の部分は解析しようとはしませんが、正規表現をいじってかなり近いものを取得することもできます。

于 2011-12-24T21:38:50.550 に答える
17

私は過去にこれをやったことがあります。

手動で行うか (ユーザーがすばやく行うのに役立つ素敵な GUI を作成する)、自動化して最近の住所データベースと照合し (購入する必要があります)、手動でエラーを処理します。

手動処理​​にはそれぞれ約 10 秒かかります。つまり、1 時間あたり 3600/10 = 360 処理できるため、4000 には約 11 ~ 12 時間かかります。これにより、高い精度が得られます。

自動化するには、最近の米国住所データベースが必要であり、それに対してルールを微調整します。正規表現に夢中にならないことをお勧めします(長期的に維持するのは難しいため、多くの例外があります)。データベースに対して 90% の一致を求め、残りは手動で行います。

http://pe.usps.gov/cpim/ftp/pubs/Pub28/pub28.pdfで Postal Addressing Standards (USPS) のコピーを入手してください。130 ページ以上あることに注意してください。それを実装する正規表現は厄介です。

国際住所の場合、すべての賭けは無効になります。米国を拠点とする労働者は検証できません。

または、データ サービスを使用します。ただし、推奨事項はありません。

さらに、郵便物を郵送するときは (それが目的ですよね?)、封筒の正しい場所に「住所訂正依頼」と記入し、データベースを更新してください。(実際にメールを仕分けするフロントデスク担当者向けの簡単な GUI を作成しました)

最後に、データをスクラブしたら、重複を探します。

于 2008-08-19T16:04:45.340 に答える
14

ここでのアドバイスの後、VB で次の関数を考案しました。これは、常に完璧ではありませんが (会社名とスイート ラインが指定されている場合は、スイートと都市を組み合わせて) 使用可能なデータを作成します。私自身のルールを破ったことなどについて、気軽にコメント/リファクタリング/怒鳴ってください。

Public Function parseAddress(ByVal input As String) As Collection
    input = input.Replace(",", "")
    input = input.Replace("  ", " ")
    Dim splitString() As String = Split(input)
    Dim streetMarker() As String = New String() {"street", "st", "st.", "avenue", "ave", "ave.", "blvd", "blvd.", "highway", "hwy", "hwy.", "box", "road", "rd", "rd.", "lane", "ln", "ln.", "circle", "circ", "circ.", "court", "ct", "ct."}
    Dim address1 As String
    Dim address2 As String = ""
    Dim city As String
    Dim state As String
    Dim zip As String
    Dim streetMarkerIndex As Integer

    zip = splitString(splitString.Length - 1).ToString()
    state = splitString(splitString.Length - 2).ToString()
    streetMarkerIndex = getLastIndexOf(splitString, streetMarker) + 1
    Dim sb As New StringBuilder

    For counter As Integer = streetMarkerIndex To splitString.Length - 3
        sb.Append(splitString(counter) + " ")
    Next counter
    city = RTrim(sb.ToString())
    Dim addressIndex As Integer = 0

    For counter As Integer = 0 To streetMarkerIndex
        If IsNumeric(splitString(counter)) _
            Or splitString(counter).ToString.ToLower = "po" _
            Or splitString(counter).ToString().ToLower().Replace(".", "") = "po" Then
                addressIndex = counter
            Exit For
        End If
    Next counter

    sb = New StringBuilder
    For counter As Integer = addressIndex To streetMarkerIndex - 1
        sb.Append(splitString(counter) + " ")
    Next counter

    address1 = RTrim(sb.ToString())

    sb = New StringBuilder

    If addressIndex = 0 Then
        If splitString(splitString.Length - 2).ToString() <> splitString(streetMarkerIndex + 1) Then
            For counter As Integer = streetMarkerIndex To splitString.Length - 2
                sb.Append(splitString(counter) + " ")
            Next counter
        End If
    Else
        For counter As Integer = 0 To addressIndex - 1
            sb.Append(splitString(counter) + " ")
        Next counter
    End If
    address2 = RTrim(sb.ToString())

    Dim output As New Collection
    output.Add(address1, "Address1")
    output.Add(address2, "Address2")
    output.Add(city, "City")
    output.Add(state, "State")
    output.Add(zip, "Zip")
    Return output
End Function

Private Function getLastIndexOf(ByVal sArray As String(), ByVal checkArray As String()) As Integer
    Dim sourceIndex As Integer = 0
    Dim outputIndex As Integer = 0
    For Each item As String In checkArray
        For Each source As String In sArray
            If source.ToLower = item.ToLower Then
                outputIndex = sourceIndex
                If item.ToLower = "box" Then
                    outputIndex = outputIndex + 1
                End If
            End If
            sourceIndex = sourceIndex + 1
        Next
        sourceIndex = 0
    Next
    Return outputIndex
End Function

parseAddress関数「AP Croll & Son 2299 Lewes-Georgetown Hwy, Georgetown, DE 19947」を渡すと、次のように返されます。

2299 Lewes-Georgetown Hwy
A. P. Croll & Son  
Georgetown
DE
19947
于 2008-08-19T19:52:34.210 に答える
13

私はアドレス処理の分野で約 5 年間働いていますが、特効薬はありません。正しい解決策は、データの値によって異なります。あまり価値がない場合は、他の回答が示唆するように、パーサーに通してください。少しでも価値がある場合は、パーサーのすべての結果を人間が評価/修正する必要があります。完全に自動化された反復可能なソリューションを探している場合は、おそらく Group1 や Trillium などのアドレス修正ベンダーに相談することをお勧めします。

于 2008-08-19T17:08:25.697 に答える
8

これでは問題は解決しませんが、これらの住所の緯度/経度データのみが必要な場合、Google Maps API はフォーマットされていない住所を適切に解析します。

良い提案です。別の方法として、各住所に対して CURL リクエストを実行して Google マップに送信すると、適切な形式の住所が返されます。そこから、思う存分正規表現できます。

于 2008-08-19T16:51:08.913 に答える
7

+1 James A. Rosen の提案されたソリューションは、私にとってはうまく機能しましたが、完全主義者にとっては、このサイトは魅力的な読み物であり、世界中のアドレスを文書化する際に私が見た中で最高の試みです: http://www.columbia.edu/kermit /postal.html

于 2010-09-17T20:05:38.043 に答える
6

住所の記録方法に基準はありますか? 例えば:

  1. street1 と street2 と city と state と zip を区切るコンマまたは改行は常にありますか?
  2. 住所の種類 (道路、通り、大通りなど) は常にスペルアウトされていますか? いつも短縮?それぞれのいくつか?
  3. 「エラー」を定義します。

私の一般的な答えは一連の正規表現ですが、これの複雑さは答えによって異なります。また、一貫性がまったくない場合は、正規表現で部分的な成功しか達成できない可能性があり (つまり、郵便番号と州を除外する)、残りを手動で行う必要があります (または、少なくとも残りの部分を非常に慎重に実行する必要があります)。エラーを見つけるために慎重に)。

于 2008-08-19T15:40:18.917 に答える
6

サンプルデータの別のリクエスト。

言及されているように、私はzipから逆方向に作業します。

zip を取得したら、zip データベースにクエリを実行し、結果を保存して、それらと zip を文字列から削除します。

そうすると、アドレスが混乱します。ほとんどの (すべて?) アドレスは数字で始まるため、残りの文字列で最初に出現する数字を見つけ、それから文字列の (新しい) 末尾まですべてを取得します。それがあなたの住所になります。その番号の左側にあるものは、おそらく宛先です。

これで、City、State、および Zip がテーブルに格納され、場合によっては 2 つの文字列 (addressee と address) が格納されているはずです。住所については、「Suite」または「Apt」の有無を確認してください。など、それを 2 つの値に分割します (アドレス行 1 & 2)。

宛先の場合、その文字列の最後の単語を姓としてパントして取得し、残りを名のフィールドに入力します。そうしたくない場合は、最初に敬称 (Mr.、Ms.、Dr. など) を確認し、スペースの数に基づいて名前がどのようになっているのかを推測する必要があります。作り物。

100% の精度で解析できる方法はないと思います。

于 2008-08-19T16:03:28.387 に答える
6

www.address-parser.comを試してください。オンラインでテストできるWebサービスを使用しています

于 2010-02-08T14:53:10.687 に答える
5

サンプルデータに基づく:

  1. 文字列の最後から始めます。郵便番号を解析します (いずれかの形式)。最後から最初のスペースまで読み取ります。郵便番号が見つからない場合はエラー。

  2. スペースと特殊文字 (カンマ) の末尾をトリミングします。

  3. 次に State に移動し、再びスペースを区切り文字として使用します。おそらく、ルックアップ リストを使用して、2 文字の州コードと完全な州名を検証します。有効な状態が見つからない場合はエラー。

  4. 末尾のスペースとカンマを再度削除します。

  5. City はややこしくなります。実際にはここでコンマを使用しますが、City でデータが多すぎるというリスクがあります。コンマまたは行頭を探します。

  6. 文字列にまだ文字が残っている場合は、そのすべてをアドレス フィールドに押し込みます。

これは完璧ではありませんが、かなり良い出発点になるはずです。

于 2008-08-19T15:55:41.303 に答える
4

人間が入力したデータの場合、例外を回避するためのコーディングに多くの時間を費やすことになります。

試す:

  1. 郵便番号を抽出する正規表現

  2. 正しい住所を取得するための郵便番号検索 (適切な政府 DB 経由)

  3. 新しいデータが古いデータと一致することをインターンに手動で確認してもらいます

于 2008-08-19T16:47:16.677 に答える
3

これでは問題は解決しませんが、これらの住所の緯度/経度データのみが必要な場合、Google Maps API はフォーマットされていない住所を適切に解析します。

于 2008-08-19T15:40:15.593 に答える
3

これは要チェックかも!! http://jgeocoder.sourceforge.net/parser.html 私にとって魅力のように働きました。

于 2011-10-15T01:23:49.240 に答える
3

RecogniContact は、米国およびヨーロッパの住所を解析する Windows COM オブジェクトです。http://www.loquisoft.com/index.php?page=8ですぐに試すことができ ます。

于 2009-05-12T14:07:31.417 に答える
3

このタイプの問題は、データの根底にあるあいまいさのために解決が困難です。

これは、住所の多くの有効な組み合わせを解析するために正規表現に基づいて再帰降下文法ツリーを定義する Perl ベースのソリューションです: http://search.cpan.org/~kimryan/Lingua-EN-AddressParse-1.20/lib/Lingua /EN/AddressParse.pm . これには、次のような住所内のサブ プロパティが含まれます。12 1st Avenue N Suite # 2 Somewhere CA 12345 USA

上記のhttp://search.cpan.org/~timb/Geo-StreetAddress-US-1.03/US.pmに似ていますが、英国、オーストラリア、カナダ。

サンプル アドレスの 1 つの出力を次に示します。「AP Croll & Son 2299 Lewes-Georgetown Hwy, Georgetown, DE 19947」から名前セクションを削除して、「2299 Lewes-Georgetown Hwy, Georgetown, DE 19947」に減らす必要があることに注意してください。これは、文字列で見つかった最初の数値までのすべてのデータを削除することで簡単に実現できます。

Non matching part       ''
Error                   '0'
Error descriptions      ''
Case all                '2299 Lewes-Georgetown Hwy Georgetown DE 19947'
COMPONENTS              ''
country                 ''
po_box_type             ''
post_box                ''
post_code               '19947'
pre_cursor              ''
property_identifier     '2299'
property_name           ''
road_box                ''
street                  'Lewes-Georgetown'
street_direction        ''
street_type             'Hwy'
sub_property_identifier ''
subcountry              'DE'
suburb                  'Georgetown'
于 2014-10-01T10:59:07.187 に答える
2

Google API の使用

$d=str_replace(" ", "+", $address_url);
$completeurl ="http://maps.googleapis.com/maps/api/geocode/xml?address=".$d."&sensor=true"; 
$phpobject = simplexml_load_file($completeurl);
print_r($phpobject);
于 2012-10-09T09:47:20.883 に答える
2

Ruby や Rails の開発者向けに、street_addressという便利な gem があります。私は自分のプロジェクトの 1 つでこれを使用しており、必要な作業を行います。

私が抱えていた唯一の問題は、住所がこの形式のP. O. Box 1410 Durham, NC 27702 場合は常に nil を返したため、「PO Box」を '' に置き換える必要があり、その後は解析できました。

于 2013-11-01T21:08:45.700 に答える
2

Word ではエラーが発生する可能性があるため、LCS アルゴリズムと組み合わせた SOUNDEX を使用して文字列を比較することを検討してください。これは非常に役立ちます。

于 2011-01-22T12:49:26.720 に答える
1

これがどのように実現可能かはわかりませんが、これが言及されているのを見たことがないので、先に進んでこれを提案すると思いました:

あなたが厳密に米国にいるなら...すべての郵便番号、州、都市、通りの巨大なデータベースを入手してください。次に、アドレスでこれらを探します。たとえば、見つけた都市が見つけた州に存在するかどうかをテストするか、見つけた通りが見つけた都市に存在するかどうかを確認することで、見つけたものを検証できます。そうでない場合は、ジョンはジョンの街ではなく、受取人の名前である可能性があります...基本的に、可能な限り多くの情報を入手し、それに対して住所を確認します。極端な例は、米国内のすべての住所のリストを取得し、各住所に最も関連性の高い住所を見つけることです...

于 2010-10-01T02:50:01.567 に答える
1

郵便番号を指定すると、その郵便番号の通り名のリストが得られるデータ サービスがあります。

正規表現を使用して Zip または City State を抽出します - 正しいものを見つけるか、エラーの場合は両方を取得します。データ ソースから通りのリストを取得する 都市と州を修正し、次に通りの住所を修正します。有効な住所 1、市区町村、都道府県、郵便番号を取得したら、住所 2..3 について推測できます。

于 2008-08-19T15:52:48.313 に答える
1

perl Geo::StreetAddress::US パッケージの JavaScript ポートがあります: https://github.com/hassansin/parse-address。これは正規表現ベースであり、かなりうまく機能します。

于 2014-12-13T01:33:31.090 に答える