Статьи

Где ты?

Поскольку этот сайт имеет действительно глобальную аудиторию, вы, читатель, можете быть в любой точке мира. Если бы я спросил вас, где на Земле вы находитесь, вы могли бы добровольно назвать название города, штата или, может быть, просто страну, в которой вы находитесь. Ответ может быть неоднозначным — это Париж, Франция или Париж, Техас?

Современные геолокационные приложения используют широту и долготу для определения местоположения людей и мест с точностью до нескольких метров, но вряд ли вы ответите на вопрос с ними. Геолокация — то есть получение вашего местоположения с помощью GPS, триангуляции Wi-Fi или, возможно, с использованием вашего IP-адреса — все это очень хорошо, но иногда вам просто нужно спросить кого-то, где они находятся.

Задача состоит в том, чтобы сделать две вещи: определить, в каком месте вы могли бы говорить, устраните неоднозначность, если необходимо, и затем точно определите, где на Земле это находится.

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

Где на Земле идентификаторы (WOEID)

Я очень осторожно использовал фразу «где на Земле», поскольку существует база данных, в которой места идентифицируются не по названию, а по идентификаторам «Где на Земле» (WOEID). База данных WOEID была собрана и сделана свободно доступной для Yahoo !, а также используется Flickr и для географических тенденций в Twitter .

У каждой записи есть широта и долгота этого места, а также имена, которые им дали люди. Чтобы усложнить это, не всегда есть отношения один-к-одному. То, что я называю Брюсселем, вы можете назвать Брюсселем, в то время как жители с большей вероятностью будут называть это Брюсселем. Тогда есть особые случаи, такие как Пекин / Пекин.

Начало работы с Placemaker

Веб-сервис Placemaker от Yahoo! — это сервис геоэкстракции, который использует базу данных WOEID и выполняет необходимую нам интерпретацию; синтаксический анализ текста в свободной форме, определение возможных мест и возврат информации о них, такой как WOEID и эта важная широта и долгота.

Прежде чем вы сможете использовать сервис Placemaker, вам понадобится идентификатор приложения, а для этого вам понадобится Yahoo! Я бы. Если вы используете какой-либо из их сервисов, у вас уже есть один. Перейти к Yahoo! веб-сайт для создания идентификатора приложения, где вам будет предложено заполнить следующую форму:

YDN Developer Registration

Большая часть формы не требует пояснений — в разделе « Метод аутентификации» установите флажок «Универсальный, аутентификация пользователя не требуется», поскольку все, что вам нужно для использования сервиса, — это идентификатор приложения, предоставленный на следующей странице. Запишите этот идентификатор приложения, так как он понадобится вам в данный момент (хотя вы всегда можете просмотреть свои существующие идентификаторы приложений из области разработчиков ).

Делать запрос

Placemaker — это REST-подобный веб-сервис с одной конечной точкой; Чтобы воспользоваться услугой, вы отправляете запрос POST на URL http://wherein.yahooapis.com/v1/document . Существует несколько доступных типов ответов: кроме стандартных XML и JSON (и JSONP), у вас также есть возможность получать результаты в формате RSS. Хотя обычно я предпочитаю JSON (сугубо личное предпочтение), в этом примере я буду использовать XML.

Давайте посмотрим на пять параметров запроса, которые вы собираетесь использовать.

POST Parameters

Первый appid — это идентификатор приложения, который вы получили ранее. Если вы пропустите это, запрос будет отклонен. Второй, documentContent , будет строкой, которую вы ищете — названный параметр, потому что сервис позволяет анализировать все документы, однако я просто собираюсь передать имя места, предоставленного пользователем.

И documentType и outputType ссылаются на outputType вами ответ, хотя они могут быть немного запутанными; documentType (из ответа) является простым текстом, в то время как соответствующий outputType является XML. ( outputType также был бы простым текстом, если бы outputType был установлен в JSON.)

Установка autoDisambiguate false переопределяет поведение службы по умолчанию, которое заключается в возвращении только наиболее вероятного места. Именно эту двусмысленность мы пытаемся решить, задавая вопрос пользователю, а не позволяя службе решать за нас.

Наконец, inputLanguage сообщает службе, на каком языке находится документ (то есть пользовательский ввод); это помогает службе знать, как интерпретировать географические названия. Это не обязательный параметр (и, по-видимому, по умолчанию используется американский английский), но стоит упомянуть, потому что важно помнить, что один WOEID может соответствовать количеству имен на множестве языков.

Код

Теперь давайте углубимся в код, когда начнем с получения текста от пользователя через POST и выполнения запроса.

 <?php $appId = YOUR_APP_ID_HERE; $name = $_POST["name"]; $handle = curl_init("http://wherein.yahooapis.com/v1/document"); curl_setopt($handle, CURLOPT_POST, 1); curl_setopt($handle, CURLOPT_POSTFIELDS, sprintf("documentContent=%s&documentType=%s&outputType=%s&autoDisambiguate=%s&appid=%s&inputLanguage=%s", urlencode($name), "text/plain", "xml", "false", $appId, "en-US")); curl_setopt($handle, CURLOPT_FOLLOWLOCATION, 1); curl_setopt($handle, CURLOPT_RETURNTRANSFER, true); $response = curl_exec($handle); curl_close($handle); 

Я предполагаю, что вы уже внедрили форму для ввода имени, и я также пропускаю такие вещи, как экранирование ввода для краткости. Код просто использует cURL, чтобы установить конечную точку на http://wherein.yahooapis.com/v1/document , переменные POST для тех, которые обсуждались ранее, и вернуть ответ веб-службы в виде строки. Не забудьте URL закодировать имя, прежде чем передавать его через POST.

Прежде чем мы начнем манипулировать ответом, давайте взглянем на то, что мы ожидаем (возможно, вы захотите отобразить его на экране в этот момент). Вот упрощенный пример ответа XML:

 <?xml version="1.0" encoding="UTF-8"?> <contentlocation /> <processingTime>0.009052</processingTime> <version> build 110725</version> <documentLength>6</documentLength> <document> <administrativeScope>..</administrativeScope> <geographicScope>..</geographicScope> <localscopes>..</localscopes> <extents>..</extents> <placeDetail>..</placeDetail> <placeDetail>..</placeDetail> <placeDetail>..</placeDetail> <placeDetail>..</placeDetail> ... </document> </xml> 

Когда вы указываете службе не устранять неоднозначность результатов поиска, ответ содержит два аспекта: область места, которое лучше всего описывает документ, и места, на которые может ссылаться документ. Другими словами, сервис обеспечивает наилучшее предположение и предоставляет дополнительную информацию об этом месте в элементах administrativeScope , geographicScope , localscopes и localscopes .

Если вы, например, запросили «Париж», он предоставил бы вам географическую информацию о регионе Иль-де-Франс и стране Франция, но эти области не относятся к Парижу, Техасу или где-либо еще, где есть такое название. , Это те места, которые нас интересуют, потому что мы хотим, чтобы пользователь разъяснил. Эти альтернативы можно найти в элементах placeDetails, как показано ниже:

 <placeDetails> <placeId>3</placeId> <place> <woeId>615702</woeId> <type>Town</type> <name><![CDATA[Paris, Ile-de-France, FR]]></name> <centroid> <latitude>48.8569</latitude> <longitude>2.34121</longitude> </centroid> </place> <placeReferenceIds>1</placeReferenceIds> <matchType>0</matchType> <weight>1</weight> <confidence>6</confidence> </placeDetails> 

Давайте посмотрим на содержимое элемента placeDetails . placeId представляет данное место в контексте ответа и может использоваться для устранения неоднозначности между несколькими совпадениями с одним и тем же WOEID, хотя это — наряду с placeReferenceIds — немного выходит за рамки данной статьи.

weight и confidence говорят нам больше о матче. weight относится к относительному весу места в документе в целом. Это в значительной степени не имеет значения в контексте нашего использования сервиса, поскольку мы отправляем только фрагмент текста, ссылающийся на одно место (по крайней мере, это то, о чем мы просим пользователя). Скорее, используется для ранжирования мест, когда упоминается число, определяемое такими факторами, как их положение в документе и количество упоминаний. Значение confidence (по шкале от 1 до 10, причем 10 является наиболее достоверным) — это уверенность в том, что это место действительно упоминается в документе, но также и то, насколько уверенно, что это место упоминается, а не другое место. Этот последний пункт важен, поскольку он учитывает относительную вероятность того, что, если 100 человек скажут «Лондон», есть вероятность, что большинство будет означать столицу Англии, а не один из меньших по размеру лондонов в Соединенных Штатах. Другими словами, мы можем отсортировать результаты в порядке убывания, основываясь на значении достоверности.

Наконец, и самое главное, есть фактическое место. Элемент place имеет тип; обычно это будет город, но также может быть штат, пригород или, конечно, страна. Элемент centroid содержит широту и долготу геометрического центра, имя должно быть самоочевидным, а woeId — это идентификатор, о котором я говорил. Поскольку это общепринятый идентификатор, ничто не мешает нам использовать его для получения информации о месте в другом месте.

Интерпретация ответа

Теперь, когда мы знакомы со структурой ответа, давайте попробуем его использовать. Вот код, который анализирует ответ:

 <?php $places = array(); $xml = simplexml_load_string($response); foreach ($xml->document->placeDetails as $xmlPlaceDetail) { $xmlPlace = $xmlPlaceDetail->place; $xmlCentroid = $xmlPlace->centroid; $place = new stdClass(); $place->id = (int)$xmlPlaceDetail->placeId; $place->woeid = (int)$xmlPlace->woeId; $place->name = (string)$xmlPlace->name; $place->lat = (float)$xmlCentroid->latitude; $place->lng = (float)$xmlCentroid->longitude; $place->confidence = (int)$xmlPlaceDetail->confidence; $places[$place->id] = $place; } 

Приведенный выше код использует SimpleXML для разбора ответа , placeDetail элементы placeDetail . Каждый раз, когда он сталкивается с одним, он берет элементы place и centroid для извлечения информации, которую мы ищем, и все это назначается новому объекту, представляющему рассматриваемое место.

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

 <?php function confidenceSort($a, $b) { if ($a->confidence == $b->confidence) { return 0; } return ($a->confidence > $b->confidence) ? -1 : 1; } uasort($places, "confidenceSort"); 

Нам нужно оставить массив мест, отсортированных в порядке убывания уверенности.

Что дальше?

Я показал вам, как запрашивать у пользователя название места, извлекал информацию о возможных опциях и сортировал их по вероятности того, что они означают одно местоположение над другим, и доступна простая демонстрационная версия, которую вы можете найти на GitHub. Что вы делаете с этим сейчас, зависит от вас — вы можете попросить пользователя дать разъяснения или попытаться уменьшить количество альтернатив, используя смещение.

Некоторые запросы могут давать десятки результатов, поэтому, вероятно, стоит попытаться повлиять на поиск, сместив его в сторону определенного местоположения, основываясь на том, что вы знаете о пользователе — вы можете передать WOEID места, используя для focusWoeId параметр focusWoeId .

Возможно, вы захотите прочитать больше о WOEID или покопаться немного глубже, посмотрев сервис Geoplanet от Yahoo !. Не только для городов и населенных пунктов, но и для ориентиров. Вы также можете обрабатывать документы целиком — представьте на мгновение возможности геотегирования содержимого блога или расширения текстового поиска, чтобы найти документы не на основе текстового содержимого, а на основе местоположения пользователя. Посмотрите документацию, поиграйте , и если вы застряли, есть форум Placemaker на Yahoo! где вы можете найти дополнительную информацию и обратиться за помощью.

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