ラベル WEBサービス の投稿を表示しています。 すべての投稿を表示
ラベル WEBサービス の投稿を表示しています。 すべての投稿を表示

2013-06-01

Google readerとお別れして、Feedlyに移行してみました

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
今日、6月1日にやったことメモです。

Google Reader終了まで、あと1ヶ月になりました。
どうやら移行先としては、
http://www.feedly.com/
が人気っぽいので移行してみました。

ぱっと使った感じはおしゃれな感じで悪くないです。


あと、今日は携帯のメールの迷惑メール対策を
携帯キャリアからのメールだけ受け取る設定にしました。

最近、迷惑メールがとてもひどくて困っていたのと
サービスとしうて受け取っているメールのドメインがだいたい把握できたので設定しました。
なんか設定はわかりにくい感じでした。


今日は、そんな感じの見直しの日でした。




2010-11-07

「図書ぶら」というのを作ってみました

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
図書館サイトの検索結果ページに、その本に関連する本のリストとAmazonへのリンクを追加するGreasemonkeyスクリプト「図書ぶら」というのを作ってみました。

私は、図書館をよく利用しています。
探す本がわかっているときはいいのですが、なんとなく本を探したいというときには、図書館サイトはむかないつくりになっています。
amazonさんの場合は本に関連する本を紹介してくれるので、参考にしちゃっています。
なのでそのamazonさんの関連本を図書館サイトの方にも表示させるようにしたら便利かもしれないと思い作ってみたのが「図書ぶら」です。

図書館で本を使う方は使ってみていただけるとうれしいです。

現在は、東京23区だけの対応になっていますがご要望があれば他の図書館にも対応したいと思っています。

ちなみに関連本を表示するためには、
Amazon Product Advertising API
を使っています。
その関連本が、その図書館に存在するかを調べるために
カーリル | 図書館API仕様書
を使っています。
これらのAPIはGoogleAppEngine上に作成したアプリがProxyして要求をかけています。
以下のような感じです。
図書ぶら-->GoogleAppEngine-->Amazon,カーリル

2010-09-08

Google App EngineでPORTAのAPIを使ってみようと思ったけど・・・

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
PORTAとは、国立国会図書館デジタルアーカイブポータルです。
こちらがAPIを提供してくれており、詳しくは以下を見てください。
http://porta.ndl.go.jp/wiki/Wiki.jsp?page=%E5%A4%96%E9%83%A8%E6%8F%90%E4%BE%9B%E3%82%A4%E3%83%B3%E3%82%BF%E3%83%95%E3%82%A7%E3%83%BC%E3%82%B9%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6

PORTAを使うとamazonとは違う感じの情報が取れないかなぁと思いGoogle App Engine(の開発環境)でAPIを試してみたところ、残念ながらタイムアウトになってしまいデータが取れなかったのです。

試したプロトコルは、OpenSearchです。
これが帰ってくる情報に結構いろいろのっている感じでよさげだったもので。
ちなみにISBNで検索するならば以下のような感じです。
http://api.porta.ndl.go.jp/servicedp/opensearch?isbn=9784334975586
戻りデータは、RSSですが拡張していろんな情報がのっています。

やろうとしたことは、図書館の分類方法のNDC(日本十進分類法)でデータを検索です。
こちらで検索するとなんかISBNとかがのってないような資料もいっぱいひっかかってしまいました。
比較的ISBNが付いているようなデータが戻ってくるようにするには、ジャンルを限定すればよい感じでした。これでもすべてのデータにISBNが付いているわけではありませんでしたが。

ちなみに試したのは、以下のような感じです。
NDCが588で始まるもの一覧です。
ジャンル指定は、dpidで指定しますがzomokuを指定するとよい感じでした。
http://api.porta.ndl.go.jp/servicedp/opensearch?ndc=588&dpid=zomoku

ちなみにndcは、588.xxxみたいに.以下も付いたりするのですがndcで指定できるのは先頭3桁までのようです。

もうちょっといじってみたかったけど、Google App Engineでタイムアウトといわれてしまうとイカんともしがたい気がするので、とりあえず断念してみる。

2010-08-11

pythonさんでAmazonのRSSからASINを取り出す

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
Amazonさんでは、カテゴリごとに売れ筋を紹介するRSSを提供しています。
どんな感じのURLになっているかは、
http://www.ajaxtower.jp/googleajaxfeed/sample/index3.html
を参照してください。

でも、RSSでは商品のタイトルとそのページへのURLは取れるものですが、他の情報は記事みたいな感じでごっちゃでしか取得できません。
個別にいろいろな情報を取得するためには、APIを利用すればよいのですがそのためにはASIN番号があると便利です。
ASIN番号はURLに埋め込まれていますので、これをpythonさんで取得します。

pythonのRSSのパースには、feedparserが便利な感じです。
RSSをパースしてASINを取り出すのは、以下のような感じです。
import re
import feedparser

#取得したカテゴリのRSSを指定
url = "http://www.amazon.co.jp/rss/bestsellers/books/492352/ref=pd_ts_rss_link"
result = feedparser.parse(url)
for e in result.entries :
  pattern = "^.+\/dp\/(.+)\/ref=.+?$"
  p = re.compile(pattern)
  m = p.search(e.link)
  asin = m.group(1)
  print asin

ちなみにカテゴリのRSSに入っている番号はAPIでBrowseNodeで取り出せる番号です。

2010-06-20

pythonさんでジオコーディングと逆ジオコーディング V3

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
以前、
pythonさんでジオコーディングと逆ジオコーディング
というのを書きましたが、いつまにかGoogle map apiがV3になっていました。

V3になって、Google Map APIを利用するためのキーが必要なくなりました。
なので、V3版で場所の名前から緯度経度取得するジオコーディングとその逆をpythonでやってみました。

Google map api V3でのジオコーディングに関しては、
http://code.google.com/intl/en/apis/maps/documentation/geocoding/
に書いてあります。

コードは以下のような感じです。
google app engineで利用することを前提にしているので
urlfetchを使っていますが、そうでないならばそこを置き換える必要があります。
jsonのパーサーも場合によって変更が必要だと思います。

import urllib
from google.appengine.api import urlfetch
import django.utils.simplejson as json

from django.conf import settings

#場所名から緯度経度取得
def geocoding(addr):
    url = 'http://maps.google.com/maps/api/geocode/json?'
    url = url + '&language=ja&sensor=false®ion=ja'
    url = url + '&address=' + urllib.quote(addr.encode('utf-8'))
    result = urlfetch.fetch(url)
    if result.status_code != 200:
        return None
    obj = json.loads(result.content)
    if obj["status"] != "OK":
        return None
    ret = {}
    ret['lon'] = str(obj["results"][0]["geometry"]["location"]["lng"])
    ret['lat'] = str(obj["results"][0]["geometry"]["location"]["lat"])
    return ret

#緯度経度から場所名取得
def regeocoding(lat,lon):
    url = 'http://maps.google.com/maps/api/geocode/json?'
    url = url + '&language=ja&sensor=false®ion=ja'
    url = url + '&latlng=' + str(lat) + ',' + str(lon)
    result = urlfetch.fetch(url)
    if result.status_code != 200:
        return None
    obj = json.loads(result.content)
    if obj["status"] != "OK":
        return None
    addr = None
    for result in obj["results"]:
        if "sublocality" in result["types"]:
            addr = result["formatted_address"]
            addr = addr.replace(u'日本, ', '', 1)
            break
    return addr


2010-05-13

Googleドキュメントにあるドキュメントをランダムで取得してメールをする

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
Googleドキュメントにいろいろメモを残しているのに全然見返すことをしていないない・・・
そんな私のためにGoogle App EngineでGoogleドキュメントの内容をランダムで取得してメール送信するものを作ってみました。

機能としては、
・文章のみをメール送信します。スプレッドシートなどは送信しません。
・取得対象はランダムです。
・文章を送信対象外にするリストを持ち、リストに追加したドキュメントは送信しません。
・oAuthを利用します
てな感じです。

エラー処理が少々大雑把なため
ドキュメントが一つもなかったり、すごく大量にあった場合にどうなるかはわかりません。

Djangoのアプリケーションになっています。
http://docs.google.com/leaf?id=0BydytAINVs9VM2E5NWRlMGItNWM1Yy00OTZhLWI5MTctYjQ0MDliNWJhMjI0&hl=ja
にアプリ部分だけzipしたものを置いてみましたので、もしご興味があればご利用ください。
zipを解凍してできたディレクトリをDjangoプロジェクトのルートに配置して利用できるように設定します。
ディレクトリ内のsettings.pyは編集する必要があります。

実行には、gdataが必要です。
以下から取得できます。
http://code.google.com/p/gdata-python-client/

Google App Engine patchも必要な気がします。
こちらで利用しているモジュールも使っているような気がします。
以下から取得できます。
http://code.google.com/p/app-engine-patch

app.yamlには
- url: /gdoc_sender/.*
  script: common/appenginepatch/main.py
  login: admin
みたいなエントリを追加する必要があります。

あと、queue.yamlを以下のような感じで。
queue:
- name: default
  rate: 5/m

- name: gdoc-sender
  rate: 5/m

そして、cron.yamlを以下のような感じで。
cron:
- description: daily mail send
  url: /gdoc_sender/set_queue/
  schedule: every day of month 09:00
  timezone: Asia/Tokyo

こんなメモを残していたのか・・・
と毎日一つは残したメモを見返すようになりましたとさ。

2010-05-04

googleドキュメントで作成した文章をAPIを利用してテキストで取得する

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
googleドキュメントで作成した文章をGoogle App Engineで取り出したくなりました。
Google App Engineで簡単に利用したいのでtext形式でダウンロードがしかくなったのです。

以下のような感じで取れました。
Djangoでの例です。
とりあえず前件取得してランダムで取得してみます。
# -*- coding: utf-8 -*-
import random
from django.http import HttpResponseRedirect
from django.utils.translation import ugettext as _
from ragendja.template import render_to_response
from django.conf import settings
import gdata.gauth
import gdata.docs.client
import gdata.docs.data

APP_NAME = 'googleDocumentTextGetTest'
def index(request):
  payload = dict()
  client = gdata.docs.client.DocsClient(source=APP_NAME)
  client.ssl = True
  client.ClientLogin('googleアカウントのメールアドレス', 'そのパスワード', client.source)
  payload['feed'] = client.get_everything()
  feed_len = len(payload['feed'])
  while True:
    get_doc = random.randint(0, feed_len-1)
    payload['selection'] = payload['feed'][get_doc]
    #取れたものがスプレッドシートとかだったらもう一回取り直す
    doc_type = payload['selection'].GetDocumentType()
    if doc_type == "document":
      break
  doc_uri = '/feeds/download/documents/Export?docID=' + payload['selection'].resource_id.text + '&exportFormat=txt'
  payload['content'] = client.get_file_content(doc_uri)
  return render_to_response(request, 'index.html',payload)


参考までにテンプレートは以下のような感じです。
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html
xmlns="http://www.w3.org/1999/xhtml"
dir="{% if LANGUAGE_BIDI %}rtl{% else %}ltr{% endif %}"
xml:lang="{% firstof LANGUAGE_CODE 'en' %}"
lang="{% firstof LANGUAGE_CODE 'en' %}">
<head>
<title>test</title>
</head>
<body>
{{ selection.title.text }}<br>
<pre>
{{ content }}
</pre>
<ul>
{% for entry in feed.entry %}
<li>{{ entry.title.text }}</li>
{% endfor %}
</ul>
<body>
<html>  


本当だったら、全件取得でなく以下のような感じで
/feeds/default/private/full/-/document
documentファイルだけを取得したかったのですが、なぜかできませんでした。

2010-05-02

GAEでgoogleさんにOAuth

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
Google App EngineでgoogleさんにOAuthしてみました。
Djangoを使ったpythonで実験しています。

まずは準備としてGoogleさんにサイトを登録して
Consumer Key

Consumer Secret
を手に入れる必要があります。

https://www.google.com/accounts/ManageDomains
で利用ドメインを登録します。すると
Manage registration
に登録したドメインが出るのでクリックします。
最初に登録したドメインのページにメタタグを埋め込んでサイトの確認を実行します。
すると
Target URL path prefix:
を入れる欄が出てくるようになるので
とりあえず
サイトでOAuthを利用するパスを入れてセーブします。
例:
 http://xxxx.xxxx.xxxx/oauth_test/index.html
 とかでOAuthを使ったもろもろをoauth_test配下に入れて置くならば、
 http://xxxx.xxxx.xxxx/oauth_test
 を登録します。
(実際は、どんなものを入れるのがよいのかいまいちよく分かっていません)

これで
Consumer Key

Consumer Secret
が発行されるのでメモしておきましょう。

今回OAuth関連の処理をするものとしてgdataを利用します。
http://code.google.com/p/gdata-python-client/
gdataは、OAuth用というよりもGoogleカレンダーとかドキュメントとかのAPIを扱う便利クライアントです。
OAuthしたらなんらかのgoogleのAPIを利用するのでこれを利用します。
取得したら、
Djangoプロジェクトディレクトリ直下に
atom
gdata
をコピーします。

今回、OAuthを試すアプリとして
oauth_test
を作ります。
これはgoogleドキュメントに登録してあるデータ一覧を取得するものにしてみます。
なのでsettings.pyに使えるように設定しておきます。
またoauth_testでは認証がかかるようにapp.yamlに以下を追加します。

- url: /oauth_test/.*
script: common/appenginepatch/main.py
login: required

なので今回用意したものは以下のような感じです
Djangoルート
|-atom
|-gdata
|-oauth_test
|-template
| |-index.html
|-settings.py
|-urls.py
|-urlsauto.py
|-views.py

oauth_test配下のものはざっと以下のような感じです。

settigns.py

from ragendja.settings_post import settings
settings.CONSUMER_KEY = '取得したConsumer Keyを入れます'
settings.CONSUMER_SECRET = '取得したConsumer Secretを入れます'


urlsauto.py

# -*- coding: utf-8 -*-
from django.conf.urls.defaults import *
rootpatterns = patterns('',
(r'^oauth_test/', include('oauth_test.urls')),)


urls.py

# -*- coding: utf-8 -*-
from django.conf.urls.defaults import *
urlpatterns = patterns('oauth_test.views',
(r'^$', 'index'),
(r'^oauth_set/$', 'oauth_set'),
(r'^oauth_callback/$', 'oauth_callback'),
(r'^oauth_revork/$', 'oauth_revork'),
)


view.py

# -*- coding: utf-8 -*-
from django.http import HttpResponseRedirect
from django.utils.translation import ugettext as _
from ragendja.template import render_to_response
from django.conf import settings
from google.appengine.api import users

import gdata.gauth
import gdata.docs.client
import gdata.docs.data

APP_NAME = 'oauthMyTest'
def index(request):
payload = dict()
login = users.get_current_user()
#すでに登録済みかどうかを確認します
#gdata.gauth.Ae*を利用することでGoogle App Engineのデータストアに
#取得したOAuthのトークンとシークレットをオブジェクトして格納して出し入れできます。
#memcacheのようにキーとtokenがセットになっています。
#ここではログインユーザのuser_idをキーにしています。
token = gdata.gauth.AeLoad(login.user_id())
if token == None:
payload['have_token'] = False
else:
payload['have_token'] = True
#ドキュメント一覧を取得します
#client.ssl = Trueを必ずつけましょう
#付け忘れるとInvalid Tokenとか言われて悩みます
client = gdata.docs.client.DocsClient(source=APP_NAME)
client.ssl = True
client.auth_token = gdata.gauth.AeLoad(login.user_id())
payload['feed'] = client.get_doclist()
return render_to_response(request, 'oauth_test/index.html',payload)

def oauth_set(request):
#googleにリダイレクト処理をします
SCOPES = ['https://docs.google.com/feeds/']
callback_url = 'http://%s/oauth_test/oauth_callback/' % request.get_host()
client = gdata.docs.client.DocsClient(source=APP_NAME)
request_token = client.GetOAuthToken(SCOPES, callback_url, settings.CONSUMER_KEY, consumer_secret=settings.CONSUMER_SECRET)
login = users.get_current_user()
#callbackしてきたときに利用できるように一時的にtokenを格納します。
gdata.gauth.AeSave(request_token, "tmp_" + login.user_id())
return HttpResponseRedirect(request_token.generate_authorization_url())

def oauth_callback(request):
#アクセス用のトークンとトークンシークレットを格納します
login = users.get_current_user()
#一時的に格納したtokenを取り出し削除しておきます。
saved_request_token = gdata.gauth.AeLoad("tmp_" + login.user_id())
gdata.gauth.AeDelete("tmp_" + login.user_id())
request_token = gdata.gauth.AuthorizeRequestToken(saved_request_token, request.build_absolute_uri())
client = gdata.docs.client.DocsClient(source=APP_NAME)
try:
#ここでアクセストークンを取得して格納
access_token = client.GetAccessToken(request_token)
gdata.gauth.AeSave(access_token, login.user_id())
except:
logging.info('cant get access token')
return HttpResponseRedirect('/oauth_test/')

def oauth_revork(request):
#取得したtokenを破棄します
login = users.get_current_user()
gdata.gauth.AeDelete(login.user_id())
return HttpResponseRedirect('/oauth_test/')


template/index.html

<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
dir="{% if LANGUAGE_BIDI %}rtl{% else %}ltr{% endif %}"
xml:lang="{% firstof LANGUAGE_CODE 'en' %}"
lang="{% firstof LANGUAGE_CODE 'en' %}">
<head>
<title>oauth_test</title>
</head>
<body>
{% if have_token %}
<a href="/oauth_test/oauth_set/">登録する</a>
{% else %}
<ul>
{% for entry in feed.entry %}
<li>{{ entry.title.text }}</li>
{% endfor %}
</ul>
<hr>
<a href="/oauth_test/oauth_revork/">登録を解除する</a>
{% endif %}
</body>
</html>


こんな感じです。
TwitterのOAuthと比べるとちょっとめんどっちい感じです。

2010-04-18

Google App EngineからTwitterにつぶやく

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
Google App EngineからTwitterにつぶやく方法です。

まず用意するのは、
TwitterのOauthサイトに飛ぶための機能
TwitterのOauthからCallbackされるところ
が必要です。

これがつぶやくための情報が取得できたことになるので
これではじめてつぶやけます。

まずTwitterのAPIを利用するための登録をTwitterに行います。
http://www.msng.info/archives/2010/01/twitter_api_oauth_with_php.php
がとても参考になります。

そしてGoogle App EngineからTwitterのAPIを利用するには、
AppEngine-OAuth-Library
が大変便利です。
使い方は、
http://blog.mudaimemo.com/2010/02/google-app-engine-twitter-oauth.html
が大変参考になります。

ざっくり使うならば以下のような感じになります。
# -*- coding: utf_8 -*-

import os
import sys
import logging

from google.appengine.ext.webapp import template
from google.appengine.ext import webapp
from google.appengine.api import urlfetch
from django.utils import simplejson as json
import traceback
import urllib
#AppEngine-OAuth-Libraryを読み込みます。
import oauth

import wsgiref.handlers

#登録した値を使います
CONSUMER_KEY = 'アプリのConsumer key'
CONSUMER_SECRET = 'アプリのConsumer secret'

class Top(webapp.RequestHandler):
  def get(self):
    template_values = {}
    path = os.path.join(os.path.dirname(__file__), 'top.html')
    self.response.out.write(template.render(path, template_values))

class TwitSignin(webapp.RequestHandler):
  def get(self):
        callback_url = '%s/twitter/callback' % (request.host_url)
        client = oauth.TwitterClient(CONSUMER_KEY, CONSUMER_SECRET,callback_url)
        self.redirect(client.get_authorization_url())

class TwitCallback(webapp.RequestHandler):
  def get(self):
    #つぶやくために必要なのは以下の二つではありません
    token = request.get('oauth_token')
    verifier = request.get('oauth_verifier')
    client = oauth.TwitterClient(CONSUMER_KEY, CONSUMER_SECRET,None)
    #以下の部分で肝心な情報を取得します
    user_info = client.get_user_info(token, verifier)
    #この下で取得する2つの情報がつぶやくために必要になります
    oauth_token  = user_info['token']
    oauth_secret = user_info['secret']

    #重要な情報がとれたところでついでにつぶやきサンプルです。
    msg = "oauthテスト なう"
    additional_params = {'status': msg}
    try:
        response = client.make_request('http://twitter.com/statuses/update.json',
                                       token=oauth_token,
                                       secret=oauth_secret,
                                       additional_params=additional_params,
                                       protected=True,
                                       method='POST')
        data = json.loads(response.content)
        if data.has_key('error'):
            logging.error(data['error'])
    except Exception, e:
        logging.error(traceback.format_exc())
        
    self.redirect("/")


def main():
  application = webapp.WSGIApplication([
                                        ('/', Top),
                                        ('/twitter/signin', TwitSignin),
                                        ('/twitter/callback', TwitCallback),
                                        ],
                                       debug=True)
  wsgiref.handlers.CGIHandler().run(application)

if __name__ == "__main__":
  main()

ちなみにtop.htmlは
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
    "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>test</title>
</head>
<body>
<a href="/twitter/signin">auth twitter</a>
</body>
</html>

2010-04-14

Google App Engineで短縮URLのAPIを利用する

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
最近、よく見る短縮URLをGoogle App Engineでも利用してみます。
bit.lyは、APIを利用できるのでbit.lyを使うことにします。

利用のためには、以下でアカウント登録が必要ですが無料ですし必要なのはメールアドレスだけです。
http://bit.ly/account/register
登録が済んだら以下でApiKeyを取得します。
http://bit.ly/account/your_api_key

ここまで出来たら準備OK。

以下のような関数を作って呼び出せば、短縮urlを利用できます。
# -*- coding: utf_8 -*-

from google.appengine.api import urlfetch
import urllib

def make_short_url(url):
    bitly_account = "bit.lyに登録したアカウント"
    bitly_key     = "bit.lyから発行されたAPIキー"
    bitly = "http://api.bit.ly/v3/shorten"
    bitly = bitly + "?login=" + bitly_account + "&apiKey=" + bitly_key
    bitly = bitly + "&format=txt"
    bitly = bitly + "&longUrl=" + urllib.quote_plus(url)
    result = urlfetch.fetch(bitly)
    if result.status_code != 200:
        return None
    return result.content[:-1]

2009-11-28

Google Static Maps APIで作成した地図画像を携帯で見ようとしても見れないことがある

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
Google Static Maps APIで地図画像を作れるわけですが、ソコニイクでもこの機能を使っています。
この画像を携帯で見たときになんか見れたり見れなかったりすることがありました。
見れなくてもリロードすれば見れたりすることが多かったわけですが、たまになんどリロードしてもダメなときもありました。
同じ画面をPCの方から確認すると問題なく見れてしまう感じだったのです。

私が持っている携帯の調子が悪いのかな?と思ったりもしたのですが、調べてみると似たようなことが他の人にも起こっていることがわかりました。

http://okwave.jp/qa5396695.html
が似たような現象で、どうも携帯だとGoogle Static Maps APIの回数制限にかかりやすい感じということがわかりました。
そして、Google Static Maps API Version2にするのもよさそうな感じということがわかりました。
しかし回数制限にひっかかるとメーターが振り切った画像が出ると書かれているのですが、私の現象では普通の画像リンク切れみたいな感じでちょっと違う感じもします。
と思いつつソコニイクでもGoogle Static Maps API Version2に書き換えてみました。

他にも調べてみると
http://php.tekmemo.net/?p=1111
という記事もあり、こちらは画像がリンク切れみたいな感じと私の現象により似ている感じです。
コチラでは必須パラメータsensorの付け忘れが原因だったようで、私の場合はsensorはつけていたのでこちらも違う感じです。

でいろいろ調べていたところ私がGoogle Static Maps APIを呼ぶときですが、以下のように呼ぶべきところを
http://maps.google.co.jp/maps/api/staticmap?
size=300x200&path=color:0xFF0000|weight:40|0,0|35,139&
sensor=false&key=[MAPS_API_Key]
&がエスケープ処理が係っていて&amp;となっていて
http://maps.google.co.jp/maps/api/staticmap?
size=300x200&amp;path=color:0xFF0000|weight:40|0,0|35,139&amp;
sensor=false&amp;key=[MAPS_API_Key]
となっていました。
なのでこちらも直しました。

そしたらなんか調子よくなってしまいました。
APIをversion2にするのとエスケープ処理をとめるのを同時にやってしまったのでどちらが本当の原因だったのかわからなくなってしまいました。

ちなみにGoogle Static Maps APIの呼び方にエラーがあった場合は、エラーメッセージが表示されるようです。
<img src="http://maps.google.co.jp/maps/api/staticmap?
size=300x200&path=color:0xFF0000|weight:40|0,0|35,139&
sensor=false&key=[MAPS_API_Key]">
としているとエラーになるとリンク切れにしか見えませんが
<a href="http://maps.google.co.jp/maps/api/staticmap?
size=300x200&path=color:0xFF0000|weight:40|0,0|35,139&
sensor=false&key=[MAPS_API_Key]">test</a>
としてリンク先を見ればエラーメッセージが確認できたりします。

2009-11-24

Google Static Maps API Version 2なるものがありました

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
Google Static Maps APIについて調べると
Google Codeの
http://code.google.com/intl/ja/apis/maps/documentation/staticmaps/
にたどり着いてこちらを参考にすることが多いと思います。

私は知らなかったのですが、これにはVersion2があるのです。
ちなみに上記の日本語版はVersion1です。

Google Codeのページを英語に切り替えると実はVersion2の説明になっていたりします。
http://code.google.com/intl/en/apis/maps/documentation/staticmaps/

Version2に関して日本語の説明ページも別のところにありました。
http://googlemaps.googlermania.com/staticmapsv2/index.html
コチラのページを英語のページとあわせて使うと便利です。

Version2になって、そんなに大きく機能が変わるわけではないのですが、個人的にはVersion2で追加されたvisibleパラメータが便利だと思っています。
visibleには、地図上に表示させたいポイントを複数指定できます。
そしてそのポイントがいい感じで収まるズームサイズを勝手に判別してくれるもののようです。

過去に
Google Static Maps APIのいい感じのズームサイズを決定する
というエントリを書いたわけですが、ここで書いた計算をしないでもGoogleさんのほうでいい感じにしてくれるのです。

Google Codeの日本語記事はとても役に立つのですが、たまに実はちょっと古いみたいなことがある気がします。
最新を常に保って欲しいとはいいませんが、
最新情報が英語版のほうにあるよ
と日本語の記事でも教えてくれるとうれしいなぁとか思ってみました。

2009-11-05

PythonさんでGoogleカレンダーのイベント内容を取得する

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
PythonでGoogleカレンダーに登録されているイベントを取得してみました。

データの取得にはgdata-python-clientというのを使うのがとても便利です。
以下から取得できます。
http://code.google.com/p/gdata-python-client/

使い方は、以下を見る感じです。
http://code.google.com/intl/ja/apis/calendar/data/1.0/developers_guide_python.html

認証には、AuthSub,OAuth,ClientLoginと種類があるのですが、以下の例ではClientLoginを利用しています。

import gdata.calendar.service

def print_event():
#認証部分
username = 'グーグルアカウント'
calendar_service = gdata.calendar.service.CalendarService()
calendar_service.email = username
calendar_service.password = 'グーグルアカウントのパスワード'
#適当にプログラム名を指定すればよい感じ
calendar_service.source = 'Google_Calendar_Event_Get_test'
calendar_service.ProgrammaticLogin()

#デフォルトのカレンダーから取得する
visibility = 'private'
projection = 'full'
query = gdata.calendar.service.CalendarEventQuery(username, visibility, projection)
#検索条件の指定
#検索範囲を指定
query.start_min = '2009-11-01'
query.start_max = '2009-12-02'
#繰り返しイベントを別のイベントとして取得
query.singleevents = 'true'
#イベントの開始日時の昇順でソート
query.orderby='starttime'
query.sortorder='a'
feed = calendar_service.CalendarQuery(query)

for ev in feed.entry:
for e in ev:
print '%s. [%s]-[%s]' % (ev.title.text,e.start_time,e.end_time)


ちなみにCalendarEventQueryの検索条件に指定できるのは、以下を参照すると分かります。
http://code.google.com/intl/ja/apis/calendar/data/2.0/reference.html#Parameters
テキストで検索するには以下を参照するとわかります。
http://code.google.com/intl/ja/apis/calendar/data/1.0/developers_guide_python.html#RetrievingWithQuery

2009-10-10

Djangoでjsonを読み取る

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
Djangoでjsonを使おうと思うとjson形式で出力することはいっぱい見つかるのですが、どっかのAPIとかを使った出力がjson形式でそれをパースしようと思ったときの情報が少ない感じがします。

json形式をパースするにはDjangoの中にsimplejsonというものが付属しているようなのでそれを利用すればよいそうです。

以下のような感じです。

import django.utils.simplejson as json

def parse_json(json_str):
obj = json.loads(json_str)
return obj


こんな感じで使う感じです。
json_str='["foo", {"bar":["aaa", "bbb", "ccc"]}]'
ret = parse_json(json_str)
foo = ret['foo']

でもDjango1.1からはsimplejsonがDjangoに組み込まれなくなったようなことをどっかで見たような気がしないでもないです。

simplejsonに関して詳しくは以下を参考にしてください。
http://undefined.org/python/#simplejson
ちなみにjson形式で出力を行うには、以下を参考にしてくみてください。
http://djangoproject.jp/doc/ja/1.0/topics/serialization.html

2009-10-03

携帯からgoogle mapにリンクをはったり、グーグルのiアプリを起動したり

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
携帯サイトなどえも自分でgoogleのapiを利用して地図を作るのもよいのですが、なんだかんだで携帯さんのgoogleさんを利用できると便利なことが多いわけです。

そんなわけで指定した場所で携帯googleマップにリンクを張る方法は、以下が参考になります。
http://imakoko.didit.jp/imakoko_html/memo/parameters_google.html
こちらでloncパラメータに緯度経度を指定できと書いてありますが、緯度経度は指定できずに地名しか指定できないようです。

緯度経度を利用するならば、逆ジオコーディングをして住所などを割り出す必要があります。
逆ジオコーディングは、以前書いた以下を参考にしていただけるとうれしいです。
pythonさんでジオコーディングと逆ジオコーディング

またdocomoでは、googleマップのiアプリも便利なわけなの起動のためのリンクなども用意すると便利な感じです。その方法は、以下が参考になります。
http://saya.s145.xrea.com/archives/2007/08/post_258.html
アプリ起動の際にqパラメータに緯度経度や地名を渡すことで指定した場所を中心にして起動できます。
qパラメータにはkml(簡易のようですが)も渡すことができるそうです。

2009-09-30

Google Static Maps APIのいい感じのズームサイズを決定する

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
Google Static Maps APIを使っているとある2点が一画面に収まるような感じのズームサイズを決定したくなることがあります。

pythonで以下のような感じで求められそうです。

#2つの指定座標が収まるズームサイズを求める
#sizeは画像サイズ(正方形地図を利用としています)
# 長方形の場合は、二つの値を受け取ってそれぞれに対して
# zoomを計算して小さい方を選べばよいと思います。
#x1,y1はポイント1の緯度経度
#x2,y2はポイント2の緯度経度
def get_zoom_size(size,x1,y1,x2,y2):
dx = float(x1)-float(x2)
dy = float(y1)-float(y2)
d=math.sqrt(dx*dx+dy*dy)
if d==0:
return 14
zoom = math.log(float(size)/d)/math.log(2)
return int(math.floor(zoom))

floatやらintやらがこなれていない感じがビンビンしてますが、なんとなく出ている感じがするので、まぁよしとしましょう。
これは、
Google Static Maps API で表示した画像の端っこの緯度経度を調べる
で紹介した以下の式を変形させて出してみました。
lx=float(xsize)/pow(2,float(zoom))

2009-09-24

携帯で位置情報を取るには、Cirius LabさんのGeoFormAPIがステキ

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
携帯サイトの醍醐味の一つは位置情報を取れることだと思うのですが、各会社毎に取得する手段が違うし、同じ会社でもGPSを使うものと基地情報(?)を使うものといろいろなわけです。
そんな違いを吸収してくれるのがCirius LabさんのGeoFormAPIなのです。
詳細は、以下をみてください。
http://lab.cirius.co.jp/index.php?GeoPlatformAPI%2FGeoFormAPI
これを利用すると、位置情報を取得するためのリンクを生成してくれます。
生成した情報をクリックすると位置情報を取得して、指定したurlに位置情報をつけてもどしてくれます。

pythonさんで利用するには、以下のような感じです。
利用前提はgoogle app engineなのでurlfetchを使っていますが、使わないときは適当に置き換えてください。
またdjangoを利用するのでrequestオブジェクトを受け渡しています。環境変数を取るときは違う手段を使っても良いと思います。

# -*- coding: utf-8; -*-
from urllib import urlencode
from google.appengine.api import urlfetch

def get_geo_form(request,return_uri,w='現在位置で探す'):
params = {
'ua':request.META.get('HTTP_USER_AGENT', ''),
'return_uri':return_uri,
'api_key':'APIを利用するためのAPIキーを指定します。',
'display':w,
}
url = 'http://api.cirius.co.jp/v1/geoform/xhtml?' + urlencode(params)
result = urlfetch.fetch(url)
if result.status_code != 200:
return None
return result.content


get_geo_formによって、リンクのhtmlを返すのでこれをそのまま使いたい場所に埋め込むことになります。

2009-09-23

pythonさんでジオコーディングと逆ジオコーディング

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
場所の名前から緯度経度取得するジオコーディングをpythonでやってみました。

google mapを利用します。
ジオコーディングに関しては、
http://code.google.com/intl/ja/apis/maps/documentation/services.html#Geocoding_Direct
に書いてあります。

コードは以下のような感じです。
google app engineで利用することを前提にしているので
urlfetchを使っていますが、そうでないならばそこを置き換える必要があります。

# -*- coding: utf-8; -*-
import xml.etree.ElementTree as etree
import urllib
from google.appengine.api import urlfetch

#場所名から緯度経度取得
def geocoding(addr):
url = 'http://maps.google.com/maps/geo?'
url = url + 'key=' + 'グーグルマップAPIのキー'
url = url + '&sensor=false'
url = url + '&output=xml'
url = url + '&q=' + urllib.quote(addr.encode('utf-8'))
result = urlfetch.fetch(url)
if result.status_code != 200:
return None
dom = etree.fromstring(result.content)
namespace ='http://earth.google.com/kml/2.0'
code = dom.findtext('.//{%s}code' % namespace)
if code != "200":
return None
point = dom.findtext('.//{%s}coordinates' % namespace)
if point == None :
return None
tmp = point.split(',')
ret = {}
ret['lon'] = tmp[0]
ret['lat'] = tmp[1]
return ret


緯度経度から場所の名称を取得する逆ジオコーディングもgoogle map apiでできることを
http://creco.net/2009/03/07/implement_google_reverse_geocoding_api/
で知りましたので、こちらも試してみました。

コードは以下のような感じです。
取得できる場所の名称が道路名だったり郵便番号だったりするケースを除外するためにAddressDetailsのAccuracyを確認する必要があるのですが、AddressDetailsのネームスペースが他と違っているので、そこが注意ポインツです。
しばらく気づかずにAddressDetailsの情報が取れなくて悩んでしまいました。

# -*- coding: utf-8; -*-
import xml.etree.ElementTree as etree
import urllib
from google.appengine.api import urlfetch

#緯度経度から場所名取得
def regeocoding(lat,lon):
url = 'http://maps.google.com/maps/geo?'
url = url + 'key=' + 'グーグルマップAPIのキー'
url = url + '&hl=ja'
url = url + '&oe=UTF8'
url = url + '&output=xml'
url = url + '&q=' + str(lat) + ',' + str(lon)
result = urlfetch.fetch(url)
if result.status_code != 200:
return None
logging.info(result.content)
dom = etree.fromstring(result.content)
namespace ='http://earth.google.com/kml/2.0'
code = dom.findtext('.//{%s}code' % namespace)
if code != "200":
return None
for placemark in dom.findall('.//{%s}Placemark' % namespace):
ad = placemark.find('.//{urn:oasis:names:tc:ciq:xsdschema:xAL:2.0}AddressDetails')
if ad.get("Accuracy") == "5" or ad.get("Accuracy") == "6":
continue
else :
addr = placemark.findtext('.//{%s}address' % namespace)
break
addr = addr.replace(u'日本', '', 1)
return addr

2009-09-20

Google Static Maps API で表示した画像の端っこの緯度経度を調べる

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
Google Static Maps APIで地図画像を作成できますが、作成した画像の一番上やら右端などがどんな緯度経度なのかを知りたいときがあります。

方法としては、
http://da-studio.blogspot.com/2008/04/google-static-maps-api.html
を見ればわかります。

理論に関しては、まったくわからないですが
ズームサイズと画像サイズから、地図に表示されている
(地図の一番上の座標)-(地図の一番下の座標)
の値がわかるようです。

これがわかれば、中心座標に求めれた数値の半分を足したり引いたりすれば、端っこの座標を求めることができるのです。

リンク先にphpのサンプルコードがあるので、こちらではpythonのコードを書いてみます。

#画像縦サイズ:ysize
#画像縦サイズ:xsize
#画像中心緯度:clat
#画像中心軽度:clon
#縦横の表示域を算出
lx=float(xsize)/pow(2,float(zoom))
ly=float(ysize)/pow(2,float(zoom))

#小数点以下をいい感じに丸める処理
lattop = round((float(clat)+ly/2)*1000000)/1000000
latbtm = round((float(clat)-ly/2)*1000000)/1000000
lontop = round((float(clon)+ly/2)*1000000)/1000000
lonbtm = round((float(clon)-ly/2)*1000000)/1000000


表示域を算出するときに、念のため値をfloatで囲んでおくのが良さげです。
何も考えずに使っていたら、それぞれintとして取り扱うコードになっていて、
算出結果が0とかになったりしたもので。

2009-08-06

Google Mapplets APIをテストする

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
Google Mappletsというのは、自分のサイトの中にGoogle Mapの機能を持ってくるのとは逆に自分の作ったものをGoogle Mapに取り込んでもらうものです。
実際に利用するには、Mapplets用のjavaスクリプト入りのXMLを用意して、それをgoogleさんに読み込んでもらうことになります。
Googleさんに読み込んでもらうにはどっかに置いとかないといけないわけですが、動くかどうかわからないものを置くのも心苦しいわけです。
なのでまずはテストが必要なわけですが、そこは流石Googleさんなのでちゃんとスクリプトをテストする環境が用意されているわけです。
http://maps.google.co.jp/gadgets/directory?synd=mpl&hl=ja&backlink=http%3A%2F%2Fmaps.google.co.jp%2Fmaps%2Fmm%3Fie%3DUTF8%26hl%3Dja%26ll%3D35.689517%2C139.785946%26spn%3D0.307284%2C0.55481%26z%3D11&cat=devtools
にある
Mapplet Scratch Pad
というmappletをgoogleマップに追加して
Googleマップのマイマップを開くと
Mapplet Scratch Pad
が利用できるようになって、ここで自分書いたmappletのコードを試すことが出来るようになるわけです。
Mapplet Scratch Padは、
http://code.google.com/intl/ja/apis/maps/documentation/mapplets/guide.html#Important_Developer_Tools
にも重要ですよん。
と書いてあるのでMappletをいじる際には必ず利用した方がよいようです。