[ 新規に投稿する ]

HttpGet での文字化けNo.07045
rosegardenyk さん 12/06/19 01:51 [ コメントを投稿する ]
いつもお世話になっています rosegardenyk です。
少し前に、IKKI さんにご教示いただいた HttpGet (下記sub routine 名) でほとんどの場合うまくいくのですが、下記の site の場合文字化けします。うまくいってる場合は HTMLのcharsetが皆 UTF-8 ですが、本例は下記の通り shift-JIS です。Insert先のファイルは、何も指定してしておらずshift-JISのままです。message でみても全角部分は文字化けしています。

Hidemarnet Explorerでは何の文字化けもありませんが、HttpGet でも文字化けさせない方法があるでしょうか? いろいろ試しましたがどうしてもわかりません。どなたかご教示いただければ感謝します。HttpGetの方が処理速度が早いのです。

 $uri1 = "http://www.nankodo.co.jp/yosyo/xforeign/nejm/366/366jun/xf366-24-2267.htm";
 call HttpGet $uri1;
 $text1 = $$return;
 insert $text1;


//** $$1: $uri ******************************************************************************************************
HttpGet:
 #http = createobject("Msxml2.XMLHTTP");
 if (!#http) #http = createobject("Microsoft.XMLHTTP");
 if (!#http) {message "オブジェクトの生成に失敗しました"; endmacro;}
 callmethod #http, "Open", "GET", $$1, false;
 callmethod #http, "Send";
 $$html = getpropstr(#http, "ResponseText");
 releaseobject #http;
return $$html;
******************

Hidemarnet Explorer の webソース表示
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-type" CONTENT="text/html; charset=Shift_JIS">
<TITLE>新生児 MRSA 集団感染調査のための高速全ゲノム配列決定</TITLE>
</HEAD>
以下略

と出るはずのものが下記にように文字化けします。

<HTML>
<HEAD>
<META HTTP-EQUIV="Content-type" CONTENT="text/html; charset=Shift_JIS">
<TITLE>&#65535;V&#65535;&#65535;&#65535;&#65535; MRSA &#65535;W&#65535;c&#65535;&#65535;&#65535;&#65535;&#65535;&#65535;&#770;&#65535;&#65535;&#1986;&#781;&#65535;&#65535;&#65535;&#65535;S&#65535;Q&#65535;m&#65535;&#65535;&#65535;z&#65535;&#311826;&#65535;TITLE>
</HEAD>
以下略

上記site は通常はhttp://www.nankodo.co.jp/yosyo/xforeign/nejm/xf2hm.htm 
からはいっていくもので上記内容が表示されてもアドレスバーの表示は変わりません。 個別の飛び先のurl右クリックをコピーしたものが
http://www.nankodo.co.jp/yosyo/xforeign/nejm/366/366jun/xf366-24-2267.htm
です。  
[ ]
RE:07045 HttpGetでの文字化けNo.07046
h-tom さん 12/06/19 06:08 [ コメントを投稿する ]
 
h-tom です。

似たような事があったと思ったら、この件と同じかな?
http://forum.mobitan.org/hm/index.php?all=2174&log=10

正確にいうと、SHIFT_JISがダメというより、サーバーからのレスポンスヘッダの
Content-Type に charset指定がないと、utf-8として処理するようなので、utf-8
以外だと化けるようです。

webサイトによって、処理を分けるしかないかな?
[ ]
RE:07046 HttpGetでの文字化けNo.07047
rosegardenyk さん 12/06/19 12:56 [ コメントを投稿する ]
h-tom さん、いつも的を得たお返事ありがとうござ思います。

>正確にいうと、SHIFT_JISがダメというより、サーバーからのレスポンスヘッダの>Content-Type に charset指定がないと、utf-8として処理するようなので、utf-8 以外だと化けるようです。
charset指定の問題だったのですね。理由がわかってよかったです。

>webサイトによって、処理を分けるしかないかな?
http://forum.mobitan.org/hm/index.php?all=2174&log=10
に Ikkiさんのコメント(IKKI 2009/08/22 02:02)
「WSH だと ADODB.Stream を使って変換するのが常套手段みたいですが、バイナリデータである ResponseBody を秀丸マクロで扱うのは無理かな…。」とありますが、やはり、今でも「ならぬものは、ならぬ。」のでしょうか?
[ ]
RE:07047 HttpGetでの文字化けNo.07048
秀丸担当 さん 12/06/19 16:33 [ コメントを投稿する ]
 
調べてみたところ、Msxml2.XMLHTTPオブジェクトのresponseBodyのプロパティは、
バイトの配列(いわゆるバイナリデータ)が返っているようです。
そしてADODB.StreamオブジェクトのWriteメソッドはバイナリデータを渡せるよ
うです。

秀丸マクロのCOMは数値と文字列とオブジェクトしか扱えず、現在のところバイ
ナリデータは扱えません。
最近の話で、オブジェクトをメソッドのパラメータに渡せない文法上の問題を解
決するために、V8.02β23でallowobjparam文を追加しました。

これと同じ方法で、バイナリデータを文字列として表すようにして、文字列をバ
イナリデータとして解釈することを許可できるようにすれば、文法上の問題を回
避してできると思います。
そういう方法を検討してみます。

ちなみにバイナリデータを文字列として表す手法としては、現状でも
getregbinary,writeregbinaryがあります。
[ ]
RE:07048 HttpGetでの文字化けNo.07049
rosegardenyk さん 12/06/20 19:21 [ コメントを投稿する ]
秀丸担当どの
>これと同じ方法で、バイナリデータを文字列として表すようにして、文字列をバイナリデータとして解釈することを許可できるようにすれば、文法上の問題を回避してできると思います。そういう方法を検討してみます。
恐れ入ります。焦らず検討の結果をお待ちします。
[ ]
RE:07049 HttpGetでの文字化けNo.07051
秀丸担当 さん 12/06/21 14:23 [ コメントを投稿する ]
 
V8.20β24でバイナリも扱えるようにしました。
allowobjparam 2; で許可すると、文字列をバイナリとして扱うことを許可しま
す。
第二パラメータ以降で明示的にパラメータごとに指定する方法も追加しました。

responseBodyとADODB.Streamを使った例:

$strOutput = "Output.txt";
$strUrl = "http://hide.maruo.co.jp/";

question $strOutput + "に\n" + $strUrl + "の内容を保存していいですか?"; 
if( result == no ) endmacro;

#objHttp = createobject("Msxml2.XMLHTTP");
callmethod #objHttp, "Open", "GET", $strUrl, 0;
callmethod #objHttp, "Send";

#objStream = createobject( "ADODB.Stream" );
callmethod #objStream, "Open";
setpropnum #objStream, "Type", 1;//adTypeBinary

allowobjparam 2;
$binBody = getpropstr( #objHttp, "responseBody" );
callmethod #objStream, "Write", $binBody;
allowobjparam 0;

callmethod #objStream, "SaveToFile", $strOutput, 2;
                         //2:adSaveCreateOverWrite
callmethod #objStream, "Close";

openfile $strOutput;
[ ]
(発言者削除)No.07055
rosegardenyk さん 12/06/22 16:37
 
[ ]
RE:07051 HttpGetでの文字化けNo.07056
rosegardenyk さん 12/06/22 17:03 [ コメントを投稿する ]
秀丸担当殿
>responseBodyとADODB.Streamを使った例:
>$strOutput = "Output.txt";
>$strUrl = "http://hide.maruo.co.jp/";
次のcharset=Shift_JISとなっているsiteに対しても試してみました。
A:http://www.nankodo.co.jp/yosyo/xforeign/nejm/366/366jun/xf366-24-2267.htm
成功です。素晴らしい処理速度です。ありがとうございます。こんなに早く対応して下さるなんて感激しています。本当に感謝します。


質問
@charset=UTF-8となっているsiteには既存のHttpGet方式で取り出せばよいと思いますが、このようなsite 例えば
C:http://www.nejm.org/doi/full/10.1056/NEJMoa1109910
に対しては上記の新方式ではHTML内容を取り出せないようです。site だけわかっていてcharsetが既知でない場合はどうしたらよいと思いますか?charsetが何であれ対応できるcodeが書けるでしょうか?日本語のsite でもcharsetがUTF-8のところはあります。私が書くと$strOutputが空なら、HttpGet方式でやり直すというふうになってしまいますが、やるとしたらそんなもんでしょうか。それともコンパクトにすることは可能でしょうか?


A上記の新方式とは関係ない話かもしれませんが。
A:のアドレスをIEなど通常のブラウザーで開くと、原文の論文が掲載されているlinkがあって、そのlinkアドレスをコピーすると、
B: http://content.nejm.org/cgi/content/short/366/24/2267
のアドレスですが、これを使って、HTML内容を取り出そうとすると、httpGet方式でも上記新方式でも取り出しに失敗します。(空の戻り値)

ブラウザーでA: を開きそこに表示されている 原文への link 先をダブルクリックするとアドレスが
C: http://www.nejm.org/doi/full/10.1056/NEJMoa1109910
に変わっています。無論ここで英語原文を読むことができます。

現在私は、vol.366/number 24/page 2267といった情報を頼りに、negm.org のアーカイブ site のHTMLデータを順に検索、分析して何とかB:のアドレスにたどり着く方法を見つけたのでC:http://www.nejm.org/doi/full/10.1056/NEJMoa1109910 
のアドレスを使ってHttpGet方式でHTML内容を取り出しています。
B:http://content.nejm.org/cgi/content/short/366/24/2267 のアドレスから直接HTML内容を取り出す方法は考えられますでしょうか?  
このC: のようなアドレス情報がいつも入手できるとは限りません。

(内部的な変換が行われていてそれに時間がかかるのでしょうか?、B:のアドレスを使うと通常のブラウザーでも、C:のアドレスに比べ表示されるまでに時間がかかります。Hidemarnet Explorerでも表示できますが、IE、Chromeよりさらに時間がかかります。また英文なのでHidemarnet Explorerを使う理由もないわけですAの質問は、手間がかかるようでしたらネグって下さい。なぜ取り出せないのか理由が知りたいだけです。)
[ ]
RE:07056 HttpGetでの文字化けNo.07057
秀丸担当 さん 12/06/22 17:33 [ コメントを投稿する ]
 
>質問
>@charset=UTF-8となっているsiteには既存のHttpGet方式で取り出せばよいと思いま
>すが、このようなsite 例えば
>C:http://www.nejm.org/doi/full/10.1056/NEJMoa1109910

このURLで前のマクロで試してみたところでは、取得できました。
先頭に空行が多くあるので、スクロールしたら内容が見えるかもしれないです。

>A上記の新方式とは関係ない話かもしれませんが。
>A:のアドレスをIEなど通常のブラウザーで開くと、原文の論文が掲載されているlink
>があって、そのlinkアドレスをコピーすると、
>B: http://content.nejm.org/cgi/content/short/366/24/2267

このアドレスは確かに取得できませんでした。
vbsでやると、「アクセスが拒否されました」とエラーメッセージが出ました。

秀丸マクロの場合、vbsのようにエラーメッセージは出ず、getresultexで成否を
取得する必要があります。
以下のようにすると成否がわかります。

  callmethod #objHttp, "Send";
  message "callmethod成否:"+str(getresultex(10));

ちなみにwww.google.comでもアクセス拒否でした。ブラウザで見るとwww.google.
co.jpにリダイレクトさるので、リダイレクトはだめとか、リファラーが無いと
だめとか、Msxml2.XMLHTTPでアクセスするんひあいろいろサイトによって条件が
あるのかもしれないです。
このあたりの話になると、Msxml2.XMLHTTPオブジェクトの上手な使い方というこ
とになってきて、Web検索して得られるvbsやjscriptなどの情報を手がかりにし
たほうがいいかもしれないです。
[ ]
RE:07057 HttpGetでの文字化けNo.07058
rosegardenyk さん 12/06/22 20:12 [ コメントを投稿する ]
早速のお返事ありがとうございます。
>>C:http://www.nejm.org/doi/full/10.1056/NEJMoa1109910
>このURLで前のマクロで試してみたところでは、取得できました。
>先頭に空行が多くあるので、スクロールしたら内容が見えるかもしれないです。
おっしゃる通りでした。ということは新方式でやればはcharsetに関係なく使えるということになりますね。こんな素晴らしい方式をありがとうございます。

>>B: http://content.nejm.org/cgi/content/short/366/24/2267
>このアドレスは確かに取得できませんでした。
>vbsでやると、「アクセスが拒否されました」とエラーメッセージが出ました。
>秀丸マクロの場合、vbsのようにエラーメッセージは出ず、getresultexで成否を取得する必要があります。
>以下のようにすると成否がわかります。
>
>  callmethod #objHttp, "Send";
>  message "callmethod成否:"+str(getresultex(10));
トライしてうまくB:0及びC:1と表示されした。
手の打ちようがないので、拒否されて駄目なものはだめですね。

>ちなみにwww.google.comでもアクセス拒否でした。ブラウザで見るとwww.google.
>co.jpにリダイレクトさるので、リダイレクトはだめとか、リファラーが無いとだめとか、Msxml2.XMLHTTPでアクセスするんひあい(場合?)ろいろサイトによって条件が>あるのかもしれないです。
>このあたりの話になると、Msxml2.XMLHTTPオブジェクトの上手な使い方というこ>とになってきて、Web検索して得られるvbsやjscriptなどの情報を手がかりにしたほうがいいかもしれないです。
ありがとうございます。vbsやjscript?はチンプンカンプンです。
「リダイレクトはだめとか」かもしれないですね。
今回もいろいろありがとうございました。


[ ]
RE:07058 HttpGetでの文字化けNo.07059
rosegardenyk さん 12/06/23 11:12 [ コメントを投稿する ]
http://www.maruo.co.jp/hidesoft/4/x07045_.html#7051
で例示していただいた code はfileに落とす例だったので、これを見れば 文字変数に取り込む用に直すのは容易かと思っていろいろ試したのですがCOMの知識がないためうまくいきません。 どうぞご教示ください。
[ ]
RE:07059 HttpGetでの文字化けNo.07060
h-tom さん 12/06/23 20:05 [ コメントを投稿する ]
 
h-tom です。

>http://www.maruo.co.jp/hidesoft/4/x07045_.html#7051
>で例示していただいた code はfileに落とす例だったので、これを見れば 文字変数
>に取り込む用に直すのは容易かと思っていろいろ試したのですがCOMの知識がないた
>めうまくいきません。 どうぞご教示ください。

参考にした所
http://homepage2.nifty.com/nonnon/SoftSample/SampleModADOS.html

担当さんの書いたマクロの、以下の部分を変更して下さい。
$OUTTEXTに、内容が入ります。

実際に動かすには、$charset に適切な文字セットを入れる必要があります。
metaタグから、charsetの内容を切り出して、設定して下さい。


//------------ 変更前 ここから
callmethod #objStream, "SaveToFile", $strOutput, 2;
                         //2:adSaveCreateOverWrite
callmethod #objStream, "Close";
openfile $strOutput;
//------------ 変更前 ここまで


//------------ 変更後 ここから
//Posionを先頭にセットしないと、うまく変換しない
setpropnum #objStream, "Position", 0;
//データ型をテキストに設定
setpropnum #objStream, "Type", 2;//adTypeText
//Streamの内容を変換する文字セット
setpropstr #objStream, "charset", $charset;
//Streamの内容をテキストとして読み込み
$OUTTEXT = callmethod_returnstr(#objStream, "ReadText");//, -1); // -1:adReadAll
callmethod #objStream, "Close";
releaseobject #objStream;
releaseobject #objHttp;

newfile;
insert $OUTTEXT;
endmacro;
//------------ 変更後 ここまで
[ ]
(発言者削除)No.07061
rosegardenyk さん 12/06/24 01:11
 
[ ]
RE:07060 HttpGetでの文字化けNo.07062
rosegardenyk さん 12/06/24 06:33 [ コメントを投稿する ]
//TEST 用マクロ

// $uri = "http://www.nejm.org/doi/full/10.1056/NEJMoa041401";                                   //charset=utf-8
 $uri = "http://www.nankodo.co.jp/yosyo/xforeign/nejm/366/366jun/xf366-24-2267.htm"; //charset=Shift_JIS
 call HttpGetBinary $uri;
 $html = $$return;
 newfile;
 insert $html;
 endmacro;
// **** $$1 : Uri *************************************************************************************
HttpGetBinary:
 #objHttp = createobject("Msxml2.XMLHTTP");
 callmethod #objHttp, "Open", "GET", $$1, 0;
 callmethod #objHttp, "Send";

//charset自動判定用追加部分(始まり)
 $$html = getpropstr(#objHttp, "ResponseText");
 loaddll "hmjre.dll";
 #n = dllfunc("SetUnicodeIndexAutoConvert", 1);//unicode文字によるずれを解消
 ##pos = dllfunc("FindRegularNoCaseSense", "(?<=charset=).+?(?=\")", $$html, 0);//大文字表記のCHARSETもある
 $charset = midstr($$html, ##pos, dllfunc("GetLastMatchLength"));
 if (!getresultex(10)) message "Http内容の取得に失敗しました。"; else message "charset = " + $charset + " のHttp内容を取得しました。";
//charset自動判定用追加部分(終わり)
 
 #objStream = createobject( "ADODB.Stream" );
 callmethod #objStream, "Open";
 setpropnum #objStream, "Type", 1;//adTypeBinary

 allowobjparam 2;
 $binBody = getpropstr( #objHttp, "responseBody" );
 callmethod #objStream, "Write", $binBody;
 allowobjparam 0;
 
 setpropnum #objStream, "Position", 0; //Posionを先頭にセットしないと、うまく変換しない
 setpropnum #objStream, "Type", 2;//adTypeText  //データ型をテキストに設定
 setpropstr #objStream, "charset", $charset; //Streamの内容を変換する文字セット
 $OUTTEXT = callmethod_returnstr(#objStream, "ReadText");  //, -1); // -1:adReadAll  //Streamの内容をテキストとして読み込み

 callmethod #objStream, "Close";
 releaseobject #objStream;
 releaseobject #objHttp;
return $OUTTEXT;
[ ]
RE:07062 HttpGetでの文字化けNo.07063
rosegardenyk さん 12/06/24 12:19 [ コメントを投稿する ]
h-tomさん、いつも懇切丁寧なcodeありがとうございます。
削除して送付しなおしたら、お礼の言葉部分が取れてました。改めてお礼申し上げます。
>実際に動かすには、$charset に適切な文字セットを入れる必要があります。metaタグから、charsetの内容を切り出して、設定して下さい。
この部分 07062 コメント http://www.maruo.co.jp/hidesoft/4/x07045_.html?a=2#7062 のように自動化してみました。同じ site でも古いものは、CHARSET=x-sjis と大文字表記になっており(今はcharset)"FindRegularNoCaseSense" にしてあります。また古いShift_JISの表記x-sjisでも問題はないようです。

>参考にした所
>http://homepage2.nifty.com/nonnon/SoftSample/SampleModADOS.html
不慣れで、まだよく理解できないのですが、できるだけ調べてからお聞きするようにします。


[ ]
RE:07063 HttpGetでの文字化けNo.07064
rosegardenyk さん 12/06/24 22:53 [ コメントを投稿する ]
理由のわからないエラーに悩んでいます。
次のTEST 用マクロでquestionに対し 1 回目、2 回目とも「はい」、「はい」と選ぶと
「マクロエラー文字列が長すぎます。
エラー箇所の内容 (変換箇所)
 $binBody = getpropstr( #objHttp, "responseBody" );
 callmethod #objStream, "Write", $binBody;
 allowobjparam 0;  」
というエラーメッセージがでます。
それ以外の組み合わせでは(例えば 「いいえ」、「はい」でも、「はい」、「いいえ」でも)エラーは出ず、2回目のHTML内容を取得します。1回目の「はい」で HttpGetBinary を実行した場合その結果を引きずっているようです。1 回目、2 回目とも「はい」、「はい」とした場合の合計文字数が長すぎますと読めてしまうのですが、なぜそうなのか、またこれを防ぐ方法がわかりません。お分かりになるようでしたらご教示ください。HttpGetBinary内に変数は、あえて$$xxxや##xxxのローカル変数に変えてあります。(特に効果は無いようですが…)



//TEST 用マクロ
 $uri0 =  "http://www.nejm.org/toc/nejm/338/7";
question "1  はい:1 回目の HttpGetBinary を実行、 いいえ: パスする。"; if (!result) goto Jump: 
 call HttpGetBinary $uri0;
Jump:
message "2   1 回目の HttpGetBinaryの後ろにきました。";
 $html0 = $$return;
 loaddll "hmjre.dll";

question "3 はい:HTML内容が長いと思いわれるHTMLを選ぶ  いいえ:短い方を選ぶ";
 if (result) $uri2 = "http://www.nejm.org/doi/full/10.1056/NEJM199802123380701";
 else $uri2 = "http://www.nejm.org/doi/full/10.1056/NEJMoa041401";
 call HttpGetBinary $uri2 ;
message "4    2 回目の HttpGetBinaryの後ろにきました。";
 $text2 = $$return;
 newfile;
 insert $uri2 + "\n\n" + $text2;
 endmacro;
// **** $$1 : Uri *************************************************************************************
HttpGetBinary:
 ##objHttp = createobject("Msxml2.XMLHTTP");
 callmethod ##objHttp, "Open", "GET", $$1, 0;
 callmethod ##objHttp, "Send";
 $$html = getpropstr(##objHttp, "ResponseText");
 loaddll "hmjre.dll";
 ##n = dllfunc("SetUnicodeIndexAutoConvert", 1);//unicode文字によるずれを解消
 ##pos = dllfunc("FindRegularNoCaseSense", "(?<=charset=).+?(?=\")", $$html, 0);
 $$charset = midstr($$html, ##pos, dllfunc("GetLastMatchLength"));
 if (!getresultex(10)) message "Http内容の取得に失敗しました。";
 else message "charset = " + $$charset + " のHttp内容を取得しました。";
 
 ##objStream = createobject( "ADODB.Stream" );
 callmethod ##objStream, "Open";
 setpropnum ##objStream, "Type", 1;//adTypeBinary

 allowobjparam 2;
 $$binBody = getpropstr( ##objHttp, "responseBody" );
 callmethod ##objStream, "Write", $$binBody;
 allowobjparam 0;
 
 setpropnum ##objStream, "Position", 0; //Posionを先頭にセット
 setpropnum ##objStream, "Type", 2;//adTypeText  //データ型をテキストに設定
 setpropstr ##objStream, "charset", $$charset; //Streamの内容を変換する文字セット
 $$output_text = callmethod_returnstr(##objStream, "ReadText"); // -1:adReadAll (Stream内容をテキストとして読み込む)

 callmethod ##objStream, "Close";
 releaseobject ##objStream;
 releaseobject ##objHttp;
return $$output_text;
[ ]
RE:07064 HttpGetでの文字化けNo.07065
秀丸担当 さん 12/06/25 09:42 [ コメントを投稿する ]
 
>理由のわからないエラーに悩んでいます。
>次のTEST 用マクロでquestionに対し 1 回目、2 回目とも「はい」、「はい」と選ぶ
>と
>「マクロエラー文字列が長すぎます。

このエラーは、エラーメッセージの通りで、文字列が長すぎるということになり
ます。
変数のサイズは、もともと4KBくらいが上限で、作業用のURL等の文字列しか扱え
ませんでしたが、V8.00/V8.10以降で拡張して、使っている全ての変数の総計で
約1MBまで扱えるようにしました。
総計なので、使っていない変数があれば $a=""; といった感じで空にしておくと、
より多く使えることになります。

例えば、今回の場合、1つ目の処理の後、
 $html0 = "";
 $$return = "";
としておくと使える量を多く確保できます。

とはいえやはり上限はあるので、HTMLのサイズによっては1つだけの処理でも上
限を超えてしまうことがあると思います。
[ ]
RE:07065 HttpGetでの文字化けNo.07066
rosegardenyk さん 12/06/25 13:36 [ コメントを投稿する ]
秀丸担当殿、早速のお返事ありがとうございます。
>このエラーは、エラーメッセージの通りで、文字列が長すぎるということになります。変数のサイズは、もともと4KBくらいが上限で、作業用のURL等の文字列しか扱えませんでしたが、V8.00/V8.10以降で拡張して、使っている全ての変数の総計で約1MBまで扱えるようにしました。総計なので、使っていない変数があれば $a=""; といった感じで空にしておくと、より多く使えることになります。
理由がはっきりしたところで対策を考えました。エラーメッセジのエラー箇所の内容 (変換箇所)が
 $binBody = getpropstr( #objHttp, "responseBody" );
とあったのでサブルーチン内のバイト変数で総計約1MB を超えたとわかりました。バイト変数($$binBodyは約0.6MBでした)は同じ内容のテキスト変数(約0.3MBでした)の約2倍あるようでした。そこで$$binBodyを経ないよう変更したところ、エラーがでなくなりました。また念のためcharset が utf-8 の場合はADODB.Streamを通す必要もないので、前のHttpGet同様 $$response = getpropstr(##objHttp, "ResponseText")でプロパティーからテキストを取得するようにしました。

>とはいえやはり上限はあるので、HTMLのサイズによっては1つだけの処理でも上限を超えてしまうことがあると思います。
本体マクロでは取得後の格納場所にできるだけ同じ変数を使うようにします。ついつい変数の合計使用可能なんて普段は考えてもいませんでした。Webから情報をはぎ取ってくるときの注意点ですね。その site のHTML 全部じゃなくて最初から最大XXXバイトだけ取ってこいみたいな命令コードがあるといいですね。charset=Shift_JIS の site ででかいHTMLだと困っちゃいますからね。 


//改善後TEST 用マクロ
 $uri0 =  "http://www.nejm.org/toc/nejm/338/7";
question "1  はい:1 回目の HttpGetBinary を実行、 いいえ: パスする。"; if (!result) goto Jump: 
 call HttpGetBinary $uri0;
Jump:
message "2   1 回目の HttpGetBinaryの後ろにきました。";
 $html0 = $$return;
 loaddll "hmjre.dll";

question "3 はい:HTML内容が長いと思いわれるHTMLを選ぶ  いいえ:短い方を選ぶ";
 if (result) $uri2 = "http://www.nejm.org/doi/full/10.1056/NEJM199802123380701";
 else $uri2 = "http://www.nejm.org/doi/full/10.1056/NEJMoa041401";
 call HttpGetBinary $uri2 ;
message "4    2 回目の HttpGetBinaryの後ろにきました。";
 $text2 = $$return;
 newfile;
 insert $uri2 + $html0 + "\n*******************************************************************************\n" + $text2;
 endmacro;
// **** $$1 : Uri *************************************************************************************
HttpGetBinary:
 ##objHttp = createobject("Msxml2.XMLHTTP");
 callmethod ##objHttp, "Open", "GET", $$1, 0;
 callmethod ##objHttp, "Send";
 $$html = getpropstr(##objHttp, "ResponseText");
 loaddll "hmjre.dll";
 ##n = dllfunc("SetUnicodeIndexAutoConvert", 1);//unicode文字によるずれを解消
 ##pos = dllfunc("FindRegularNoCaseSense", "(?<=charset=).+?(?=\")", $$html, 0);
 $$charset = midstr($$html, ##pos, dllfunc("GetLastMatchLength"));
 if (!getresultex(10)) message "Http内容の取得に失敗しました。";
//追加(始まり)
 else {
  message "charset = " + $$charset + " のHttp内容を取得しました。";
  if ($$charset == "utf-8") {
   $$response = getpropstr(##objHttp, "ResponseText");
    releaseobject ##objHttp;
   return $$response;
  }
 }
//追加(終わり)
 ##objStream = createobject( "ADODB.Stream" );
 callmethod ##objStream, "Open";
 setpropnum ##objStream, "Type", 1;//adTypeBinary

 allowobjparam 2;
//変更 $$binBody は変数を経由せずに次行のように直接 getpropstr( ##objHttp, "responseBody" )を書き込む;
 callmethod ##objStream, "Write", getpropstr( ##objHttp, "responseBody" );
 allowobjparam 0;
 
 setpropnum ##objStream, "Position", 0; //Posionを先頭にセット
 setpropnum ##objStream, "Type", 2;//adTypeText  //データ型をテキストに設定
 setpropstr ##objStream, "charset", $$charset; //Streamの内容を変換する文字セット
 $$output_text = callmethod_returnstr(##objStream, "ReadText"); // -1:adReadAll (Stream内容をテキストとして読み込む)
 callmethod ##objStream, "Close";
 releaseobject ##objStream;
 releaseobject ##objHttp;
return $$output_text;
[ ]
RE:07066 HttpGetでの文字化けNo.07067
rosegardenyk さん 12/06/25 15:03 [ コメントを投稿する ]

>>とはいえやはり上限はあるので、HTMLのサイズによっては1つだけの処理でも上限を超えてしまうことがあると思います。
>本体マクロでは取得後の格納場所にできるだけ同じ変数を使うようにします。ついつい変数の合計使用可能量に制約があるなんて普段は考えてもいませんでした。Webから情報をはぎ取ってくるときの注意点ですね。その site のHTML 全部じゃなくて最初から最大XXXバイトだけ取ってこいみたいな命令コードがあるといいですね。charset=Shift_JIS の site ででかいHTMLだと困っちゃいますからね。 
うっかりしましたが「HTMLのサイズによっては1つだけの処理でも上限を超えてしまうことがある」というのは、charset に関係ない話ですよね。だとすると、私にとっては大問題です。医学論文の長いやつがあるたびに取得できないかも知れないとヒヤヒヤしなければいけないわけですから。
そういえば、v8.11 から 「dllfuncのパラメータの長さ制限(16KB)を無くす。」となってこれはパラメータのバッファーサイズのはなしですがパラメータって文字変数のことがほとんどでこちらの制限がなくなったのに、通常の変数のサイズ合計に1MB程度という制限があるのもバランス悪くありませんか?
Web時代の秀丸活用という観点からは通常の変数のサイズ合計の制限もできれば外してほしいです。(少なくとも拡張)
[ ]
RE:07067 HttpGetでの文字化けNo.07068
秀丸担当 さん 12/06/25 15:58 [ コメントを投稿する ]
 
確かに今回バイナリも扱えるようにしたことで、足らないケースが増えてくると
思います。
拡張することは可能ですが、メモリの許す限りいくらでも…というようにするこ
とは、すみませんが難しいです。
秀丸エディタのマクロは複数の秀丸エディタ間を行き来して共有できるようにし
ているという都合上、32bit版においては4GBのアドレス空間をひっ迫することに
なってしまうためです。
ちなみに64bit版においては余裕があります。
動作環境で変数用のメモリの拡張をできるような設定を検討します。
[ ]
RE:07068 HttpGetでの文字化けNo.07069
rosegardenyk さん 12/06/25 22:08 [ コメントを投稿する ]
>秀丸エディタのマクロは複数の秀丸エディタ間を行き来して共有できるようにしているという都合上、32bit版においては4GBのアドレス空間をひっ迫することになってしまうためです。
了解です。何か技術的理由があるとぼんやり推測していたのですがこういうことなのですね。

>動作環境で変数用のメモリの拡張をできるような設定を検討します。
恐れ入ります。今回もまたお願いをすることになってしまいました。拡張可能になるということでホットしました。β版のお知らせを待っています。

>ちなみに64bit版においては余裕があります。
現在 私のPCは64bit版なので これも朗報です。実装メモリは4.00GBですが、増設する必要がありますか? 特に必要なくても増やしておいた方が早いとか何かいいことがありますか? 前のPC(XP)に比べ、4.00GBもあると知って卒倒しそうなくらい大きいなと思いましたが… 4GBのアドレス空間というのは32・64に共通で、実装メモリバイト数とも関係ない話と推測してますが、正しくはどうなんでしょうか?


秀丸は何と32bit版を DL してました。現在v8.20 β24です。新しいβ版のお知らせをいただいたら、64ビット版をDLしますが、32ビット版はコントロールパネルの「アプリケーションの追加と削除」で先にアンインストールする必要がありますか? IKKIさんの作ったあるマクロ用に試しに導入したDENGAKUDLL.dllは設定したmacroファイル用ホルダーに入れてあります。これと設定用ホルダはそのままで使えると思っています。HMJRE.dllは同梱されているはずだし、他に考慮する点ございますでしょうか?   



[ ]
RE:07069 HttpGetでの文字化けNo.07070
秀丸担当 さん 12/06/26 14:27 [ コメントを投稿する ]
 
>現在 私のPCは64bit版なので これも朗報です。実装メモリは4.00GBですが、増設す
>る必要がありますか?

今回のマクロの変数の話においては、プログラムの仕組み上の問題で、実際のメ
モリはあまり関係ないです。
どんなに実際のメモリが多くても、1つのプログラム内のアドレス空間がひっ迫
していると大きなメモリを確保できないことがあります。

>秀丸は何と32bit版を DL してました。現在v8.20 β24です。新しいβ版のお知らせ
>をいただいたら、64ビット版をDLしますが、32ビット版はコントロールパネルの「ア
>プリケーションの追加と削除」で先にアンインストールする必要がありますか? IK
>KIさんの作ったあるマクロ用に試しに導入したDENGAKUDLL.dllは設定したmacroファ
>イル用ホルダーに入れてあります。これと設定用ホルダはそのままで使えると思って
>います。HMJRE.dllは同梱されているはずだし、他に考慮する点ございますでしょう
>か?   

64bit版を入れるときには32bit版はアンインストールせずにインストールすれば
多くの設定を引き継いだまま使えます。
ただ同時には使えず、関連付けやインストール時に作成されるショートカットも
最後にインストールしたどちらか1つのものになります。

DLLや変換モジュールは、プログラムそのものなので、64bit/32bit間で原則的に
互換性はありません。
DENGAKUDLLなどを使われている場合は32bit版を使われることをおすすめします。
一応、64bit版の[その他]→[動作環境]→[64bit版]で、32bit版のDLLを動作させ
る設定もありますが、32bitをバイパスしていて、パフォーマンスが低下したり、
DLLの動作によっては完全に動作できない可能性もあります。
[ ]
RE:07070 HttpGetでの文字化けNo.07071
rosegardenyk さん 12/06/26 19:40 [ コメントを投稿する ]
>一応、64bit版の[その他]→[動作環境]→[64bit版]で、32bit版のDLLを動作させる設定もありますが、32bitをバイパスしていて、パフォーマンスが低下したり、DLLの動作によっては完全に動作できない可能性もあります。
貴重な情報ありがとうございます。
単純に、64bit版に余裕があるからといって飛びつくように64bit版をインストールすればいいという話ではないようですね。32 bit版にも拡張機能はつけていただけると思っていますので、むやみに拡張しなければ(例えば、現在の約1MBからいきなり10MBとかにしないで)、2〜3MBに拡張していろいろ自分の関心領域のHTML文書 でテストをしてみてから決めるのがよいのかなと考えています。どうもいろいろありがとうございました。

[ ]
RE:07071 HttpGetでの文字化けNo.07077
秀丸担当 さん 12/06/28 12:50 [ コメントを投稿する ]
 
V8.20β25で、[その他]→[動作環境]→[環境]のところに変数のメモリ上限を決
める設定を追加しました。
[ ]
RE:07077 HttpGetでの文字化けNo.07078
rosegardenyk さん 12/06/28 14:39 [ コメントを投稿する ]
秀丸担当殿
>V8.20β25で、[その他]→[動作環境]→[環境]のところに変数のメモリ上限を決める設定を追加しました。
早速の対応ありがとうございます。上記32ビット版V8.20β25で 上限 2MB に設定して、前と同じテストマクロで「はい」+「はい」として 試したところ、問題なくHTML 取得に成功ました。感激しております。

マクロ変数の上限を 最大の 64MB でも成功です。(当たり前か)
HELP を見ると 「exemacro文でマクロ内からマクロを呼び出した場合はさらに新しくメモリを確保するので、最大で10ネスト(入れ子状態)した場合、上限指定の10倍のメモリが確保される場合があります。」とあります。これが秀丸担当さんの言う「秀丸エディタのマクロは複数の秀丸エディタ間を行き来して共有できるようにしているという都合上、32bit版においては4GBのアドレス空間をひっ迫することになってしまうためです。」というご懸念の意味ですね。

ここで質問です。exemacro文は使ったことも使う予定もないので常時最大の 64MB にしておいても大丈夫なのではないのかなと考えています。どうでしょうか? 
exemacro文以外にも、考慮すべき文や関数がありますか。こうしたメモリーコンシューミングな文を避ければ、32ビット版でも他のパフォーマンスには特に問題ないと考えよろしいでしょうか?だとすると大きなファイル(Max 10MBぐらいですが…)を1変数に取り込んで、文字変数内正規表現置換処理をいろいろしようと考えていたので私にとって朗報です。

  
[ ]
RE:07078 HttpGetでの文字化けNo.07080
秀丸担当 さん 12/06/28 16:39 [ コメントを投稿する ]
 
>ここで質問です。exemacro文は使ったことも使う予定もないので常時最大の 64MB に
>しておいても大丈夫なのではないのかなと考えています。どうでしょうか? 

もし他の方が作られたマクロを使う場合はその中でexecmacroを使っているかも
しれないですが、常にご自身が作られたマクロのみで、execmacroを使わなけれ
ば大丈夫だと思います。

>exemacro文以外にも、考慮すべき文や関数がありますか。こうしたメモリーコンシ
>ューミングな文を避ければ、32ビット版でも他のパフォーマンスには特に問題ないと
>考えよろしいでしょうか?だとすると大きなファイル(Max 10MBぐらいですが…)を

COM関係でまるごと扱わなくてはいけない場合は仕方ないですが、巨大な1ファ
イルを変数にまるごと取り込んで、それを処理するという方法はできる限り避け
たほうがいいと思います。
もともと秀丸マクロの変数は古いバージョンでは1つの上限約4KBと、合計で
64KBというものからそれを拡張にしてきてここまできていて、巨大なファイルを
まるごとを変数として扱うことは想定していないです。
10MBもの変数を扱うと、少しの操作でも何度も内部的に10MBまるごとメモリコ
ピーしたり移動したり、パフォーマンス的にも良くないこともあるほか、もしか
したらまだ見つかっていない予期せぬ不具合がある可能性もあると思います。
いったん秀丸エディタ上にファイルを開いて、それを検索や置換などをするほう
がパフォーマンスも安全性もいいと思います。
[ ]
RE:07080 HttpGetでの文字化けNo.07081
rosegardenyk さん 12/06/28 19:03 [ コメントを投稿する ]
>秀丸エディタ上にファイルを開いて、それを検索や置換などをするほう
がパフォーマンスも安全性もいいと思います。
変数内処理は高速と思っていたのですがごく小サイズの場合の話かもしれませんね。パフォーマンスがかえって下がったり、不測の障害の可能性があるというのでは意味がありません。あぶないところでした。

私のような素人プログラマーというものは飛んでもないことを考えてしまうものなのです。何故こんなことを思いついたかというと、少し前簡単な内容ですが頻繁にファイル間を行ったり来たりする処理で、画面がちらつくのと処理が遅いのでdisabledraw をかけたのですが active ファイルが変わるたびに、外れてdisabledrawにならず、この辞書のようなファイルを1変数に取り込んで処理したところ何秒もかかっていた処理が一瞬で終わったからです。プログラミングになれた人が使う技法を知らないためにとんでもないことを思いついた面もあります。例えば辞書引きで最長一致検索といった高頻度にファイルアクセスをする技法で参考になるもの例えば秀丸マクロないし本がある様でしたら教えて頂けるとありがたいです。 
[ ]
RE:07081 HttpGetでの文字化けNo.07082
秀丸担当 さん 12/06/29 09:59 [ コメントを投稿する ]
 
一般的な常套手段としては、openfile "/h"; で見えない作業用の秀丸エディタ
を開いてそこでいろいろするのが多く使われている方法だと思います。

例:
  #h=hidemaruhandle(0);
  openfile "/h";
  #hTemp=hidemaruhandle(0);
  //何らかの処理
  setactivehidemaru #h; //元の秀丸に戻る
  closehidemaruforced #hTemp; //作業用の秀丸を閉じる

ただ言われている通りちらついたりします。
ReplaceRegular等で文字列を操作する方法だと1KBくらいの小さなデータでは、
確かに変数上での操作のほうが速いです。
しかし500KBや1MBの大きなデータで試してみたところでは、変数の操作だと10秒
くらい待つことがありました。作業用の秀丸でreplaceallfastだと一瞬でした。

目的によっては、あまり使われる手法ではないと思いますが、作業用の秀丸エデ
ィタを作らずファイルの最後に挿入してそこで作業して、undo;して消しておく
というのが速いことがあります。
例えば辞書ファイルから検索して文字列を取り出すというような場合、この方法
のほうだとちらつきもなく速いかもしれません。
ただ全置換などはやり直しにもたついて逆に使えなかったりすると思います。

例:
  #x=x;
  #y=y;
  #yScroll=screentopy;
  disabledraw;
  gofileend;
  insert "\n";
  insertfile "テストデータ.txt";
  //何らかの処理
  undo;
  undo;
  moveto #x,#y;
  enabledraw #yScroll;


もっと高度な手法としては、DLLを自作して、dllfuncを呼び出す方法があります。
プログラムそのものなので、かなり高速でちらつきなしでできますが、これはマ
クロだけではできなくてDLLを作る必要があるので、難しいと思います。
[ ]
RE:07082 HttpGetでの文字化けNo.07083
rosegardenyk さん 12/06/29 10:21 [ コメントを投稿する ]
秀丸担当様
いろいろなアイデアさすがですね。検証などお手数もかけてしまいました。心より感謝します。一つ一つ検討して参ります。この題名は長くなり過ぎましたのでこれで終わりにします。検討後、題名を改めてまた相談させていただきます。ありがとうございます。
[ ]

[ 新規に投稿する ]