2

私の問題

米国下院のサイトにある個々のリンクをクロールして、リストされているすべての個人のワシントンの住所を見つけようとしています。問題は、ワシントンの住所の形式が時々変わることです。弾丸、パイプ、新しいライン、ブレークタグがあり、一致させるのが難しい場合があります。


多くのページをクロールして、ほぼ類似しているアドレスを取得しようとしています。

固有の空白は無視してください。文字列部分の類似性を示すだけです

    1433 ロングワースハウスオフィスビルワシントンDC 20515
     332キャノンHOBワシントンDC20515
    1641 LONGWORTH HOUSE OFFICE BUILDING WASHINGTON、DC 20515
    1238キャノンHOB(ラインリターン)
    ワシントンDC20515
    8293ロングワースハウスオフィスビル•ワシントンDC•20515
    8293ロングワースハウスオフィスビル| ワシントンDC| 20515

これらはそれぞれ、他の大量のテキストタグとhtmlタグに囲まれて個別に戻ってきます。アドレスには、アドレス自体に<br>または<br/>が含まれる場合もあります。

私がやりたいのは、ソース文字列から最初の一致をキャプチャし、それを変数の値として設定することです。私の理解では、これは正規表現でアプローチするのが最善です。

アップデート:

最近のさまざまな表現方法について詳しく学んだ結果、厳密ではない表現が最適であると判断しました。これらのアドレスは、箇条書き、パイプ、および改行で表示されています。おそらく、次のことを伝える表現が最適でしょう。

[数字][何でも]["ワシントン"][何でも][DC|DC][何でも][5つの数字]

どうやらそれはあまりにも緩いです。何でもブロックが段落をもたらしていたのは、私が何でも数文字を許可することに単に興味があるときでした。

これまでのところ、以下にあるアドレスの照合に失敗しました(これらは多くのアドレスのほんの一部です)

4

5 に答える 5

2

編集: 最初の数値セットと「ワシントン」の間の [何でも] データが適切に機能するには、もう少し制限を加える必要があるようです。[anything] セクションには、数字を含めないでください。数字は、アドレスの開始を区切るために使用するものです。これは、提供された 3 つの Web サイトで機能します。

最初の最善のステップは、すべての HTML タグを取り除き、「 」文字エンティティを置き換えることだと思います。

$input = strip_tags($input);
$input = preg_replace("/&nbsp;/"," ",$input);

次に、アドレスが指定した形式と一致する (近い) 場合は、次のようにします。

$results= array();
preg_match("/[0-9]+\s+[^0-9]*?\s+washington,?\s*D\.?C\.?[^0-9]+[0-9]{5}/si",$input,$results);
foreach($result[0] as $addr){
    echo "$addr<br/>";
}

これは、提供した 3 つの例で機能し、$results[0]見つかった各アドレスが含まれている必要があります。

ただし、たとえば、住所に「Apartment #2」などがある場合、これは機能しません。これは、「Washington, DC」に最も近い番号が住所の開始を示すと見なされるためです。

次のスクリプトは、各テスト ケースに一致します。

<?php
    $input = "
        1433&nbsp;Longworth House Office Building Washington,  D.C. 20515
         332 Cannon HOB                      Washington   DC   20515
        1641 LONGWORTH HOUSE OFFICE BUILDING WASHINGTON,  DC   20515
        1238 Cannon H.O.B.
        Washington, DC 20515
        8293 Longworth House Office Building • Washington DC • 20515
        8293 Longworth House Office Building | Washington DC | 20515
    ";
    $input = strip_tags($input);
    $input = preg_replace("/&nbsp;/"," ",$input);

    $results= array();
    preg_match_all("/[0-9]+\s+[^0-9]*?washington,?\s*D\.?C\.?[^0-9]*?[0-9]{5}/si",$input,$results);
    foreach($results[0] as $addr){
        echo "$addr<br/>";
    }
于 2009-12-26T02:49:54.987 に答える
1

この正規表現は、入力文字列に含めることができるものに対して、より柔軟なアプローチを取ります。「ワシントンDC」の部分はハードコーディングされていません。アドレスのさまざまな部分が個別にキャプチャされ、アドレス全体がでキャプチャされ$matches[0]ます。

$input = strip_tags($input);
preg_match('/
(\d++)    # Number (one or more digits) -> $matches[1]
\s++      # Whitespace
([^,]++), # Building + City (everything up until a comma) -> $matches[2]
\s++      # Whitespace
(\S++)    # "DC" part (anything but whitespace) -> $matches[3]
\s++      # Whitespace
(\d++)    # Number (one or more digits) -> $matches[4]
/x', $input, $matches);
于 2009-12-26T06:03:10.180 に答える
1

これを行うために構築されたツールと API があります。たとえば、SmartyStreets の LiveAddress は非常にうまく機能します。私はそれを開発するのを手伝ったので、あなたの痛みの一部を感じます...これはあなたが質問で提供したサンプルからの出力です:

ここに画像の説明を入力

CSV 出力は次のとおりです。

ID,Start,End,Segment,Verified,Candidate,Firm,FirstLine,SecondLine,LastLine,City,State,ZIPCode,County,DpvFootnotes,DeliveryPointBarcode,Active,Vacant,CMRA,MatchCode,Latitude,Longitude,Precision,RDI,RecordType,BuildingDefaultIndicator,CongressionalDistrict,Footnotes
1,4,69,"1433&nbsp;Longworth House Office Building Washington, D.C. 20515",Y,0,,1433 Longworth House Office Building Washington D,,Washington DC 20515-0001,Washington,DC,20515,District of Columbia,AAU1,205150001330,,,,Y,38.89106,-77.01132,Zip5,Residential,S,,AL,Q#X#
2,75,134,332 Cannon HOB Washington DC 20515,Y,0,,332 Cannon Hob,,Washington DC 20515-3226,Washington,DC,20515,District of Columbia,AAU1,205153226996,,,,Y,38.89106,-77.01132,Zip5,Residential,H,Y,AL,H#Q#
3,139,199,"1641 LONGWORTH HOUSE OFFICE BUILDING WASHINGTON, DC 20515",Y,0,,1641 Longworth House Office Building,,Washington DC 20515-0001,Washington,DC,20515,District of Columbia,AAU1,205150001411,,,,Y,38.89106,-77.01132,Zip5,Residential,S,,AL,Q#X#
4,204,247,"1238 Cannon H.O.B.
Washington, DC 20515",Y,0,,1238 Cannon H O B,,Washington DC 20515-0001,Washington,DC,20515,District of Columbia,AAU1,205150001385,,,,Y,38.89106,-77.01132,Zip5,Residential,S,,AL,Q#X#
5,252,316,8293 Longworth House Office Building • Washington DC • 20515,Y,0,,8293 Longworth House Office Building,,Washington DC 20515-0001,Washington,DC,20515,District of Columbia,AAU1,205150001934,,,,Y,38.89106,-77.01132,Zip5,Residential,S,,AL,Q#X#
6,321,381,8293 Longworth House Office Building | Washington DC | 20515,Y,0,,8293 Longworth House Office Building,,Washington DC 20515-0001,Washington,DC,20515,District of Columbia,AAU1,205150001934,,,,Y,38.89106,-77.01132,Zip5,Residential,S,,AL,Q#X#

約2秒かかりました。この API は、ある程度までは無料で使用できます。同様の API が他にもあるかもしれません。自分に最適なオプションを見つけるために、いろいろ調べてみることをお勧めします...自分で正規表現を書くよりも優れていることを保証します (ヒント: このコード ビハインドは正規表現に基づいていません)。

于 2013-06-13T20:51:48.897 に答える
1

編集:

あなたが言及したサイトを見た後、私は以下がうまくいくはずだと思います。という変数にクロールしたページのコンテンツがあると仮定すると$page、次を使用できます

$subject = strip_tags($page)

ページからすべての HTML マークアップを削除します。次に、正規表現を適用します

(\d+)\s*(.*?)\s*washington.{0,5}(DC|D.C.).{0,5}(\d{5})

RegexBuddyは、このために次のコードを生成します (私は PHP を知りません)。

if (preg_match('/(\d+)\s*(.*?)\s*washington.{0,5}(DC|D.C.).{0,5}(\d{5})/si', $subject, $regs)) {
    $result = $regs[0];
} else {
    $result = "";
}

$regs[1]次に、最初のキャプチャ括弧 (数字) の内容が含まれます。

/si修飾子を使用して、ドットを改行に一致させ、正規表現で大文字と小文字を区別しないようにすることに注意してください。

于 2009-12-26T08:33:13.620 に答える
0

あなたの質問は私にはあまり明確ではありませんが、私があなたを正しく理解していれば、DOMパーサーを使用してpタグを照合し、それらのいずれかに「ワシントン」という単語が含まれているかどうか、または電話番号がワシントンに一致するかどうかを確認できると思います.範囲。

于 2009-12-26T02:03:00.027 に答える