--- title: gauche でウェブAPIをたたく — その1 author: kazu634 date: 2010-02-14 url: /2010/02/14/_1471/ 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:5115;}s:9:"hash_tags";a:0:{}s:8:"accounts";a:1:{i:0;s:7:"kazu634";}}' categories: - gauche - Lisp ---

Lispを使ってウェブAPIをたたき、xmlを取得しました。http getメソッドを使う tumblr の記事を取得します。

httpリクエストを送る

http-getを用います:

ここでpathはリクエストURIのパスコンポーネントまでを指定する 文字列です。与えられたnameとvalueのalistから、 httpリクエスト手続きはHTML4で定められた application/x-www-form-urlencoded形式の クエリ文字列を構成し、pathにアペンドします。 例えば次のふたつのリクエストは同じ効果を持ちます。 二番目の呼び出しではurlエスケープが自動的に行われることに注目してください。

(http-get "example.com" "/search?q=foo%20bar&n=20")
(http-get "example.com" '("/search" (q "foo bar") (n 20)))

Gauche ユーザリファレンス: 11.19 rfc.http – HTTP

getメソッドだとこれで十分です。postメソッドだとこれ以外にも指定するみたいです(そもそも、 http-post メソッドを使用する必要がある)。

http-getメソッドは、

  1. httpステータスコード
  2. httpレスポンスヘッダー
  3. httpボディー

の三つを返します(from 「Gauche ??? Amazon Web Services??? : torus solutions!」)。XML部分はボディーの部分なので、多値を受け取るようにしておく必要があります(後述のまとめを参照)。

文字コード変換する

次のようにするのがお約束(?)のようです:

(use gauche.charconv)
(let* ((raw-in (open-input-string str))
(in (open-input-conversion-port raw-in 'utf-8)))
;; do something
;; (display in) 
)

strの部分に変換する前の文字列を指定する。

XMLをS式に変換する

XMLをS式にしたものをSXMLと呼びます。sxml.ssaxモジュールを用いて、変換コマンドを使用できるようにします:

(use sxml.ssax)
(ssax:xml->sxml xml '())

xmlの部分にXML形式の文字列を指定してください。

まとめ

私のtumblrから引用を、テキスト形式に変更して取得するには次のようにします:

(use rfc.http)
(use sxml.ssax)
(use gauche.charconv)
;; http-getは多値を返すので、多値を受け取る
;; XML部分はbody部分だけのため、
;; http-get の戻り値を ssax:xml->sxml するとエラーになる
;; from http://torus.jp/memo/x200607/aws.rd.html
(define (get-sxml-from-tumblr user)
(let-values (((status header body)
(http-get
(string-append user ".tumblr.com")
"/api/read?type=quote?filter=text")))
;; status codeが200でなければ、空リストを返す
(when (not (equal? status "200")) '())
;; XMLが返ってきていれば、 SXML に変換する
(let* ((raw-in (open-input-string body))
(in (open-input-conversion-port raw-in 'utf-8)))
(ssax:xml->sxml in '()))))

このようにしてから、REPLで

gosh> (get-sxml-from-tumblr "kazu634)

とすれば取得したXMLをSXMLに変換したものが表示されます。

プログラミングGauche

プログラミングGauche