簡體   English   中英

使用RegEx從PHP中的字符串中提取地址

[英]Extract Address from String in PHP with RegEx

我的問題

我試圖在美國眾議院網站上搜尋各個鏈接,以查找所有列出的個人的華盛頓地址。 問題在於華盛頓地址的格式不時變化。 有時會有子彈,煙斗,新線和破折號,很難匹配。


我正在嘗試抓取許多頁面以檢索基本相似的地址:

忽略特殊的空格。 只是為了顯示字符串部分的相似性

1433 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. (line return)
    Washington, DC 20515
    8293 Longworth House Office Building • Washington DC • 20515
    8293 Longworth House Office Building | Washington DC | 20515

這些中的每一個將單獨返回,並被成噸的其他文本和html標簽包圍。 這些地址甚至可能在地址本身中包含<br>或<br/>。

我想做的是從源字符串中捕獲第一個匹配項,並將其設置為變量的值。 根據我的理解,最好使用正則表達式來解決。

更新:

在了解了這些天可能出現的各種方式之后,我決定最好用不太嚴格的表達方式。 這些地址顯示有項目符號,豎線和換行符。 傳達以下內容的表達式也許是最好的:

[數字] [任何] [“華盛頓”] [任何] [DC | DC] [任何] [五個數字]

顯然那太松了。 當我僅對允許包含任何字符的字符感興趣時, 任何內容塊都會引入段落。

到目前為止,我未能匹配以下內容(這些只是其中的一部分)

編輯 :似乎在第一組數字和“華盛頓”之間的[任何數據]必須稍微受限一些才能正常工作。 [anything]節不應包含任何數字,因為數字是我們用來界定地址之一開頭的數字。 這適用於您提供給我們的三個網站。

我說最好的第一步是剝離所有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/>";
}

這適用於您提供的三個示例, $results[0]應該包含找到的每個地址。

但是,例如,如果地址中包含“ 2號公寓”之類的地址,這將不起作用,因為它假定最接近“華盛頓特區”的數字標記了地址的開頭。

以下腳本匹配每個測試用例:

<?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/>";
    }

有一些工具和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。 我鼓勵您環顧四周,以找到最適合您的選項...我保證,這比編寫您自己的正則表達式要好(提示:其代碼背后的代碼並非基於正則表達式)。

此正則表達式對輸入字符串可以包含的內容采取更靈活的方法。 “華盛頓特區”部分尚未硬編碼到其中。 地址的不同部分分別捕獲,整個地址將在$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);

編輯:

在查看了您提到的站點之后,我認為以下方法應該可行。 假設您具有在名為$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修飾符使點與換行符匹配,並使正則表達式不區分大小寫。

您的問題對我來說不是很清楚,但是如果我對您的理解正確,我想您可以使用DOM解析器來匹配p標簽,然后檢查其中是否有單詞“ Washington”或電話號碼是否與Washington匹配區域。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM