Извлечь адрес из строки

Предположим, у меня есть эта строка:

<div>john doe is nice guy btw 8240 E. Marblehead Way 92808 is also</div> 

или эта строка:

 <div>sky being blue? in the world is true? 024 Brea Mall Brea, California 92821 jackfroast nipping on the firehead</div> 

Как я могу извлечь адрес из одной из этих строк? Это связано с каким-то регулярным выражением, верно?

Я пробовал искать в Интернете решение с использованием JavaScript или PHP, но безрезультатно. И никакое другое сообщение здесь о переполнении стека (насколько мне известно) не дает решения, которое использует jQuery и / или Javascript и / или PHP. (Ближайшим является используемый в Parse Street Address, City, State, Zip из строки , в которой нет ни одного кода в потоке об извлечении почтового кода из строки.

Может кто-нибудь указать мне в правильном направлении? Как я могу сделать это в jQuery или JavaScript или PHP?

Пробовал это по двенадцати различным строкам, которые были похожи на ваши, и это сработало отлично:

 function str_to_address($context) { $context_parts = array_reverse(explode(" ", $context)); $zipKey = ""; foreach($context_parts as $key=>$str) { if(strlen($str)===5 && is_numeric($str)) { $zipKey = $key; break; } } $context_parts_cleaned = array_slice($context_parts, $zipKey); $context_parts_normalized = array_reverse($context_parts_cleaned); $houseNumberKey = ""; foreach($context_parts_normalized as $key=>$str) { if(strlen($str)>1 && strlen($str)<6 && is_numeric($str)) { $houseNumberKey = $key; break; } } $address_parts = array_slice($context_parts_normalized, $houseNumberKey); $string = implode(' ', $address_parts); return $string; } 

Это предполагает номер дома, по крайней мере, двух цифр и не более шести. Это также предполагает, что почтовый индекс не находится в «расширенной» форме (например, 12345-6789). Однако это может быть легко изменено для соответствия этому формату (здесь будет использоваться правильный пример: (\d{5}-\d{4}) .

Но использование regex для анализа данных, введенных пользователем … Не очень хорошая идея здесь, потому что мы просто не знаем, что пользователь собирается вводить, потому что были (как можно предположить) отсутствие проверок.

Просматривая код и логику, начиная с создания массива из контекста и захвата zip:

 // split the context (for example, a sentence) into an array, // so we can loop through it. // we reverse the array, as we're going to grab the zip first. // why? we KNOW the zip is 5 characters long*. $context_parts = array_reverse(explode(" ", $context)); // we're going to store the array index of the zip code for later use $zipKey = ""; // foreach iterates over an object given the params, // in this case it's like doing... // for each value of $context_parts ($str), and each index ($key) foreach($context_parts as $key=>$str) { // if $str is 5 chars long, and numeric... // an incredibly lazy check for a zip code... if(strlen($str)===5 && is_numeric($str)) { $zipKey = $key; // we have what we want, so we can leave the loop with break break; } } 

Сделайте некоторые уборка, чтобы у нас был лучший объект, чтобы украсить номер дома от

 // remove junk from $context_array, since we don't // need stuff after the zip $context_parts_cleaned = array_slice($context_parts, $zipKey); // since the house number comes first, let's go back to the start $context_parts_normalized = array_reverse($context_parts_cleaned); 

И тогда давайте возьмем номер дома, используя ту же основную логику, что и почтовый индекс:

 $houseNumberKey = ""; foreach($context_parts_normalized as $key=>$str) { if(strlen($str)>1 && strlen($str)<6 && is_numeric($str)) { $houseNumberKey = $key; break; } } // we probably have the parts we for the address. // let's do some more cleaning $address_parts = array_slice($context_parts_normalized, $houseNumberKey); // and build the string again, from the address $string = implode(' ', $address_parts); // and return the string return $string; 

Регулярные выражения используются для тестирования шаблонов . Вам нужно знать, какой шаблон вы ищете. Из двух приведенных вами примеров я хотел бы найти номер, а затем текст, заканчивающийся пятизначным числом.

Все адреса должны быть в этом формате. Вы не можете магически извлекать адреса из строки.

Если все ваши адреса начинаются и заканчиваются номерами, вы можете использовать это регулярное выражение для извлечения необходимых данных:

 /[0-9].+[0-9]/gi 

Пример Javascript:

 "<div>john doe is nice guy btw 8240 E. Marblehead Way 92808 is also</div>".match(/[0-9].+[0-9]/gi) // ["8240 E. Marblehead Way 92808"] "<div>sky being blue? in the world is true? 024 Brea Mall Brea, California 92821 jackfroast nipping on the firehead</div>".match(/[0-9].+[0-9]/gi) // ["024 Brea Mall Brea, California 92821"] 

В новом примере, который содержит номер телефона, вы можете:

 /[0-9].*[0-9]/gi 

Пример Javascript:

 "john doe 7143138656 is 8240 e marblehead way 92808".match(/[0-9].*[0-9]/gi) // ["7143138656 is 8240 e marblehead way 92808"] 

Но это поможет вам, только если у вас есть информация о матче в строке. Если вам действительно нужен мощный адресный адрес, вам нужно идти вперед и создавать мощный анализ.

Вы можете начать поиск в тексте для целевых ключевых слов, затем отфильтровать параграф, чтобы затем удалить информацию, которую вы ищете.

Это непростой вопрос, но это можно сделать, вы можете использовать более одного регулярного выражения для некоторых совпадений, но если адрес не имеет шаблона, регулярное выражение будет бесполезным, в это время вам нужно будет изменить свой подход.

Это обычная «ошибка», чтобы попытаться разобрать все с помощью регулярных выражений из-за удобства. Однако регулярные выражения не являются ответом на все. В этом случае не похоже, что вы ищете регулярные шаблоны в тексте, а скорее «естественные» выражения, которые кто-то писал бы, как будто они разговаривают с вами. Это естественное выражение не обязательно будет следовать какой-либо согласованной схеме вообще. Некоторые люди сначала вводят номера апплетов, затем строят номер, некоторые люди покидают город и пропускают почтовый индекс, некоторые люди могут поместить город, штат, страну THEN zip. Невозможно перечислить все возможные шаблоны регулярных выражений, которые кто-то может приготовить с адресом.

Для адресов естественного языка я бы забыл определение адресов регулярных выражений и перешел к алгоритму синтаксического анализа с учетом состояния.

  1. Я бы начал с чтения текста слева направо (по крайней мере на английском языке) по одному слову за раз. На каждом слове вы делаете один логический тест: «Может ли это слово быть началом адреса?». Я бы предположил, что это номер для номера здания или числа appt / unit / box (так что «Box XXX», «PO BOX XXX», «PO XXX», «Unit XXX», «#XXX» или любое число меньше чем 6 цифр в длину). Хотя я не знаю, что это правда, я никогда не видел северо-американского здания с номером 7 цифр, что является минимальным для телефона. Поэтому я подозреваю, что вы можете легко сортировать номера телефонов и номера зданий. Этот тест «start of address» может быть набором совпадений регулярных выражений, но мы не сопоставляем весь адрес, просто проверяем слова или фразы, которые запускают адрес. Я бы даже сказал, что это будет проще без соответствия регулярных выражений .

  2. После того, как вы обнаружили начало адреса, вы создаете «объект состояния синтаксического анализа адреса» (некоторый класс, который вы используете для хранения адреса в качестве продолжения разбора и отслеживания того, что у вас есть до сих пор, и того, что вы ожидаете в дальнейшем). Теперь вы можете продолжить выполнение предложения и продолжить добавление к объекту состояния парсера. Следуя номеру здания, я, вероятно, ожидаю название улицы или указатель направления (NEWS NE. NW. SE. SW.). Если ни один из них не прекратит разбор вашего адреса и не примет неверный или неполный адрес, продолжайте искать новые начальные слова адреса. В противном случае добавьте название улицы и / или указатели направления в дерево разбора и продолжайте движение!

  3. Все, что следует за названием улицы, может быть бесконечно переменным. Некоторые пользователи могут просто остановиться по номеру здания и названию улицы (при условии, что их местный город / регион / страна). В противном случае вы, вероятно, ищете либо название города, либо почтовый индекс / почтовый индекс. Если найдено, добавьте в свой адрес объект анализа, если не предполагаете неполный адрес (заполните информацию о местоположении пользователя по умолчанию?) Или неверный адрес (игнорируйте и продолжаете искать другой старт адреса?).

В конечном итоге этот подход может быть одним довольно простым методом JavaScript, возможно, с несколькими сотнями строк кода (я не парень PHP, но я предполагаю, что это будет похоже). Если бы вы попытались перечислить все возможные шаблоны регулярных выражений, кто-то мог бы создать адрес с вами, у вас было бы сотня из них одна, и это все равно было бы ненадежным! (Возможно, слишком медленно, если вы пытаетесь сопоставить сотни шаблонов регулярных выражений).

Мое мышление говорит, что вам нужно что-то сказать вашему коду, который «здесь должен быть здесь, – это адрес, а остальное – простой текст». Для этого либо вы создаете массив адресов, либо сохраняете адреса в базе данных, откуда вы можете сравнить их с вашими вставленными значениями

Мне повезло с помощью Google Geocode API . Трудно попытаться придумать все возможные способы ввода адресной строки.

Недавно мне пришлось извлечь часть адреса из одной строки для сайта недвижимости, и я обнаружил, что лучшим вариантом было использование API геокодирования google. Это позволило мне получить улицу, город, штат, почтовый индекс, широту, долготу и многое другое для каждого введенного адреса.

Я нашел отличное руководство по настройке API-интерфейса google geocode (PHP) здесь: http://www.andrew-kirkpatrick.com/2011/10/google-geocoding-api-with-php/

Лучшая часть, она даже работает с названиями мест. Таким образом, поиск «UCLA» или «Штаб-квартиры Apple» предоставит вам все части адреса, которые могут вам понадобиться.