html текст
All interests
  • All interests
  • Design
  • Food
  • Gadgets
  • Humor
  • News
  • Photo
  • Travel
  • Video
Click to see the next recommended page
Like it
Don't like
Add to Favorites

Используем почтовые индексы в своём приложении во благо tutorial

Я думаю, что на многих сайтах пользователя спросят его физический адрес. Для доставки ли, для отсылки бумажного спама уведомлений ли. И, в общем-то — это мелочь. Вбил индекс, Москва, область, район, село, улица, дом, квартира. Казалось бы, что тут упрощать, каждый вроде помнит свой адрес, трудно ли его вбить? Но дьявол, как всегда, кроется в мелочах: пользователь опечатывается в адресе, посылка уходит не туда, лучи «добра» идут вам в обратную связь и вообще жизнь плохеет.

Приглядитесь к первой части адреса — индексу. В этом наборе из шести цифр уже есть область, район и город/село. Их можно подставить автоматом. Этим мы убъём сразу двух зайцев:
  • Убережём пользователя от ошибок (при вводе неверного индекса он сразу заметит, что город-то не его), что, в случае доставки письма (а то и посылки), может здорово её ускорить (пока её по неверному индексу зашлют, да пока разберутся, что не туда заслали, да отправят туда — пользователь вам всю плешь проест)
  • пользователю будет приятно, что о нём заботятся :-)

Дело за малым: нам нужна база почтовых индексов.

И она есть! Всамделишняя, электронная и, главное, официальная база индексов от Почты России.

Встречайте: info.russianpost.ru/database/ops.html

База доступна в уже диковинном для молодых разработчиков формате DBF и регулярно (два раза в месяц) обновляется.

Конечно, по подробности эта база до ФИАС недотягивает, но, стоит отдать должное, она гораздо проще (всего одна таблица!), поэтому, если вам не нужна точность до улицы и дома, а хватит только населённого пункта — вам сюда.

Прикручиваем счастье к… ну, давайте к сайту.


Итак, радостно качаем базу и думаем, как же её впихнуть в используемый нами КакойТамУНасСовременныйSQL (а то и НеSQL).

Ищем в гугле, ищем в яндексе, ищем в apt-cache, последний нам радостно и выдаёт:

envek@envek-work:~$ apt-cache search dbf
pgdbf - converter of XBase / FoxPro tables to PostgreSQL
dbf2mysql - xBase <--> MySQL

Здорово-то как! Я использую Postgres и конвертировать буду в него. В базе используется ещё досовская кодировка, так что призовём на помощь iconv. Кстати, самые свежие версии pgdbf (>= 0.6.2) сами шаманством владеют и iconv призывают, но до убунтовского репозитория они ещё не добрались.

mv {PIndx08,post_indices}.dbf # Переименовываем файл, как будет называться таблица
pgdbf -u post_indices.dbf | iconv -f CP866 > post_indices.sql # Конвертируем

Что же, теперь надо заставить это работать.

Я использую Ruby on Rails, на её примере и покажу. Кто рельсы не понимает, может пролистать.

Cоздаём модель, которая будет нашу информацию из базы данных и представлять в приложении
rails g model PostIndex

В миграцию вдумчиво копируем структуру таблицы из оригинальной базы, делаем индекс первичным ключом:
class CreatePostIndices < ActiveRecord::Migration
  def change
    create_table :post_indices, id: false do |t|
      t.string :index,     limit:  6
      t.string :ops_name,  limit: 60
      t.string :ops_type,  limit: 50
      t.string :ops_subm,  limit:  6
      t.string :region,    limit: 60
      t.string :autonom,   limit: 60
      t.string :area,      limit: 60
      t.string :city,      limit: 60
      t.string :city_1,    limit: 60
      t.date   :act_date
      t.string :index_old, limit:  6
      t.index  :index_old
    end
    reversible do |to|
      to.up do
        execute 'ALTER TABLE post_indices ADD PRIMARY KEY (index);'
      end
    end
  end
end

Слегка настраиваем модель:
class PostIndex < ActiveRecord::Base
  self.primary_key = 'index'
end

Делаем простенький контроллер, который нам почтовый индекс в json-формате отдаст:
# В консоли: rails generate controller PostIndices
class PostIndicesController < ApplicationController
  def get
    @index = PostIndex.where(index: params[:index]).first
    @index = PostIndex.where(index_old: params[:index]).order(:index).first! unless @index
    respond_to do |format|
      format.json { render json: @index.to_json(only: [:index, :region, :area, :city]) }
    end
  end
end

Прописываем в config/routes.rb маршрут, по которому приложение нам отдаст желанные индексы:
get '/post_index/:index(.:format)', controller: :post_indices, action: :get

И, главное: html и javascript, которые и сделают всю магию для пользователя.

HTML-форма:
<form id='address_form'>
  <table>
    <tr>
      <td><label for='address_postcode'>Почтовый индекс</label></td>
      <td>
        <input class='postcode_field' id='address_postcode' name='address[postcode]'>
        <p class='description'>После ввода почтового индекса, поля «область», «район» и «город» заполняются автоматически.</p>
      </td>
    </tr>
    <tr>
      <td><label for='address_region'>Область/край/республика</label></td>
      <td><input class='region_field' id='address_region' name='address[region]'></td>
    </tr>
    <tr>
      <td><label for='address_area'>Район</label></td>
      <td><input class='area_field' id='address_area' name='address[area]'></td>
    </tr>
    <tr>
      <td><label for='address_city'>Город/село</label></td>
      <td><input class='city_field' id='address_city' name='address[city]'></td>
    </tr>
  </table>
</form>

Javascript-код (очень подробный, с уведомлением пользователя, отловом ошибок и исправлением индекса)
jQuery(document).ready(function($){
  $('.postcode_field').on('keyup change', function () {
    // Найдём все поля
    var postcode_field = $(this);
    var form = postcode_field.parents("form");
    var region_field = $('.region_field', form);
    var area_field   = $('.area_field', form);
    var city_field   = $('.city_field', form);
    // Очистим все поля
    region_field.val('');
    area_field.val('');
    city_field.val('');
    // Если индекс введён полностью - загрузим информацию о нём
    var postcode = this.value;
    if (postcode.length == 6) {
      jQuery.ajax({ 
        dataType: "jsonp",
        url: 'http://postindexapi.ru/'+postcode+'.json?callback=?',
        beforeSend: function() { // Уведомим пользователя, что загрузка идёт
          $("td:last-child p.description.notice, td:last-child p.description.alert", postcode_field.parents("tr")).remove();
          $('<p class="description notice loading"></p>').text("Загрузка…").appendTo($("td:last-child", postcode_field.parents("tr")))
        },
        success: function(data){
          postcode_field.val(data.index);
          region_field.val(data.region);
          area_field.val(data.area);
          city_field.val(data.city);
          if (data.index != postcode) {
              var message = "Вы ввели устаревший почтовый индекс: "+postcode+", ваш текущий индекс: "+data.index;
              $('<p class="description notice"></p>').text(message).appendTo($("td:last-child", postcode_field.parents("tr")))
          }
        },
        error: function (jqxhr, status, e) {
          var message = 'Произошла ошибка при загрузке адреса по почтовому индексу!'+e;
          if (e == 'Not Found') message = 'Почте России такой почтовый индекс не известен';
          if (status == 'timeout') message = 'Сервер с почтовыми индексами не отвечает. Попробуйте ещё раз.';
          $('<p class="description alert"></p>').text(message).appendTo($("td:last-child", postcode_field.parents("tr")))
          console.debug(jqxhr, status, e);
        },
        complete: function () { // Уберём плашку
          $("td:last-child p.description.loading", postcode_field.parents("tr")).remove();
        }
      });     
    }
  });
});

И, вуаля, при вводе индекса нам автоматом подставляется область, город и так далее. Заодно, бонусом, мы можем исправлять устаревшие индексы на актуальные (очень часто у людей записаны адреса родственников с уже безнадёжно устаревшими индексами).





Ещё штришок: чтобы держать базу всегда свежей, создадим rake-таск, который будет запускаться по крону, скажем, раз в две недели и всё это делать за нас (в Gemfile у вас должен быть gem 'nokogiri', можно с require: false):

require 'open-uri'
require 'fileutils'
require 'nokogiri'

namespace :post_index do

  desc 'Update used post indices database to latest'
  task update: :environment do
    # Get info about post indices database
    url_prefix = 'http://info.russianpost.ru/database'
    doc  = Nokogiri::HTML(open("#{url_prefix}/ops.html"))
    file = doc.at_css('a[name=newdbdata]+table tr:last-child td:nth-child(4) a').attr :href
    FileUtils.mkdir_p "#{Rails.root}/tmp/post_indices"
    dir = Pathname.new("#{Rails.root}/tmp/post_indices")
    filepath = Pathname.new("#{dir}/#{file}")
    filepath_success = Pathname.new("#{dir}/#{file}.success")
    if filepath.exist? and filepath_success.exist?
      puts 'Already up-to-date.'
    else
      # Download, unzip, rename and convert post indices file
      sh "wget #{url_prefix}/#{file} -O #{filepath}"
      sh "unzip -o #{filepath} -d #{dir}"
      dbf_filename = filepath.to_s.gsub /\.zip$/, '.DBF'
      sh "cp -f #{dbf_filename} #{dir}/post_indices.dbf"
      sh "pgdbf -u #{dir}/post_indices.dbf | iconv -f CP866 > #{dir}/post_indices.sql"
      # Import in database
      config = Abitur::Application.config.database_configuration[::Rails.env]
      dbh, dbu, dbp, db = config['host'], config['username'], config['password'], config['database']
      sh "PGPASSWORD=#{dbp} psql -U #{dbu} -w -h #{dbh} #{db} < #{dir}/post_indices.sql"
      # Clean up
      FileUtils.rm [dbf_filename, "#{dir}/post_indices.dbf", "#{dir}/post_indices.sql"], force: true
      FileUtils.touch filepath_success
    end
  end

end

Резюме


Плюсы: простота внедрения, использования и поддержания в актуальном состоянии, малый вес
Минусы: невысокая подробность (только до населённого пункта), ВСЕ ГОРОДА КАПСОМ, ПОЧТА РОССИИ, ЗАЧЕМ?

И для самых ленивых


Ну, и напоследок. Если же вам такая мелочь понравилась, но вы яростно не желаете тащить эту информацию к себе в приложение, то специально для вас я сделал мини-сервис postindexapi.ru. Который делает как раз то, что я описал выше — отдаёт информацию об индексе в JSON. Пользуйтеся на здоровье! Инструкции прилагаются.
И автор не погнушается попросить донату.
Автор с благодарностью примет любые средства на поддержку сервиса postindexapi.ru.
PayPal: envek@envek.name
WebMoney: R157729290120
С не меньшею благодарностью принимаются так же pull request'ы и bug report'ы, а так же любые советы и пожелания в гитхаб-репозитории: github.com/Envek/postindexapi.ru


Спасибо за внимание.
Читать дальше
Twitter
Одноклассники
Мой Мир

материал с habrahabr.ru

1

      Add

      You can create thematic collections and keep, for instance, all recipes in one place so you will never lose them.

      No images found
      Previous Next 0 / 0
      500
      • Advertisement
      • Animals
      • Architecture
      • Art
      • Auto
      • Aviation
      • Books
      • Cartoons
      • Celebrities
      • Children
      • Culture
      • Design
      • Economics
      • Education
      • Entertainment
      • Fashion
      • Fitness
      • Food
      • Gadgets
      • Games
      • Health
      • History
      • Hobby
      • Humor
      • Interior
      • Moto
      • Movies
      • Music
      • Nature
      • News
      • Photo
      • Pictures
      • Politics
      • Psychology
      • Science
      • Society
      • Sport
      • Technology
      • Travel
      • Video
      • Weapons
      • Web
      • Work
        Submit
        Valid formats are JPG, PNG, GIF.
        Not more than 5 Мb, please.
        30
        surfingbird.ru/site/
        RSS format guidelines
        500
        • Advertisement
        • Animals
        • Architecture
        • Art
        • Auto
        • Aviation
        • Books
        • Cartoons
        • Celebrities
        • Children
        • Culture
        • Design
        • Economics
        • Education
        • Entertainment
        • Fashion
        • Fitness
        • Food
        • Gadgets
        • Games
        • Health
        • History
        • Hobby
        • Humor
        • Interior
        • Moto
        • Movies
        • Music
        • Nature
        • News
        • Photo
        • Pictures
        • Politics
        • Psychology
        • Science
        • Society
        • Sport
        • Technology
        • Travel
        • Video
        • Weapons
        • Web
        • Work

          Submit

          Thank you! Wait for moderation.

          Тебе это не нравится?

          You can block the domain, tag, user or channel, and we'll stop recommend it to you. You can always unblock them in your settings.

          • habrahabr.ru
          • домен habrahabr.ru

          Get a link

          Спасибо, твоя жалоба принята.

          Log on to Surfingbird

          Recover
          Sign up

          or

          Welcome to Surfingbird.com!

          You'll find thousands of interesting pages, photos, and videos inside.
          Join!

          • Personal
            recommendations

          • Stash
            interesting and useful stuff

          • Anywhere,
            anytime

          Do we already know you? Login or restore the password.

          Close

          Add to collection

             

            Facebook

            Ваш профиль на рассмотрении, обновите страницу через несколько секунд

            Facebook

            К сожалению, вы не попадаете под условия акции