ExcelからXMLHTTPを呼び出したときに特定のURLでエラーが発生することがあると先日書いた。
Excelから使っていることが原因なのかどうかを切り分けるため、IE(HTML)から呼び出したときにどうなのか、確認してみた。
結果としては、Excelの時と同じく、ブラウザでもエラーとなってしまった。
エラーとなるページは何が悪いのか?調べようと思い、該当ページを自製ツールでダウンロードしようとしたところ、うまくダウンロードできない。
おかしいと思いレスポンスヘッダを確認したところ、どうやら該当ページは 302 Found を返している模様。
いろいろ見比べたところ、ヤフオクでは(見つけられる限りでは)3パターンのレスポンスを返しているようだと言うことが分かった。
(1)アダルトカテゴリ以外の場合
200 OK を返し、期待するオークションページを返す
(2)アダルトカテゴリの場合
200 OK を返すが、「アダルトカテゴリに入ろうとしています」というページを返す。このページの中のログインページへのリンクに、期待するオークションページへのリンクがパラメータとして渡される。ログイン後、期待するオークションページにリダイレクトする。
(3)条件不明(特定出品者のオークションに限られる模様)
302 Found を返し、LocationでログインページへのURLを渡してくる。(IEは自動的にリダイレクトするためログインページが表示される)。URLには期待するオークションページへのリンクがパラメータとして含まれており、ログイン後、期待するオークションページにリダイレクトする。
このうち、(3)のパターンは、XMLHTTPで取得できない。xmlhttp.statusで302が取得できるわけではなく、メソッド自体が失敗する(エラーが発生する)。
XMLHTTPは、レスポンス 302 をサポートしていない、ということでFA?
ちなみに、WinHTTPでは 302 Found のページの場合、Locationで示されるURLにリダイレクトし、その結果を返してくれる。
とりあえずExcelから使う分には XMLHTTP を単純に WinHTTP に置き換えれば何とか動きそうだ。なお WinHTTP の COM I/F である WinHTTPRequest は XMLHTTP とI/F互換があるので、オブジェクト生成時のProgIDを MSXML2.XMLHTTP から WinHttp.WinHttpRequest.5.1 に書き換えればよい。
ただ、Microsoft独自I/FなのでHTMLで使うのは厳しそう。Win+IE以外じゃ使えないだろうし。
そういえばVista+IE7のMSXMLではこの問題直ってるんだろうか?
いまだにVistaもIE7も導入していないのでテストができない。。
まとめ
I/F | ProgID | DLLバージョン | ||
XMLHTTP 2.6 | MSXML2.XMLHTTP.2.6 | msxml2.dll 8.30.9529.0000 (XML OM for Win32) |
正しく取得できる | send()でエラーが発生する。エラーコードは-2147024891 (0x80070005) |
XMLHTTP 3.0 | MSXML2.XMLHTTP.3.0 | msxml3.dll 8.70.1113.0000 (MSXML 3.0 SP7) |
正しく取得できる | 同上 |
XMLHTTP 4.0 | MSXML2.XMLHTTP.4.0 | msxml4.dll 4.20.9841.0000 (MSXML 4.0 SP 2) |
正しく取得できる | 同上 |
XMLHTTP 5.0 | MSXML2.XMLHTTP.5.0 | msxml5.dll 5.10.2930.0000 (MSXML 5.0) |
正しく取得できる | 同上 |
WinHTTP | WinHttp.WinHttpRequest.5.1 | winhttp.dll 5.01.2600.2180 |
正しく取得できる | リダイレクト後のページを取得できる |
念のためMSXML3以外のバージョンも試してみたが、どれも結果は一緒だった。MSXML6は入っていなかったので確認していない。
send()のエラーは、JavaScriptであれば try〜catch で捕捉可能。
Excel VBAではOn Error Resume Next〜On Error GoTo 0で捕捉し、Err.Numberでエラーコードを取得。
ちなみにProgIDにバージョン指定のない MSXML2.XMLHTTP を指定すると、システムのデフォルトバージョン(私の環境では MSXML2.XMLHTTP.3.0)がロードされる。