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