とりあえず日記

VIM→秀丸エディタ→VIM→秀丸エディタ→VIM→秀丸エディタ→VIM→秀丸エディタ→VIM→秀丸エディタ→VIM→秀丸エディタ(いまここ🍄)

google suggestで入力候補してみる

google検索すると出てくる「もしかして」のアレです。
今更ですが・・・

大まかな手順

  1. キーワードをUTF8でURLエンコードする
  2. googleへ(1)で作った文字列を送る
  3. 候補をXMLで返してくる
  4. 箇所を正規表現で抜き出す
  5. お好きに加工する

具体的には

キーワードをUTF8でURLエンコードする。
エンコード エンコード
のびた %E3%81%AE%E3%81%B3%E3%81%9F

googleのアドレス
http://google.com/complete/search?output=toolbar&q=%E3%81%AE%E3%81%B3%E3%81%9F

HTTPでやりとりする

秀丸マクロは以下の通り

HttpGet:
    // $$1 = URI
    // $$return = ResponseText
    #http = createobject("Msxml2.XMLHTTP");
    if (!#http) #http = createobject("Microsoft.XMLHTTP");
    if (!#http) return "";
    callmethod #http, "Open", "GET", $$1, false;
    callmethod #http, "Send";
    $$response = getpropstr(#http, "ResponseText");
    releaseobject #http;
    return $$response;
googleが返してくるXML
<?xml version="1.0"?>
<toplevel>
    <completesuggestion>
        <suggestion data="のび太"/>
        <num_queries int="8180000"/>
    </completesuggestion>
    <completesuggestion>
        <suggestion data="のび太のバイオハザード"/>
        <num_queries int="93200"/>
    </completesuggestion>
    <completesuggestion>
        <suggestion data="のび太のbiohazard"/>
        <num_queries int="360000"/>
    </completesuggestion>
    <completesuggestion>
        <suggestion data="のび太と鉄人兵団"/>
        <num_queries int="46500"/>
    </completesuggestion>
</toplevel>
正規表現で抜き出す

正規表現で""の間にある文字列を抜き出します。

(?\1)<suggestion data="([^"]+)"/>

そうすると、下記文字列を取得できます。

ここまで出来れば後は如何様にも加工できます。

ソースコード(google_suggest_sub.js)

//google_suggest_sub.js
var text="";
while(!WScript.StdIn.AtEndOfStream){
	text+=WScript.StdIn.ReadAll();
}
WScript.StdOut.Write(
	encodeURI(text)
);

ソースコード(google_suggest.mac)

ソースコードgithubにアップしました。(右上のダウンロードからzipを選択してください)
https://github.com/ohtorii/google_suggest

$$old_searchbuffer = searchbuffer;
##old_searchoption = searchoption;
disabledraw;
call Main;
enabledraw;
setsearch $$old_searchbuffer, ##old_searchoption;
endmacro;

#g_suggestion_num 		= 0;
$g_suggestion_str[0] 	= "";

Main:
	if(rectselecting){
		return false;
	}
	
	#is_selectline = false;
	if (!selecting) {
		#is_selectline = true;
		selectline;
	}
	$$text = gettext(seltopx, seltopy, selendx, selendy, true);
	if(!strlen($$text)){
		return false;
	}

	call GetSuggestString $$text;
	if(! ##return){
		return false;
	}
	if(#g_suggestion_num){
		menuarray $g_suggestion_str, #g_suggestion_num;
		if(0<result){
			##index = result - 1;
			begingroupundo;
			insert($g_suggestion_str[##index]);
			if(#is_selectline){
				insert("\n");
			}
			endgroupundo;
		}
	}

	return true;


/*
(入力)のびたの
(出力)
#g_suggestion_num 		= 2;
#g_suggestion_str[0] 	= "のび太の 結婚前夜";
#g_suggestion_str[1] 	= "のび太の くせになまいきだ";
*/
GetSuggestString:
	$$text = $$1;
	##old_hidemaru = hidemaruhandle(0);

	openfile "/h";

	##cur_hidemaru = hidemaruhandle(0);
	insert $$text;

	//「改行」があれば削除しておく
	replaceallfast "\\n","",regular;

	selectline;
	call RunEncodeURL_UTF8;

	selectline;
	$$encode_text = gettext(seltopx, seltopy, selendx, selendy, false);
	//備考:"&hl=ja"はロケール指定っぽい。「つける・つけない」でgoogleが返してくる候補が変わります。
	call HttpGet "http://google.com/complete/search?output=toolbar&q=" + $$encode_text + "&hl=ja";
	$$xml_text = $$return;
	//message($$xml_text);

	selectall;
	backspace;
	insert $$xml_text;
	gofiletop;

	$$reg = "(?\\1)<suggestion data=\"([^\"]+)\"/>";
	searchdown $$reg, nocasesense, regular;
	##tmp_result = result;
	while(##tmp_result){
		$$text = gettext(seltopx, seltopy, selendx, selendy, true);
		$g_suggestion_str[#g_suggestion_num] = $$text;
		#g_suggestion_num 					 = #g_suggestion_num + 1;
		finddown;
		##tmp_result = result;
	}

	setactivehidemaru	##old_hidemaru;
	closehidemaruforced ##cur_hidemaru;

	return true;


/*UTF8でURLエンコードを行う。
(入力)のびたの
(出力)%E3%81%AE%E3%81%B3%E3%81%9F%E3%81%AE
*/
RunEncodeURL_UTF8:
	$$mod = currentmacrodirectory+"\\google_suggest_sub.js";
	$$mod = "\"" + $$mod + "\"";
	runex 	"cscript.exe //U //nologo " + $$mod, 1
			,5,""
			,6,""
			,1,""
			,2,currentmacrodirectory
			,2,1,2;
	return ;


HttpGet:
	// $$1 = URI
	// $$return = ResponseText
	#http = createobject("Msxml2.XMLHTTP");
	if (!#http) #http = createobject("Microsoft.XMLHTTP");
	if (!#http) return "";
	callmethod #http, "Open", "GET", $$1, false;
	callmethod #http, "Send";
	$$response = getpropstr(#http, "ResponseText");
	releaseobject #http;
	return $$response;