From ea2312617991b684face69538d765a97da7e7e84 Mon Sep 17 00:00:00 2001 From: kojisato118 Date: Wed, 6 Apr 2016 07:50:42 +0900 Subject: [PATCH] =?UTF-8?q?[#116427361]=20=E3=83=87=E3=83=AA=E3=83=90?= =?UTF-8?q?=E3=83=AA=E3=83=97=E3=83=AD=E3=83=90=E3=82=A4=E3=83=80=E3=81=AE?= =?UTF-8?q?=E5=AF=BE=E5=BF=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/tracker.rb | 9 +- .../api/corporations/delivery_provider.rb | 133 ++++++++++++++++++ lib/tracker/api/formatter/status.yml | 14 ++ spec/api/delivery_provider_spec.rb | 38 +++++ 4 files changed, 190 insertions(+), 4 deletions(-) create mode 100644 lib/tracker/api/corporations/delivery_provider.rb create mode 100644 spec/api/delivery_provider_spec.rb diff --git a/lib/tracker.rb b/lib/tracker.rb index 56ab351..af5be44 100644 --- a/lib/tracker.rb +++ b/lib/tracker.rb @@ -8,6 +8,7 @@ require 'tracker/api/corporations/sagawa' require 'tracker/api/corporations/yuusei' require 'tracker/api/corporations/seinou' +require 'tracker/api/corporations/delivery_provider' module Tracker # :nodoc: # 荷物追跡 @@ -16,7 +17,7 @@ class Base # @todo クラス名を変える # @todo validationの改修 # @param no [String] 追跡番号 - # @param company [String] 運送会社 (yamato, sawaga, yuusei, seinou) + # @param company [String] 運送会社 (yamato, sawaga, yuusei, seinou, delivery_provider) # @param format [Symbol] (nil[:hash], :json) # @param validation [Symbol] バリーデーションの利用 default: false # @return [Array] @@ -30,12 +31,12 @@ def self.execute(no: nil, company: nil, format: nil, validation: false) end data = [] - # 運送各社を追加する場合はここ(現状は3社のみ) - coms = ["yamato", "sagawa", "yuusei"] + # 運送各社を追加する場合はここ(現状は4社のみ) + coms = ["yamato", "sagawa", "yuusei", "delivery_provider"] companies = company.to_s.empty? ? coms : [company] companies.each do |c| - str = "Tracker::Api::#{c.capitalize}" + str = "Tracker::Api::#{c.split("_").map(&:capitalize).join}" klass = Object.const_get(str) a = klass.new a.no = no diff --git a/lib/tracker/api/corporations/delivery_provider.rb b/lib/tracker/api/corporations/delivery_provider.rb new file mode 100644 index 0000000..686ec4b --- /dev/null +++ b/lib/tracker/api/corporations/delivery_provider.rb @@ -0,0 +1,133 @@ +require 'tracker/api/builder' +require 'tracker/api/formatter' +require 'tracker/api/implementation' +require 'nokogiri' +require 'net/http' + +module Tracker + module Api + # デリバリープロバイダー + # @see http://track-a.tmg-group.jp/cts/TmgCargoSearchAction.do?method_id=INIT + # Cookieが必要なことや一回検索結果ページを経由して詳細画面に遷移するため他の業者と実装が微妙に変わる + class DeliveryProvider + include Tracker::Api::Implementation + + def build_param + @data = [] + @data << ["method_id", "POPUPSEA"] + @data << ["inputData[0].inq_no", @no] + + self + end + + def create_form + @uri = URI.encode_www_form(@data) + + self + end + + def send_data + # cookieがないと情報取得できない模様 + host = "track-a.tmg-group.jp" + http = Net::HTTP.new(host) + path = "/cts/TmgCargoSearchAction.do" + + # cookie取得のための通信 + res = http.get("#{path}?method_id=INIT") + @cookie = res.get_fields("set-cookie").first.match(/(JSESSIONID=.*);/)[1] + + # 検索のための通信 + res = http.get("#{path}?#{@uri}", {"Cookie" => @cookie}) + + # 検索結果画面 + @url = "http://#{host}#{path}?#{@uri}" + @html = res.body + + self + end + + def parse_data + @build = Tracker::Api::Builder.new + @doc = Nokogiri::HTML.parse(@html) do |config| + config.noblanks + end + + @doc.search('table[@id="list"]').each do |node| + node.css('tr').each_with_index do |tr, i| + next if i != 1 + @build.no = tr.search('td[@class="inq_list_input"]').text.strip + @build.status = tr.search('td[@class="inq_list_status"]').text.strip + unless @build.status == "" + # 詳細はformボタンを押して別ページに表示される + detail_info = tr.search('td[@class="inq_list_dtl"]').first + params = detail_info.children.search("input")[0].attributes["onclick"].value.match(/(\(.*\))/)[1].split(',') + doc = Nokogiri::HTML.parse(detail_html(params: params)) do |config| + config.noblanks + end + + doc.search('table[@class="dtl2"]').each do |node| + node.css('tr').each_with_index do |tr, i| + + build = Tracker::Api::Builder.new + build.no = @no + + tr.css('td').each_with_index do |n, j| + case j + when 0 #日付 + build.date = n.text + when 1 #商品所在地 + build.place = n.text + when 2 #状態 + build.status = n.text + end + end + build.company = "delivery_provider" + build.order_no = i + @details << build.object_to_hash unless i == 0 + end + end + else + # 検索結果がないときの文言にお問い合わせ番号がまじるため、"未登録"に書き換える + @build.status = "未登録" + if @build.no == "" + @build.no = @no + end + end + end + end + + self + end + + def insert_latest_data + @build.company = "delivery_provider" + @details << @build.object_to_hash + self + end + + private + def detail_html(params:) + # formで使っているパラメーターを切り出す + tmp_mani_num = params[1].gsub(/\'/, '') + tmp_trk_id = params[2].gsub(/\'/, '') + tmp_item_num = params[3].gsub(/\'/, '') + tmp_cust_ord_num = params[4].gsub(/(\'|\))/, '') + + data = [] + data << ["method_id", "DTL_SHOW"] + data << ["tmp_mani_num", tmp_mani_num] + data << ["tmp_trk_id", tmp_trk_id] + data << ["tmp_item_num", tmp_item_num] + data << ["tmp_cust_ord_num", tmp_cust_ord_num] + + host = "track-a.tmg-group.jp" + http = Net::HTTP.new(host) + path = "/cts/TmgCargoSearchAction.do" + + res = http.get("#{path}?#{URI.encode_www_form(data)}", {"Cookie" => @cookie}) + + res.body + end + end + end +end diff --git a/lib/tracker/api/formatter/status.yml b/lib/tracker/api/formatter/status.yml index 9a5ba84..797311c 100644 --- a/lib/tracker/api/formatter/status.yml +++ b/lib/tracker/api/formatter/status.yml @@ -136,3 +136,17 @@ seinou: "配達": :entry #完了 "配達済みです": :complete + +delivery_provider: + #未登録 + "未登録": :noentry + #引受(受付) + "配送センターからデータを受信しました。": :entry + #配送中 + "近くの配達店まで輸送中です": :entry + #不在 + "ご不在のため、持ち帰りました。再配達をお申込みください。": :reject + #配達中 + "配達中です": :entry + #完了 + "配達完了しました": :complete diff --git a/spec/api/delivery_provider_spec.rb b/spec/api/delivery_provider_spec.rb new file mode 100644 index 0000000..8dda1ac --- /dev/null +++ b/spec/api/delivery_provider_spec.rb @@ -0,0 +1,38 @@ +require 'spec_helper' + +describe Tracker::Api::DeliveryProvider do + let(:delivery_provider) { Tracker::Api::DeliveryProvider.new no: "123412341231" } + + describe ".new" do + subject { delivery_provider.no } + it { should eq "123412341231" } + end + + describe "#execute" do + context "データがある" do + subject { delivery_provider.execute } + it { expect(subject.data).not_to be_empty } + it { expect(subject.details).not_to be_empty } + end + end + + describe "#make" do + context "オリジナルデータをもっている" do + subject { delivery_provider.execute.make.details[0]["origin"] } + it { expect(subject).to_not be_empty } + end + end + + describe "#result" do + context "Hash配列を返す" do + subject { delivery_provider.execute.make.result } + it { should be_a Array } + it { expect(subject[0]).to be_key "no" } + it { expect(subject[0]).to be_key "company" } + it { expect(subject[0]).to be_key "status" } + it { expect(subject[0]).to be_value "123412341231" } + it { expect(subject[0]).to be_value "delivery_provider" } + end + end + +end