none
WEB上のデータ取得時にエラーが発生 RRS feed

  • 質問

  • おはようございます。

     

    以下のような記述で、WEB上のデータを取得しようとしているのですが、かなりの頻度で

    WEBページからソースが取得できません。

     

    'Webページのソースを読み込むプロシージャ
        Public Function GetWebPageSource(ByVal URL As String, ByRef source As String, _
            ByVal charcode As String) As Boolean
            Dim Request As WebRequest
            Dim Response As HttpWebResponse
            Dim DataStream As Stream
            Dim Reader As StreamReader

            Try
                '指定されたURLへのリクエストを生成する
                Request = WebRequest.Create(URL)

                'レスポンスを得る
                Response = CType(Request.GetResponse(), HttpWebResponse)

                'データストリームを得る
                DataStream = Response.GetResponseStream()

                'Webページのソースを読み出すためのストリームリーダーを生成する。
                Reader = New StreamReader(DataStream, Encoding.GetEncoding(charcode))

                'WEBページのソースを読み出す
                source = Reader.ReadToEnd

                '後始末をする
                Reader.Close()
                DataStream.Close()
                Response.Close()

                '戻り値を返す
                GetWebPageSource = True

            Catch ex As Exception
                GetWebPageSource = False
            End Try
        End Function

     

        Public Sub Get_New_Dailydata()
            Dim Source As String = ""
            Dim Result As Boolean
            Dim r As Regex
            Dim Regsource As String
            Dim m As Match
            Dim i As Integer    'ループ変数
            Dim j As Integer
            Dim Writer As New IO.StreamWriter("C:\DailyData.txt", True)
            Dim StartCode As Integer
            Dim EndCode As Integer
            Dim Zenjituhi As Integer
            Dim Zenjituhi_Temp As String

            'カウンター表示ラベルのテキストを削除
            'lbl_Counter.Text = ""

            '銘柄数を格納する配列
            Dim StockCode As String
            StartCode = 1300
            EndCode = 9999

            '1300~9999までのすべての銘柄をチェックし、該当するものをテキストファイルに書き込み

            For i = StartCode To EndCode Step 50
                StockCode = ""

                '取得する銘柄コードのリストを作成
                For j = i To i + 49
                    If StockCode = "" Then
                        StockCode = j
                    Else
                        StockCode = StockCode & "+" & j
                    End If

                    If j = EndCode Then
                        Exit For
                    End If
                Next

                '株価データを読み込む
                Result = GetWebPageSource("http://quote.yahoo.co.jp/q?s=" & StockCode & _
                                        "&d=v2", Source, "EUC-JP")

                If Result = False Then
                    MsgBox("株価データの取得に失敗しました。")

                    Exit Sub
                End If

                '正規表現で株価等のデータを検索する。
                Regsource = "<td nowrap align=left><a href=.*?>(.*?)</a></td><td nowrap align=left>" _

    "<small><img src=.*? alt=.*? width=20 height=15 align=absmiddle>" _

    "<b>(.*?)&nbsp;</b></small></td><td nowrap align=center>(.*?)</td>" _

    "<td nowrap><b>(.*?)</b></td><td nowrap>(.*?)</td><td nowrap>(.*?)</td>" _

    "<td nowrap>(.*?)</td><td nowrap>(.*?)</td><td nowrap>(.*?)</td><td nowrap>(.*?)</td>"
                r = New Regex(Regsource)
                m = r.Match(Source)

                'テキストファイルに日足のデータを書き込みする。
                While m.Success
                    Zenjituhi_Temp = Replace(m.Groups(5).Value, "<font color=ff0020>", "")
                    If Replace(Zenjituhi_Temp, "</font>", "") = "---" Then
                        Zenjituhi = 0
                    Else
                        Zenjituhi = Replace(Zenjituhi_Temp, "</font>", "")
                    End If

                    Writer.WriteLine(m.Groups(1).Value & " " & m.Groups(2).Value & " " & _
                        m.Groups(8).Value & " " & m.Groups(9).Value & " " & m.Groups(10).Value & " " & _
                        m.Groups(4).Value & " " & Zenjituhi & " " & m.Groups(7).Value)

                    m = m.NextMatch
                End While

                '現在の進行状況をカウンターに表示
                My.Application.DoEvents()
                frm_menu.lbl_Counter.Text = i & "件終了 / " & EndCode & "件中"
            Next

            Writer.Close()
        End Sub

     

    こちらはモジュールに記述をしてあり、フォームのコマンドボタンクリックにて実行するようにしてあります。

     

    できる場合もあるのですが、できないことが多く、できない場合は、「GetWebPageSource」で

    起こっているようです。

     

    自分でも、調べている最中ですが、何か原因となるようなことがありましたら、ご教授いただけませんでしょうか。

    どうか、よろしくお願いします。

     

     

    2008年2月2日 23:36

回答

  • 私も以前、同じ問題にぶつかりました。定かではありませんが、短時間に多数のアクセスをするとサーバーから切断されるようです。どのような仕様になっているのかはわかりませんが、私の場合、全銘柄の4本値を正常に取得できる時もあれば、途中で切断されるケースも多々発生しました。

     

    以下にもそのようなことが書いてありますね。

    機能部品(DLL/ソース) 情報収集 Yahooファイナンス情報取得DLL
    http://invest-prg.rich-prj.com/p_lib/dll_dg_yahoo.html

     

    Yahoo!ファイナンスから株価を取得するということであれば、切断されることを前提にプログラミングするしかないでしょう。

    もしくは一定のウエイトを置くなどの工夫が必要だと思います。

     

    #ご存じのようにYahoo!ファイナンスから株価を取得するアプリは多数存在しますので、ひょっとすると何か逃げ手があるのかもしれないなぁとは思ったりしますが・・・。ただ、サーバーの対策はいつ変わるかわかりませんので・・・。全銘柄をスクリーンスクラッピングされることが多数発生すると、結構な負担がサーバーにかかるでしょうし。

    2008年2月3日 5:05
    モデレータ

すべての返信

  • 一般的には、投げられた例外に原因などの情報が含まれているものですが。

    2008年2月3日 1:13
  • TI-cb400s さん、こんにちは

    ダッチです。

     

     TI-cb400s さんからの引用

    自分でも、調べている最中ですが、何か原因となるようなことがありましたら、ご教授いただけませんでしょうか。

    どうか、よろしくお願いします。

    できない場合というのは、"株価データの取得に失敗しました。" とメッセージが表示されるということですよね。

     

    なぜそうなったかの原因をつかむには、まず GetWebPageSource メソッドで例外をキャッチしたときの ex の中身を見ることで原因がわかるかもしれません。

     

    ちなみに私の環境で数回ほど動かし見ましたが、例外は発生しませんでした。

    2008年2月3日 1:17
  • 外池と申します。

     

    「取得できません」だけでは、情報が不足です。

     

    どのような状況に遭遇して「できない」とご判断されているのでしょうか? エラーが発生する? それとも、エラーは発生しないものの長い時間処理が止まってしまう? 処理が終わるのに得られたデータがまったく意図したものではない?

     

    GetWebPageSourceだけを拝見しましたが、

     

    エラーの発生への対処として、Try Catchの作り方が大雑把すぎます。処理ごとにわけてTry Catchを作ってください。で、処理ごとに正常・エラーの確認をしましょう。エラーが発生したらどのようなエラーなのか出力するようにしましょう。

     

    処理が止まってしまうような場合の対処として、まずは、非常に簡単なWebサイトで試してください。フレームに分かれていない単一のページ、文字数が少ないページで、正しくデータが得られることを確認してください。その上で、以下、重要なのですが、複雑なWebのページでは、1回の読み取り操作ですべてのソースが得られるとも限りません。私は、同様のプログラミングでは、非同期実行でしか書いたことがないので、そのときは、何回か読み取り操作が必要になるケースがありました。いわゆる「Chunked」なページの場合です。Chunkedなページの場合、同期実行の場合どうすればよいのか、ドキュメントで調べてください。

     

    最後に、意図しないデータを得てしまうケースですが・・・、提示された後半のコードから推察するに、yahooのページですよね。非常に高度なサイトを相手に、この手のツールを開発するのは、大変なことです。と言うのも、yahoo側も特殊なツールを排除するような仕組みを持っているかもしれません。サーバー側ではアクセスしてきているクライアントがどのブラウザを使っているかを識別する機構があって、不明な場合は拒否の応答が返えすことも可能なのです。あるいは、yahooの適切なページからクリックしてあるページに移動しないと、つまり、ひとつ前に適切なページを一度ひらいていないと、やはり拒否の応答が返すようになっているかもしれません。

     

    このあたり・・・、VBの知識というよりも、まずは、http通信の知識が必要で、その上で、.Net Frameworkのネット操作関連のクラスライブラリーに精通しないと難しいところです。

    2008年2月3日 1:49
  • 私も以前、同じ問題にぶつかりました。定かではありませんが、短時間に多数のアクセスをするとサーバーから切断されるようです。どのような仕様になっているのかはわかりませんが、私の場合、全銘柄の4本値を正常に取得できる時もあれば、途中で切断されるケースも多々発生しました。

     

    以下にもそのようなことが書いてありますね。

    機能部品(DLL/ソース) 情報収集 Yahooファイナンス情報取得DLL
    http://invest-prg.rich-prj.com/p_lib/dll_dg_yahoo.html

     

    Yahoo!ファイナンスから株価を取得するということであれば、切断されることを前提にプログラミングするしかないでしょう。

    もしくは一定のウエイトを置くなどの工夫が必要だと思います。

     

    #ご存じのようにYahoo!ファイナンスから株価を取得するアプリは多数存在しますので、ひょっとすると何か逃げ手があるのかもしれないなぁとは思ったりしますが・・・。ただ、サーバーの対策はいつ変わるかわかりませんので・・・。全銘柄をスクリーンスクラッピングされることが多数発生すると、結構な負担がサーバーにかかるでしょうし。

    2008年2月3日 5:05
    モデレータ
  • ご回答ありがとうございます。

     

    エラー処理については、個人でしか私用しないものばかり作っていたため、

    勉強を怠っており、現在勉強中ですので、未熟な部分については、ご容赦

    ください。

     

    エラーとしては、エラー処理としてある、「株価データが取得できませんでした。」

    というものが帰ってくるのですが、URLも間違ってはおらず、ブレークポイントを

    つけ、ひとつずつ処理を追っていくと、ホームページのソースが取得できず

    上記のエラーとなります。

     

    trapemiyaさんがご回答いただいたないようですと、納得がいきます。

    できない状態で、しばらくしてから再度実行すると、うまく取得できたり

    もします。

     

    よい機会なので、エラー処理についても、しっかりと勉強したいと

    思います。

    ご回答いただきました、皆様、本当にありがとうございます。

    2008年2月3日 6:28