DOBON.NET DOBON.NETプログラミング掲示板過去ログ

Webページをmht形式で保存

環境/言語:[VB2008(.NET 3.5 + WinXP/SP3),IE8]
分類:[.NET]

以下について、ご指導下さい。

やりたい事は、Webページ【h ttp://www.weather-eye.com/amedas_graph/amdgrh.cgi】から
各都道府県の各気温と現在時刻を取得する事です。
mht形式で所得できれば、文字列操作で何とかなるだろうと思いましたが、
スタート地点でつまずいています。
以下では肝心の都道府県のデータが欠落します。IEでmht形式で保存した場合とは異なります。

(1)IEでmht形式で保存したものと同じ結果を得るには、どうすればいいですか?

'環境:(VB2008(.NET 3.5 + WinXP/SP3),IE8)
'参考URL:h ttp://www.atmarkit.co.jp/fdotnet/dotnettips/690createmht/createmht.html
'以下のコードはWindows Formアプリのボタンクリックにて起動しています。

Imports System.Runtime.InteropServices.Marshal
Public Class Form1
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _
Handles Button1.Click
Dim CDO As Object = Nothing
Try
Const adSaveCreateOverWrite = 2
Dim url As String = "h ttp://www.weather-eye.com/amedas_graph/amdgrh.cgi"
Dim path As String = My.Computer.FileSystem.SpecialDirectories.Desktop & "\abcd.mht"
CDO = CreateObject("CDO.Message")
CDO.CreateMHTMLBody(url)
CDO.GetStream.SaveToFile(path, adSaveCreateOverWrite)
MessageBox.Show(path & " を作成しました!")
Catch ex As Exception
MessageBox.Show(ex.Message)
Finally
If CDO IsNot Nothing AndAlso IsComObject(CDO) Then ReleaseComObject(CDO)
End Try
End Sub
End Class

(2)関連質問で、このWebページをIEで開くと地域選択ComboBoxのTextが、
初期状態で関東・甲信越になりますが、これを近畿にすることはできますか?

'以上、よろしくご指導下さい。
■No27723 に返信(masaさんの記事)

HTML のソースをながめてみると、amdgrh.cgi にレイアウトテンプレートが記述されていて、
adsdt.cgi に値が記述されています。
JavaScript で動的に、レイアウトテンプレートと値を結合して、表示しています。

Windows 7、Internet Explorer 8 の環境において、当該ページを MHTML 形式で保存して
みました。
値が出力されているはずの adsdt.cgi には Please access from WeatherEye. という
文字列が出力されていて、adsdt.cgi を正常に取得することはできませんでした。
外部から直接 adsdt.cgi にアクセスすることは想定されていない模様です。

XML 形式で天気情報を提供する Web サービスを利用した方がよいのではないでしょうか。
■No27723に返信(masaさんの記事)
> 各都道府県の各気温と現在時刻を取得する事です。
だけの条件ならWebBrowserコントロールを使って取得する事が可能です。
全国各地の現在の気温
7:00 現在
地域選択: 北海道・東北 関東・甲信越 東海・北陸 近畿 中国・四国 九州・沖縄 現在の気温 昨日同時刻の気温
前日の最低/最高気温 (1h観測値)
北海道・東北
札幌-0.4℃
-2.9℃
-3.5℃
1.4℃
青森2.1℃
0.8℃
-1.6℃
3.8℃
のような形での取得になるので、表形式のような形に整形するには、ちょっと
厄介です。(上記の状態での取得は比較的簡単)

> mht形式で所得できれば、文字列操作で何とかなるだろうと思いましたが、
> スタート地点でつまずいています。
保存してからどのようにして取得するつもりですか?
保存してから取得できるなら、WEB上で表示している段階からでも取得できるはずです。

> (1)IEでmht形式で保存したものと同じ結果を得るには、どうすればいいですか?
データが取得できれば保存する必要はないのでしょうか?

> (2)関連質問で、このWebページをIEで開くと地域選択ComboBoxのTextが、
> 初期状態で関東・甲信越になりますが、これを近畿にすることはできますか?

こちらも、WebBrowserコントロール(又は、IE)を使ってできるかと。
■No27729に返信(もりおさんの記事)

もりお様、返信していただき、ありがとうございます。
又、検証して頂いた事、感謝いたします。
WebBrowserコントロールを使って、できるようなのでもう少し研究してみます。
■No27730に返信(VBレスキュー(花ちゃん)さんの記事)

VBレスキュー(花ちゃん) 様、返信していただき、ありがとうございます。
WebBrowserコントロールを使ってできるとのヒントを頂き、以下を試してみましたが
うまくいきません。もう少し、アドバイスをいただけないでしょうか?

> (2)関連質問で、このWebページをIEで開くと地域選択ComboBoxのTextが、
> 初期状態で関東・甲信越になりますが、これを近畿にすることはできますか?
> こちらも、WebBrowserコントロール(又は、IE)を使ってできるかと。
こちらについては、まったく見当もつきません。

(1)WebBrowserコントロールにNavigateメソッドで対象URLを読み込み
(2)DocumentCompletedイベントでDocumentStream.Readにてバッファに読み込み

>保存してからどのようにして取得するつもりですか?
>保存してから取得できるなら、WEB上で表示している段階からでも取得できるはずです。

IEでmht形式で保存したものを、テキストエディッタで読み込むと895行目辺りに
TMPVALS[0][0] =3D =
['=BB=A5=CB=DA','100','68','99','99','181','6.8','-0.1','-0.1','8.1']=0A=
の記述があり、TMPVALSの添え字[0][0] で都道府県を特定でき、その後の文字列から
各気温が取得できると考えました。
言われる通り、保存せずにデータを取得できるなら、当然そのほうがベターです。
保存については、別の理由でできればいいですけど・・・(以下)

>データが取得できれば保存する必要はないのでしょうか?
これについては、mht形式で保存できれば、リンク切れなどで読めなくなるページを
画像付でみれるので。。と言う事です。



■No27735に返信(masaさんの記事)
> うまくいきません。もう少し、アドバイスをいただけないでしょうか?
どのようなコードを書いてどこがどううまくいかなかったのかを書いて貰わないと
こちらには理解できません。

指定のサイトが表示できたのなら地区を一度選択し直してから下記を実施して
見て下さい。
(サイト表示時のデフォルトの関東地区のままでは途中までしか取得できない)

Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click
TextBox1.Text = WebBrowser1.Document.Body.InnerText
End Sub

プログラムからオプションを選択するには、HTML のソースコードやタグ等に
ついて勉強して頂かないとヒント程度では伝わらないし、応用もできないので
下記のサンプル等で少し試して勉強されたらどうでしょうか?
VB6.0 で IE を使っての方法ですが VB2008 でも要領は同じです。

http://hanatyan.sakura.ne.jp/patio/read.cgi?no=176
又、下記のようなツールを作るとか。
http://hanatyan.sakura.ne.jp/samplepic/vb8_237.htm

一応、VB6.0 の IE を使って全国の都市のデータを一括で表形式で取得して
CSV 形式で保存するまでは、テスト済みです。
■No27737に返信(VBレスキュー(花ちゃん)さんの記事)

VBレスキュー(花ちゃん)様、ありがとうございます。
以下のコードで全国の各気温を取得する事ができました。
又、コンボボックスのナビゲートもできました。

Public Class Form1
Dim url As String = "h ttp://www.weather-eye.com/amedas_graph/amdgrh.cgi"
Dim ret As New System.Text.StringBuilder
Dim flag As Boolean = True

Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
AddHandler WebBrowser1.DocumentCompleted, AddressOf WebBrowser1_DocumentCompleted
With WebBrowser1
.ScriptErrorsSuppressed = True 'スクリプトエラーのメッセージを表示しない
.Navigate(url)
End With
End Sub

Private Sub WebBrowser1_DocumentCompleted(ByVal sender As Object, ByVal e As System.Windows.Forms.WebBrowserDocumentCompletedEventArgs)
If Not WebBrowser1.Url.ToString = url Then Return
If flag Then
flag = False
Me.WebBrowser1.Navigate("javascript:initData(0);")
AreaNavigate()
End If
End Sub

Sub AreaNavigate()
For i As Integer = 0 To 5
Me.WebBrowser1.Navigate("javascript:initData(" & i.ToString & ");")
Application.DoEvents()
ret.Append(WebBrowser1.Document.Body.InnerText)
Next
Console.WriteLine(ret)
End Sub
End Class

どうも、ありがとうございました。
ここまで取得できれば、データの加工は何とでもなりますので問題ないです。
もし、何かお気づきの点があれば、ご指摘下さい。
自分としては、'Application.DoEvents'が気になっていまが、
ここで同期をとらないと自宅の環境(VB2008(.NET 3.5 + Win7(64bit)),IE8)では、各気温が取得できませんでした。
■No27742に返信(masaさんの記事)
> 以下のコードで全国の各気温を取得する事ができました。
> 又、コンボボックスのナビゲートもできました。
私の方法とは少し違いますが、ご自分が理解できる方法で取得できればなによりかと。

> 自分としては、'Application.DoEvents'が気になっていまが、
> ここで同期をとらないと自宅の環境(VB2008(.NET 3.5 + Win7(64bit)),IE8)では、各気温が取得できませんでした。

CPU の性能が高いから、表示される前に、表示データを取得しているのでしょうね
私的には、ループ内で無暗に使用するような場合でなく、それに変わる方法が
見当たらない場合は使用してもいいかなと思っております。

mht 形式で保存する方法ですが、画面に表示された状態で取得して保存しないと
データ部分が保存されないようなので、IE をプログラム上から操作して
保存のダイアログボックスを表示させ、そのウィンドウのハンドルを取得して
(別スレッドなりから)保存のボタンを操作するしか、今の所思い浮かびません。

>これについては、mht形式で保存できれば、リンク切れなどで読めなくなるページを
>画像付でみれるので。。と言う事です。
データ部分は保存しておけば問題ないはずですので、グラフ部分は、元のデータを
使って、グラフを表示するプログラムを作っておくとかした方が後々の利用価値が
多いかと思います。

Microsoft Chart Controls for Microsoft .NET を使ってのグラフ作成方法
http://www.hanatyan.sakura.ne.jp/patio/read.cgi?no=262
■No27745に返信(VBレスキュー(花ちゃん)さんの記事)

VBレスキュー(花ちゃん) 様、返信していただき、ありがとうございます。

>私の方法とは少し違いますが
もし、差し障りがなければ、さわりだけでも、ご紹介いただけないでしょうか?

当初、コンボボックスをナビゲートするのに以下のようにSetAttributeで試行錯誤
していたのですが、コンボボックスのTextは変わるものの都道府県は変化なしで、
時間をとられました。最終的には、上のコードのようにHTML内のスクリプトを実行することで
実現できましたが、もし、以下のような方法でも可能で、もし、ご存知なら教えてもらえませんか?

Dim forms As HtmlElementCollection = WebBrowser1.Document.All.GetElementsByName("Select1")
forms(0).SetAttribute("selectedIndex", "3")’近畿
'WebBrowser1.Document.Forms(0).InvokeMember("submit")

mht 形式で保存するのにIEのメニュをトレースする事は、自分も考えましたが労力の割りに、
合わないと思い素直にPDFで保存しておくこととします。

グラフ作成方法のページも紹介頂き、ありがとうございます。
今まで.NETでグラフ作成の経験はありませんので、ゆっくり腰をすえて勉強してみます。
■No27746に返信(masaさんの記事)
> Dim forms As HtmlElementCollection = WebBrowser1.Document.All.GetElementsByName("Select1")
> forms(0).SetAttribute("selectedIndex", "3")’近畿
> 'WebBrowser1.Document.Forms(0).InvokeMember("submit")

そこまでできたのなら、下記を追加すれば切り替わります。
Dim forms As HtmlElementCollection = WebBrowser1.Document.All.GetElementsByName("Select1")
forms(0).SetAttribute("selectedIndex", "3") '近畿

forms(0).RaiseEvent("onchange")

実は、私も VB6.0 のWebBrowser と同じ方法が使えず色々調べ、試した結果
ですので、これが正しいやり方かどうかは自信ありませんが。
因みに、VB6.0 では、.FireEvent("onChange", "changeOrderChk();") でOK
■No27748に返信(VBレスキュー(花ちゃん)さんの記事)

> そこまでできたのなら、下記を追加すれば切り替わります。
> Dim forms As HtmlElementCollection = WebBrowser1.Document.All.GetElementsByName("Select1")
> forms(0).SetAttribute("selectedIndex", "3") '近畿
>
> forms(0).RaiseEvent("onchange")

見事、切り替わりました。
本当に良い勉強になりました。感謝申し上げます。
ありがとうございました。
解決済み!
■No27749に返信(masaさんの記事)
> ■No27748に返信(VBレスキュー(花ちゃん)さんの記事)
>
>>そこまでできたのなら、下記を追加すれば切り替わります。
>>Dim forms As HtmlElementCollection = WebBrowser1.Document.All.GetElementsByName("Select1")
>>forms(0).SetAttribute("selectedIndex", "3") '近畿
>>
>>forms(0).RaiseEvent("onchange")
>
> 見事、切り替わりました。
> 本当に良い勉強になりました。感謝申し上げます。
> ありがとうございました。
■No27753に返信(masaさんの記事)

読み直していたら、間違って送信ボタンを押してしまいました。
すみません。
解決済み!

DOBON.NET | プログラミング道 | プログラミング掲示板