elisp で http client + とってきた http ソースから必要な部分を正規表現でぶっこ抜く

まだ, 完成ではないけど,
翻訳したい文字列を翻訳サイトに送って, その結果を http のソースでもらい,
そして, 必要な翻訳結果の部分のみを正規表現で抜きとる, ここまでできた.
ほぼオッケーといいたいところだけど, うーん・・・なんだよなあ.
とりあえず, ソース.

ソース

;;; -*- Coding: iso-2022-7bit -*-
;; http client を作ってみるテスト

(defvar text-translator-site-data-list
  '(("excite_enja" "www.excite.co.jp" "POST /world/english/ HTTP/1.0"
     "wb_lp=ENJA&before=%s" japanese-shift-jis-dos
     "<input type=\"hidden\" name=\"after\" value=\"\\([^\"]*\\)")

    ("excite_jaen" "www.excite.co.jp" "POST /world/english/ HTTP/1.0"
     "wb_lp=JAEN&before=%s" japanese-shift-jis-dos
     "<input type=\"hidden\" name=\"after\" value=\"\\([^\"]*\\)")

    ("google_enja" "translate.google.com" "POST /translate_t HTTP/1.0"
     "langpair=en|ja&ie=utf-8&oe=utf-8&text=%s" utf-8-dos
     "<div id=result_box dir=ltr>\\([^<]*\\)")

    ("google_jaen" "translate.google.com" "POST /translate_t HTTP/1.0"
     "langpair=ja|en&ie=utf-8&oe=utf-8&text=%s" utf-8-dos
     "<div id=result_box dir=ltr>\\([^<]*\\)")

    ("altavista_enja" "babelfish.altavista.com" "POST /tr HTTP/1.1"
     "doit=done&intl=1&tt=urltext&trtext=%s&lp=en_ja&btnTrTxt=Translate"
     utf-8-dos
     "	    <td class=s><input type=hidden name=\"q\" value=\"\\([^\"]*\\)")

    ("altavista_jaen" "babelfish.altavista.com" "POST /tr HTTP/1.1"
     "doit=done&intl=1&tt=urltext&trtext=%s&lp=ja_en&btnTrTxt=Translate"
     utf-8-dos
     "	    <td class=s><input type=hidden name=\"q\" value=\"\\([^\"]*\\)")))

(defvar text-translator-wait-second 2)

(defun text-translator-client (type string)
  "指定したサイトに翻訳したい語句を投げ, 翻訳結果を受け取る関数."
  (let* ((buf "*http fetch*")
         (proc (open-network-stream "Web Connection" buf (nth 1 type) 80))
         (enc-str (text-translator-url-encode-string string (nth 4 type)))
         (post-str (progn (string-match "%s" (nth 3 type))
                          (replace-match enc-str nil nil (nth 3 type)))))
    (with-current-buffer (get-buffer-create buf)
      (erase-buffer)
      (set-process-coding-system proc (nth 4 type) 'binary)
      (process-send-string
       proc
       (format "%s%s%s%s%s%s%s%s%s%s%s%s%s"
               (nth 2 type) "\r\n"
               (concat "HOST: " (nth 1 type)) "\r\n"
               "Accept-Charset: Shift_JIS,utf-8;q=0.7,*;q=0.7\r\n"
               "Content-Type: application/x-www-form-urlencoded\r\n"
               "Content-Length: "
               (string-bytes post-str) "\r\n"
               "\r\n"
               post-str "\r\n"
               "\r\n"))
      (sleep-for text-translator-wait-second)
      (re-search-backward (nth 5 type))
      (match-string 1))))
(text-translator-client (nth 1 text-translator-site-data-list) "日本語")

;; google2.el より拝借.
(defun text-translator-url-encode-string (str &optional coding)
  (apply (function concat)
         (mapcar
          (lambda (ch)
            (cond
             ((eq ch ?\n)               ; newline
              "%0D%0A")
             ((string-match "[-a-zA-Z0-9_:/]" (char-to-string ch)) ; xxx?
              (char-to-string ch))      ; printable
             ((char-equal ch ?\x20)     ; space
              "+")
             (t
              (format "%%%02X" ch))))   ; escape
          ;; Coerce a string to a list of chars.
          (append (encode-coding-string (or str "") (or coding 'iso-2022-jp))
                  nil))))

;; end

実行するには, 上のコードの中にある, この関数,

(text-translator-client (nth 1 text-translator-site-data-list) "日本語")

これを実行すればオッケー.
nth の引数は, 0から5までを今のところ取る.
0,1 が excite. 2,3 が google. 4,5 が altavista.
ちなみに, google2.el より拝借したという関数の元の関数は, w3m-url-encode-string みたいです.

問題点

何が微妙か.
関数 text-translator-client の中の下の方に, sleep-for 使ってる.
ここでは, 2秒間動作を止めて待つ, というとをさせてる.
なんで使ってるか. そうしないと上手くいかない・・・.
これ使わなかったら, re-search-backward で取ってこれない.
たぶん, process-send-string を使ってソースを取得し終わってから, re-search-backward が実行されるんじゃないんだと思う.
だから, バッファに文字列を出力してる最中に, 次の re-search-backward が実行される.
そして, マッチする部分が無い, という結果になるんだと思う.
2秒待つってだって, 2秒待って上手くいくかどうかも微妙だからねえ.
どうにかならないもんかなあ.
また, ruby script に戻すか? そうすれば少くともこういう事態にはならんと思うけど.

更新時刻

2007年, 4月27日, 3:50