VB6でテレビ番組表HTMLの保存

タグの編集
投稿者 gmon_nx  (社会人) 投稿日時 2009/1/29 17:08:09
はじめまして。
教えてgooにて、こちらの質問
http://oshiete1.goo.ne.jp/qa4583806.html

をしたのですが、解決に至らず止まってしまってます。
どちら様か続きの回答をいただけないでしょうか。
よろしくお願いします。
投稿者 魔界の仮面弁士  (社会人) 投稿日時 2009/1/29 20:11:18
★1:質問文について★

> うまくできませんでした。
具体的に「どうなってしまうのか」を記述しないと、話が正しく伝わりませんよ。

・エラーが出るなら、エラーメッセージを正確に転記しましょう。
・処理が停止してしまうなら、どこで停止するのかを明記しましょう。
・期待動作しない場合には、どのような結果を期待して、実際には
 どうなってしまうのかを記載しましょう。

なお、今のコードは『Web からのデータ受信』と『そのデータをファイルに保存』という
2 つの手順を行っていますので、そのどちらに問題があるのかも切り分けた方が良いでしょう。

たとえば、いきなりファイルに保存するのではなく、
Dim sData As String
sData = Inet1.OpenURL(strURL)
RichTextBox1.Text = sData
Print #1, sData
のように、変数保存/画面表示/ファイル保存など、複数の確認方法をとってみてください。


> ソースを開いてみるとEUC-JPとなっていまして、これが原因かと思うのですが
これは、Web サイト側の不具合だと思います。
 サーバーからの応答ヘッダ:Content-Type: text/html; charset=Shift_JIS
 サーバーからの応答ボディ:Shift_JIS エンコードされた文字列
 HTML 中の META タグ:<meta http-equiv="Content-Type" content="text/html; charset=EUC-JP" />
ということで、HTML の記述が、実際の文字コードと一致していません。

なので、保存するファイル名を、~.html にしている場合は、ブラウザによっては
EUC-JP と誤解され、文字化けしてしまうかも知れません。対処方法は以下3案。

(A) 無加工で保存する場合:
 IE で開くと、文字化けする可能性があります。化けた場合には、右クリック[エンコード]から、
 [日本語 (シフトJIS)]を選択して、表示を切り替えてください。

(B) META タグを修正して保存する場合:
 文字コードは Shift_JIS を維持し、META タグを書き換えるものです。たとえばこんな感じ。
Dim sRawData As String, sSJIS As String
sRawData = Inet1.OpenURL(strURL)
sSJIS = Replace(sRawData, "text/html; charset=EUC-JP""text/html; charset=Shift_JIS")
Print #1, sSJIS

(C) 文字コードを修正して保存する場合:
 META タグが EUC-JP なので、保存時に Shift_JIS → EUC-JP 変換するという物です。
 これは、回答2 で korin_さんが書かれている方法です。

=====================================================================
★2:回答1(yyr446さん)の内容について★

これは『Web からのデータ受信』の方法を変更し、『ファイルへ保存』する部分はそのままにしていますね。
保存側に関しては、先述した
 (A) 無加工で保存する場合
 (B) META タグを修正して保存する場合
 (C) 文字コードを修正して保存する場合
の A案 に相当する処理手順です。

> の行がコンパイルエラーになってしまいました。
この回答は、VB.NET の構文になっています(解放処理が省かれた不完全なコードですが)。
VB6 の場合は、以下のようになるでしょう。
Dim strURL As String
strURL = "http://tv.nikkansports.com/tv.php?site=007&mode=06&category=g&area=025&template=time&sdate=20081226&lhour=24&shour=5&arg=05"

'[Microsoft XML, v3.0]での実装例 
With New MSXML2.XMLHTTP30
    .open "GET", strURL, False    '括弧が付かない事に注意 
    .send
    RichTextBox1.Text = .responseText
End With


なお、回答1の文中では「Microsoft XML v6.0を参照設定」と書かれていますが、
実際に呼び出しているのは、3.0 バージョンになっています。
> = CreateObject("Msxml2.XMLHTTP.3.0")
もし、6.0 バージョンを呼び出したい場合には、
 = New MSXML2.XMLHTTP60
 = New MSXML2.ServerXMLHTTP60
 = CreateObject("MSXML2.XMLHTTP.6.0")
 = CreateObject("MSXML2.ServerXMLHTTP.6.0")
のいずれかの構文を使う事になります。もっとも、gmon_nx さんの環境には 6.0 が無いようですが。

また、CreateObject を使うのであれば、変数宣言を As Object にすれば、
参照設定する必要はありません。逆に言うと、参照設定しているのであれば、
New キーワードを使って生成した方が良いでしょう。

ただし、XMLHTTP の .responseText は、文字コードの判定を自動的に行ってくれますが、
サーバーの設定や DLL のバージョンによって動作が変化しますので注意してください。
(生のバイナリを受け取る .responseBody を使って、自前で変換した方が安全かも?)


=====================================================================
★3:回答2(korin_さん)の内容について★

これは『Web からのデータ受信』の方法は変更せず、『ファイルへ保存』する部分のみを修正していますね。
保存側に関しては、先述した
 (A) 無加工で保存する場合
 (B) META タグを修正して保存する場合
 (C) 文字コードを修正して保存する場合
の C 案 に相当する処理手順です。

> これはどこに記述すれば良いのでしょうか?
> 質問文のソースに加えて記述するのでしょうか?
両方のコードを良く見直してみましょう。

gmon_nx さんは、受け取った文字列を「Print # ステートメント」で保存しましたよね。
korin_ さんは、受け取った文字列を「ADODB.Stream オブジェクト」で保存しています。

ですから、これそのものが完成形のコードと言えるでしょう。

「通信部分」と、「(文字コード変換を伴った)保存部分」に分けて考えると、
意図が理解できるでしょうか。
'通信部分(この部分は元質問のコードと同一) 
Dim sText As String
sText = Inet1.OpenURL(strURL)

'EUC-JP に変換して保存する部分 
'Microsoft ActiveX Data Objects 2.8 Library (2.5以上ならOK)を参照設定 
With New ADODB.Stream
    .open
    .Type = adTypeText
    .Charset = "EUC-JP"
    .WriteText sText
    .SaveToFile strFileName, adSaveCreateOverWrite
    .Close
End With


korin_ さんのように、参照設定無し(レイトバインド)にしても良かったのですが、
ここではマジックナンバー「2」の意味を説明する意味も込めて、
参照設定ありのコードに変更しています。

なお、こうした .WriteText による変換が成功するのは、「変数 sText が文字化けしていない時」だけです。
もし、受信したデータを画面に表示するために
 RichTextBox1.Text = sText 'TextBox ではなく、RichTextBox を使うこと
を行ってみて、日本語部分が文字化けしているような時には使えません。
(今回は化けないと思いますので、その場合の対処方法は説明しないでおきます)
投稿者 gmon_nx  (社会人) 投稿日時 2009/2/28 07:48:42
大変長らく返信が遅れてしまい失礼いたしました。
かの有名な魔界の仮面弁士さんにご回答いただきうれしく思います。

遅ればせながら試してみたのですが、
大変初歩的なところ?で引っかかってしまいました。

★3を試したところ、「URLが不正」とのエラーが出ました。
ならばと、
★1のリッチテキストに書き出す例をと試したところ、
やはり同じエラーとなりました。


URLを変えてみても同じになります。
これはどうしたことでしょうか?

尚、最初の質問でうまくいかないというのは、
文字化けしたうえ、全文が保存されないということでした。

よろしくお願いします。
投稿者 gmon_nx  (社会人) 投稿日時 2009/3/1 05:43:47
[追記]
★2の[Microsoft XML, v3.0]での実装例を試してみたところ、
正しくhtmlを取得することに成功しました。

様々なパターンで詳細にご説明して下さりありがとうございました。

ただ、このプログラムでShift-JISのhtmlを取得した場合は、
日本語部分のみ文字化けしてしまいます。
EUCと両用のプログラムにしたいと思っているのですが、
どうしたら良いでしょうか?
投稿者 魔界の仮面弁士  (社会人) 投稿日時 2009/3/3 19:56:39
> 文字化けしたうえ、全文が保存されないということでした。
どういう意味でしょう。全文が保存されず、一部のみが保存されるのでしょうか?
だとしたら、URLの読み込みに時間がかかってタイムアウトしてしまい、
文書の後半を取り込めなかったのかも。


> EUCと両用のプログラムにしたいと思っているのですが、
> どうしたら良いでしょうか? 

そもそもは、
>> これは、Web サイト側の不具合だと思います。
>>  サーバーからの応答ヘッダ:Content-Type: text/html; charset=Shift_JIS
>>  サーバーからの応答ボディ:Shift_JIS エンコードされた文字列
>>  HTML 中の META タグ:<meta http-equiv="Content-Type" content="text/html; charset=EUC-JP" />
>> ということで、HTML の記述が、実際の文字コードと一致していません。
に起因する問題であって、文字化けしないように「正しく作られたサイト」であれば、
得られたバイナリをそのまま無加工で保存するだけで良いはずです。


この場合、EUCのサイトは、EUCのHTMLファイルとして保存し、Shift_JIS ならば
Shift_JIS のファイルとして保存されることになります。


無加工で保存できないのは、「文字コードの指定が間違っているサイトを保存する場合」、
「文字コードの指定がなく、文字コードを機械的に判断できない場合」
「保存時に、別の文字コードに変換して保存したい場合」などであり、
その場合は、今回の説明に即した方法で、文字コードの変更処理や、metaタグの
修正などを施さねばならないでしょう。

今回の状況は、どの場合に相当しますか?



> 日本語部分のみ文字化けしてしまいます。
まずは、『なぜ文字化けしたのか』を解析し、そのメカニズムを理解するようにしてみてください。
文字化けの原因が分からなければ、問題を回避するコードを書くこともままならないでしょうから。
投稿者 gmon_nx  (社会人) 投稿日時 2009/3/6 16:04:21
アドバイスありがとうございます。
文字化けの原因の分析、ちょっと難しいですが・・
もうちょっといろいろ試してみたいと思います。
今後の参考にさせていただきます。