--- title: Emacs から HTTP リクエストを送信する author: kazu634 date: 2009-11-29 url: /2009/11/29/_1406/ 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:4957;}s:9:"hash_tags";a:0:{}s:8:"accounts";a:1:{i:0;s:7:"kazu634";}}' categories: - Emacs ---
id:hayamiz さんの twittering-mode のソースをのぞいていると、 Emacs だけで HTTP リクエストを送信していることを発見した。 Web 経由の API って、基本的には HTTP の get か post リクエストなんだから、 Emacs から Web API を利用することが出来るのではないかと考えてみた。
というわけで、 Google Mapジオコーディング API を使用してみようと考えてみました…でも、まだ途中です。とりあえず xml でレスポンスを入手するところまで出来ました。基本的には id:hayamiz さんのソースをぱくり参考にさせていただいております。
「*test-buffer*」というバッファーに HTTP レスポンスを表示させ、そこからごちゃごちゃと処理する流れになっています。
(require 'xml) ;; バッファーが存在しなければ、バッファーを作成する (defun GMap-get-or-generate-buffer (buffer) (if (bufferp buffer) (if (buffer-live-p buffer) buffer (generate-new-buffer (buffer-name buffer))) (if (stringp buffer) (or (get-buffer buffer) (generate-new-buffer buffer))))) ;; HTTP GETリクエストを送信する (defun GMap-http-get (address) "A method for sending http GET request to maps.google.com" (GMap-get-or-generate-buffer "*test-buffer*") (save-excursion (set-buffer "*test-buffer*") (erase-buffer)) (let ((proc nil) (query (url-hexify-string address))) (condition-case nil (progn (setq proc (open-network-stream "GMap-connection-process" "*test-buffer*" "maps.google.com" 80)) (set-process-sentinel proc 'test-sentinel) (process-send-string proc (let ((nl "\r\n")) (concat "GET /maps/geo?output=xml&hl=ja&q=" query "&ie=UTF8&oe=UTF8 HTTP/1.1" nl "Host: maps.google.com" nl "Keep-Alive: 10" nl "Accept: text/xml" ",application/xhtml+xml" ",application/html;q=0.9" ",text/plain;q=0.8" nl "Accept-Charset: utf-8;q=0.7,*;q=0.7" nl "Connection: close" nl nl)))) (error (message "Failure: HTTP GET") nil)))) ;; HTTP レスポンスからヘッダーの部分を抽出する (defun GMap-extract-http-response-header (&optional buffer) "A method for extracting http response. You need to give the buffer name as the argument." (save-excursion (set-buffer "*test-buffer*") (let ((content (buffer-string))) (substring content (string-match "\r?\n\r?\n" content))))) ;; HTTP レスポンスからボディーの部分(XML)を抽出する (defun GMap-extract-http-response-body (&optional buffer) "A method for extracting http response body from HTTP response." (if (stringp buffer) (setq buffer (get-buffer buffer))) (if (null buffer) (setq buffer "*test-buffer*")) (save-excursion (set-buffer buffer) (let ((content (buffer-string))) (xml-parse-region (+ (string-match "\r?\n\r?\n" content) (length (match-string content))) (point-max))))) ;; GET リクエストを送信して、レスポンスが返ってきたら実行される関数 (defun test-sentinel (proc state) (let ((header (GMap-extract-http-response-header)) (status nil)) (if (string-match "HTTP/1\.[01] \\([A-Z0-9 ]+\\)\r?\n" header) (progn (setq status (match-string-no-properties 1 header)) (case-string status (("200 OK") (message "Success: Get.")) (t (message status)))) (message "Failure: Bad HTTP response."))))
下記のコマンドを実行してみてください。とりあえずレスポンスは取得できています。後はこれをどうつかうかだな:
(GMap-http-get "横浜") (GMap-extract-http-response-header) (GMap-extract-http-response-body)