blog/content/post/2009/11/18/2009-11-18-00001273.md

240 lines
17 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
title: グルメサイトを横断検索した結果を出力するスクリプト
author: kazu634
date: 2009-11-18
wordtwit_post_info:
- 'O:8:"stdClass":13:{s:6:"manual";b:0;s:11:"tweet_times";i:1;s:5:"delay";i:0;s:7:"enabled";i:1;s:10:"separation";s:2:"60";s:7:"version";s:3:"3.7";s:14:"tweet_template";b:0;s:6:"status";i:2;s:6:"result";a:0:{}s:13:"tweet_counter";i:2;s:13:"tweet_log_ids";a:1:{i:0;i:4931;}s:9:"hash_tags";a:0:{}s:8:"accounts";a:1:{i:0;s:7:"kazu634";}}'
categories:
- Perl
---
<div class="section">
<p>
anythingのソースを作るために、グルメサイトを横断検索して結果を出力するスクリプトを作成しました。
</p>
<h4>
仕様
</h4>
<ul>
<li>
電話番号を引数として受け取る
</li>
<li>
検索するのは、以下のサイト: <ol>
<li>
ホットペッパー
</li>
<li>
ぐるなび
</li>
<li>
ドコイク?
</li>
</ol>
</li>
<li>
出力する形式は以下の順番にタブで区切って出力する <ol>
<li>
ヒットしたサイト名
</li>
<li>
店名
</li>
<li>
住所
</li>
<li>
URL
</li>
<li>
電話番号
</li>
</ol>
</li>
</ul>
<h4>
ソース
</h4>
<p>
pmファイルを作成してみました:
</p>
<pre class="syntax-highlight">
<span class="synStatement">package</span><span class="synType"> WebService::Gourmet;</span>
<span class="synStatement">use </span><span class="synConstant">5.010000</span>;
<span class="synStatement">use strict</span>;
<span class="synStatement">use warnings</span>;
<span class="synStatement">use </span>Carp;
<span class="synStatement">use base</span> <span class="synConstant">qw(Class::Accessor::Fast Exporter)</span>;
__PACKAGE__-&#62;mk_accessors(qw ( tel result ));
<span class="synStatement">use </span>WebService::Simple;
<span class="synStatement">use </span>YAML::Syck;
<span class="synStatement">use </span>XML::Simple;
<span class="synStatement">use </span>Encode;
<span class="synComment"># Items to export into callers namespace by default. Note: do not export</span>
<span class="synComment"># names by default without a very good reason. Use EXPORT_OK instead.</span>
<span class="synComment"># Do not simply export all your public functions/methods/constants.</span>
<span class="synComment"># This allows declaration use WebService::Gourmet ':all';</span>
<span class="synComment"># If you do not need this, moving things directly into @EXPORT or @EXPORT_OK</span>
<span class="synComment"># will save memory.</span>
<span class="synStatement">our</span> <span class="synIdentifier">%EXPORT_TAGS</span> = (
<span class="synConstant">'all'</span> =&#62; [
<span class="synConstant">qw(</span>
<span class="synConstant"> )</span>
]
);
<span class="synStatement">our</span> <span class="synIdentifier">@EXPORT_OK</span> = ( @{ <span class="synIdentifier">$EXPORT_TAGS</span>{<span class="synConstant">'all'</span>} } );
<span class="synStatement">our</span> <span class="synIdentifier">@EXPORT</span> = <span class="synConstant">qw(</span>
<span class="synConstant">)</span>;
<span class="synStatement">our</span> <span class="synIdentifier">$VERSION</span> = <span class="synConstant">'0.01'</span>;
<span class="synComment"># Preloaded methods go here.</span>
<span class="synStatement">sub</span><span class="synIdentifier"> search_hot </span>{
<span class="synStatement">my</span> <span class="synIdentifier">$self</span> = <span class="synStatement">shift</span>();
<span class="synComment"># ホットペッパー</span>
<span class="synStatement">my</span> <span class="synIdentifier">$gourmet</span> = WebService::Simple-&#62;<span class="synStatement">new</span>(
<span class="synConstant">base_url </span>=&#62; <span class="synConstant">&#34;http://webservice.recruit.co.jp/hotpepper/shop/v1/&#34;</span>,
<span class="synConstant">param </span>=&#62; { <span class="synConstant">key </span>=&#62; <span class="synConstant">'your api key'</span>, }
);
<span class="synComment"># 入力された電話番号は「lll-mmm-nnnn」という形式のみを想定している。</span>
<span class="synComment"># しかし、ホットペッパーは「lllmmmnnnn」という形式のみ受け付ける。</span>
<span class="synComment"># そこで変換を行う。</span>
<span class="synStatement">my</span> <span class="synIdentifier">$arg</span> = <span class="synIdentifier">$self</span>-&#62;{tel};
<span class="synIdentifier">$arg</span> =~ <span class="synStatement">s/</span><span class="synConstant">-</span><span class="synStatement">//g</span>;
<span class="synComment"># APIをリクエストする</span>
<span class="synStatement">my</span> <span class="synIdentifier">$response</span> = <span class="synIdentifier">$gourmet</span>-&#62;get( { <span class="synConstant">tel </span>=&#62; <span class="synIdentifier">$arg</span>, } );
<span class="synComment"># 結果を $self-&#62;result に格納する</span>
<span class="synStatement">if</span> ( <span class="synStatement">defined</span> XMLin( <span class="synIdentifier">$response</span>-&#62;content )-&#62;{shop} ) {
<span class="synStatement">my</span> <span class="synIdentifier">$data</span> = XMLin( <span class="synIdentifier">$response</span>-&#62;content )-&#62;{shop};
<span class="synStatement">my</span> <span class="synIdentifier">$result</span> = {
<span class="synConstant">&#34;Hotpepper&#34;</span> =&#62; {
<span class="synConstant">&#34;shopname&#34;</span> =&#62; encode( <span class="synConstant">'utf8'</span>, <span class="synIdentifier">$data</span>-&#62;{name} ),
<span class="synConstant">&#34;address&#34;</span> =&#62; encode( <span class="synConstant">'utf8'</span>, <span class="synIdentifier">$data</span>-&#62;{address} ),
<span class="synConstant">&#34;url&#34;</span> =&#62; encode( <span class="synConstant">'utf8'</span>, <span class="synIdentifier">$data</span>-&#62;{urls}-&#62;{pc} ),
<span class="synConstant">&#34;tel&#34;</span> =&#62; <span class="synIdentifier">$self</span>-&#62;tel,
}
};
<span class="synIdentifier">$self</span>-&#62;result(<span class="synIdentifier">$result</span>);
}
<span class="synComment"># ヒットすれば t を返し、ヒットしなければ f を返す</span>
<span class="synStatement">return</span> <span class="synStatement">defined</span> XMLin( <span class="synIdentifier">$response</span>-&#62;content )-&#62;{shop};
}
<span class="synStatement">sub</span><span class="synIdentifier"> search_gournavi </span>{
<span class="synStatement">my</span> <span class="synIdentifier">$self</span> = <span class="synStatement">shift</span>();
<span class="synComment"># ぐるなびへのアクセス</span>
<span class="synStatement">my</span> <span class="synIdentifier">$gourmet</span> = WebService::Simple-&#62;<span class="synStatement">new</span>(
<span class="synConstant">base_url </span>=&#62; <span class="synConstant">&#34;http://api.gnavi.co.jp/ver1/RestSearchAPI/?&#34;</span>,
<span class="synConstant">param </span>=&#62; { <span class="synConstant">keyid </span>=&#62; <span class="synConstant">'your api key'</span>, }
);
<span class="synComment"># 電話番号の取得</span>
<span class="synStatement">my</span> <span class="synIdentifier">$arg</span> = <span class="synIdentifier">$self</span>-&#62;{tel};
<span class="synComment"># APIをリクエストする</span>
<span class="synStatement">my</span> <span class="synIdentifier">$response</span> = <span class="synIdentifier">$gourmet</span>-&#62;get( { <span class="synConstant">tel </span>=&#62; <span class="synIdentifier">$arg</span>, } );
<span class="synComment"># 結果を $self-&#62;result に格納する</span>
<span class="synStatement">if</span> ( <span class="synStatement">defined</span> XMLin( <span class="synIdentifier">$response</span>-&#62;content )-&#62;{rest} ) {
<span class="synStatement">my</span> <span class="synIdentifier">$data</span> = XMLin( <span class="synIdentifier">$response</span>-&#62;content )-&#62;{rest};
<span class="synStatement">my</span> <span class="synIdentifier">$result</span> = {
<span class="synConstant">&#34;GourNavi&#34;</span> =&#62; {
<span class="synConstant">&#34;shopname&#34;</span> =&#62; encode( <span class="synConstant">'utf8'</span>, <span class="synIdentifier">$data</span>-&#62;{name} ),
<span class="synConstant">&#34;address&#34;</span> =&#62; encode( <span class="synConstant">'utf8'</span>, <span class="synIdentifier">$data</span>-&#62;{address} ),
<span class="synConstant">&#34;url&#34;</span> =&#62; encode( <span class="synConstant">'utf8'</span>, <span class="synIdentifier">$data</span>-&#62;{url} ),
<span class="synConstant">&#34;tel&#34;</span> =&#62; <span class="synIdentifier">$self</span>-&#62;tel,
<span class="synConstant">&#34;image&#34;</span> =&#62; encode( <span class="synConstant">'utf8'</span>, <span class="synIdentifier">$data</span>-&#62;{image_url}-&#62;{shop_image1} ),
}
};
<span class="synIdentifier">$self</span>-&#62;result(<span class="synIdentifier">$result</span>);
}
<span class="synComment"># ヒットすれば t を返し、ヒットしなければ f を返す</span>
<span class="synStatement">return</span> <span class="synStatement">defined</span> XMLin( <span class="synIdentifier">$response</span>-&#62;content )-&#62;{rest};
}
<span class="synStatement">sub</span><span class="synIdentifier"> search_dokoiku </span>{
<span class="synStatement">my</span> <span class="synIdentifier">$self</span> = <span class="synStatement">shift</span>();
<span class="synComment"># ドコイク?へのアクセス</span>
<span class="synStatement">my</span> <span class="synIdentifier">$gourmet</span> = WebService::Simple-&#62;<span class="synStatement">new</span>(
<span class="synConstant">base_url </span>=&#62; <span class="synConstant">&#34;http://api.doko.jp/v1/searchPOI.do?&#34;</span>,
<span class="synConstant">param </span>=&#62; {
<span class="synConstant">key </span>=&#62; <span class="synConstant">'your api key'</span>,
<span class="synConstant">format </span>=&#62; <span class="synConstant">'xml'</span>,
}
);
<span class="synComment"># 電話番号の取得</span>
<span class="synStatement">my</span> <span class="synIdentifier">$arg</span> = <span class="synIdentifier">$self</span>-&#62;{tel};
<span class="synComment"># APIをリクエストする</span>
<span class="synStatement">my</span> <span class="synIdentifier">$response</span> = <span class="synIdentifier">$gourmet</span>-&#62;get( { <span class="synConstant">tel </span>=&#62; <span class="synIdentifier">$arg</span>, } );
<span class="synComment"># 結果を $self-&#62;result に格納する</span>
<span class="synStatement">if</span> ( <span class="synStatement">defined</span> XMLin( <span class="synIdentifier">$response</span>-&#62;content )-&#62;{poi} ) {
<span class="synStatement">my</span> <span class="synIdentifier">$data</span> = XMLin( <span class="synIdentifier">$response</span>-&#62;content )-&#62;{poi};
<span class="synStatement">my</span> <span class="synIdentifier">$result</span> = {
<span class="synConstant">&#34;dokoiku&#34;</span> =&#62; {
<span class="synConstant">&#34;shopname&#34;</span> =&#62; encode( <span class="synConstant">'utf8'</span>, <span class="synIdentifier">$data</span>-&#62;{name} ),
<span class="synConstant">&#34;address&#34;</span> =&#62; encode( <span class="synConstant">'utf8'</span>, <span class="synIdentifier">$data</span>-&#62;{address} ),
<span class="synConstant">&#34;url&#34;</span> =&#62; encode( <span class="synConstant">'utf8'</span>, <span class="synIdentifier">$data</span>-&#62;{dokopcurl} ),
<span class="synConstant">&#34;tel&#34;</span> =&#62; <span class="synIdentifier">$self</span>-&#62;tel,
}
};
<span class="synIdentifier">$self</span>-&#62;result(<span class="synIdentifier">$result</span>);
}
<span class="synComment"># ヒットすれば t を返し、ヒットしなければ f を返す</span>
<span class="synStatement">return</span> <span class="synStatement">defined</span> XMLin( <span class="synIdentifier">$response</span>-&#62;content )-&#62;{poi};
}
<span class="synStatement">sub</span><span class="synIdentifier"> pretty_print </span>{
<span class="synStatement">my</span> <span class="synIdentifier">$self</span> = <span class="synStatement">shift</span>();
<span class="synStatement">my</span> <span class="synIdentifier">@work</span> = <span class="synStatement">keys</span> ( %{ <span class="synIdentifier">$self</span>-&#62;result });
<span class="synStatement">my</span> <span class="synIdentifier">$key</span> = <span class="synIdentifier">$work</span>[<span class="synConstant"></span>];
<span class="synStatement">my</span> <span class="synIdentifier">$shopname</span> = <span class="synIdentifier">$self</span>-&#62;result-&#62;{<span class="synIdentifier">$key</span>}-&#62;{<span class="synConstant">&#34;shopname&#34;</span>};
<span class="synStatement">my</span> <span class="synIdentifier">$address</span> = <span class="synIdentifier">$self</span>-&#62;result-&#62;{<span class="synIdentifier">$key</span>}-&#62;{<span class="synConstant">&#34;address&#34;</span>};
<span class="synStatement">my</span> <span class="synIdentifier">$url</span> = <span class="synIdentifier">$self</span>-&#62;result-&#62;{<span class="synIdentifier">$key</span>}-&#62;{<span class="synConstant">&#34;url&#34;</span>};
<span class="synStatement">my</span> <span class="synIdentifier">$tel</span> = <span class="synIdentifier">$self</span>-&#62;result-&#62;{<span class="synIdentifier">$key</span>}-&#62;{<span class="synConstant">&#34;tel&#34;</span>};
say <span class="synConstant">&#34;</span><span class="synIdentifier">$key</span><span class="synSpecial">\t</span><span class="synIdentifier">$shopname</span><span class="synSpecial">\t</span><span class="synIdentifier">$address</span><span class="synSpecial">\t</span><span class="synIdentifier">$url</span><span class="synSpecial">\t</span><span class="synIdentifier">$tel</span><span class="synConstant">&#34;</span>;
}
<span class="synStatement">sub</span><span class="synIdentifier"> search </span>{
<span class="synStatement">my</span> <span class="synIdentifier">$self</span> = <span class="synStatement">shift</span>();
<span class="synStatement">if</span> ( <span class="synIdentifier">$self</span>-&#62;search_hot() ) {
<span class="synIdentifier">$self</span>-&#62;pretty_print;
}
<span class="synStatement">if</span> ( <span class="synIdentifier">$self</span>-&#62;search_gournavi() ) {
<span class="synIdentifier">$self</span>-&#62;pretty_print;
}
<span class="synStatement">if</span> ( <span class="synIdentifier">$self</span>-&#62;search_dokoiku() ) {
<span class="synIdentifier">$self</span>-&#62;pretty_print;
}
}
<span class="synConstant">1</span>;
</pre>
<h4>
使い方
</h4>
<pre class="syntax-highlight">
<span class="synPreProc">#!/usr/bin/env perl</span>
<span class="synComment"># === Libraries ===</span>
<span class="synStatement">use strict</span>;
<span class="synStatement">use warnings</span>;
<span class="synStatement">use utf8</span>;
<span class="synStatement">use lib</span> <span class="synConstant">'/Users/kazu634/bin/lib'</span>;
<span class="synStatement">use </span>WebService::Gourmet;
<span class="synComment"># === Main part ===</span>
<span class="synStatement">my</span> <span class="synIdentifier">$tel</span> = <span class="synStatement">shift</span> || <span class="synStatement">die</span> <span class="synConstant">&#34;Usage: gourmet 000-000-0000</span><span class="synSpecial">\n</span><span class="synConstant">&#34;</span>;
<span class="synStatement">die</span> <span class="synConstant">&#34;Telephone number must be with hyphen. For example, 000-000-0000&#34;</span>
<span class="synStatement">unless</span> ( <span class="synIdentifier">$tel</span> =~<span class="synStatement"> /</span><span class="synConstant">^</span><span class="synSpecial">\d+</span><span class="synConstant">-</span><span class="synSpecial">\d+</span><span class="synConstant">-</span><span class="synSpecial">\d+</span><span class="synConstant">$</span><span class="synStatement">/</span> );
<span class="synStatement">my</span> <span class="synIdentifier">$instance</span> = WebService::Gourmet-&#62;<span class="synStatement">new</span>( { <span class="synConstant">tel </span>=&#62; <span class="synIdentifier">$tel</span> } );
<span class="synIdentifier">$instance</span>-&#62;search();
</pre>
<h4>
実行結果
</h4>
<pre class="syntax-highlight">
~ on kazu634 <span class="synStatement">[</span><span class="synConstant">530</span><span class="synStatement">]</span> $: gourmet <span class="synConstant">03-3780-3908</span>
Hotpepper 正軍 東京都渋谷区道玄坂2--15 阿久津ビル3F http://www.hotpepper.jp/strJ000062726/?<span class="synIdentifier">vos</span>=nhppalsa000016 <span class="synConstant">03-3780-3908</span>
GourNavi 炭火串焼 正軍 〒<span class="synConstant">150-0043</span> 東京都渋谷区道玄坂<span class="synConstant">2-25-15</span> 阿久津ビル3F http://<span class="synStatement">r</span>.gnavi.co.jp/b418500/?<span class="synIdentifier">ak</span>=VMPVyGdfIVYCrk8cr02oSYEV7QXvr8jhUTdC%2Ba4dsB8%3D <span class="synConstant">03-3780-3908</span>
dokoiku 炭火串焼 正軍 東京都渋谷区道玄坂<span class="synConstant">2-25-15</span> 阿久津ビル3F http://www.doko.jp/search/shop/sc70016616/?<span class="synIdentifier">vos</span>=apidoko1 <span class="synConstant">03-3780-3908</span>
</pre>
</div>