C#プログラミングTipsWebページのダウンロード(1)デジタルアドバンテージ |
通常、Webページにアクセスするには、ブラウザを利用するのが一般的だが、プログラムによりWebページやWeb上にあるファイルを直接ダウンロードすることも可能だ。これにより、特定ページを定期的にローカル・ファイルに保存したり、複数ページをいっきにダウンロードしたりといったことが可能になる。また、ファイアウォールとの兼ね合いから、データ交換をHTTP経由で行わなければならないような場合にも、プログラムによるWebのアクセスは有効である(ファイアウォールが存在する場合でも、Webアクセス用として、HTTPは利用可能なケースが多い)。.NET Frameworkのクラス・ライブラリでは、このようなWebへのアクセスを行うための機能がいくつか提供されている。Webへのアクセスはダウンロードとアップロードの2つに大別することができるが、今回はまずダウンロード方法についてまとめてみた。
WebClientクラスによるWebページのダウンロード
クラス・ライブラリの中で、Webのアクセスに関して最も高級なクラスはWebClientクラス(System.Net名前空間)である。このクラスはデータのダウンロードに関して次の3つのメソッドを持っている。
- public Stream OpenRead(string address)
- public void DownloadFile(string address, string fileName)
- public byte[] DownloadData(string address)
各メソッドの“address”パラメータには、WebページのURLを文字列で指定することができる。メソッドのパラメータと戻り値を見ればその機能はだいたい予想がつくだろう。ここではまず、OpenReadメソッドを使用して、Webページのソース・データ(HTMLデータ)を画面に表示するサンプル・プログラムを次に示す。ご覧のとおり、非常に単純でお手軽だ。
|
|
Webページのソース・データを画面に表示するプログラムopenread.cs | |
openread.csのダウンロード
|
ここでは本Insider.NETのトップページ(実際のファイルはindex.html)を取得し、それを画面に表示している。まずWebClientクラスのインスタンスを作成し(13行目)、OpenReadメソッドを呼び出す(14行目)。OpenReadメソッドは該当ページに対する読み取り専用のStreamオブジェクトを返す。このStreamオブジェクトさえ取得すれば、それに続く手順は「ファイルの入出力の基礎」で解説しているものと同じで、バイナリとして、あるいは文字列として、ストリームの源がネットワークかファイルかということは区別せずに読み込むことができる。
ここではShift-JISとしてWebページを読み込んでいる。もちろんこれは、@ITのサイトで使用されている文字コードがShift-JISだからである。サイトによっては、異なる文字コード(例えばEUCコードなど)が使用されているだろう。その場合は、使用されている文字コードの種類に応じてプログラムを修正する必要がある。サイトで使用されている文字コードは、ページ内のタグやWebページの取得時に得ることができるレスポンス・ヘッダ(後述)などに記述されている場合にはそれによって判別できるが、明記されていない場合はページの内容から独自に自動判別する機構が必要となる。
StreamReaderクラスが持つReadToEndメソッド(18行目)は、ストリームの最後までを1つの文字列としていっきに読み込む便利なメソッドだ。対象のページが巨大なときには、一時的に大量のメモリが必要となるが、最近のシステムは多くのメモリを搭載しているので、実用上これが問題になることはほとんどないだろう。
Webページのファイルへの保存
Webページに対するストリームが得られれば、別のファイルをオープンし、そのデータをファイルに書き込むことも簡単だが、WebClientクラスのDownloadFileメソッドを使用すれば、もっと簡単にこれを行うことができる。次のサンプル・プログラムはInsider.NETのトップページにあるビットマップ・ファイルを“fdotnet.gif”というファイル名で保存する。
|
|
Web上のビットマップ・ファイルを保存するプログラムdownload.cs | |
download.csのダウンロード
|
DownloadFileメソッドは、その内容にかかわらずバイナリとしてデータを読み込むので、サーバにあるファイルをそのままローカルに保存することができる。
WebRequestクラスとWebResponseクラス
これまで見てきたように、WebClientクラスはお手軽に利用できるクラスだが、その反面、細かな制御はできない。例えばWebClientクラスでは、取得しようとしているページのサイズや最終更新日時などの情報を、ページ本体を取得する前に得ることなどはできない。このように、より細かな制御を行いながらWebにアクセスするには、次に説明するWebRequestクラスとWebResponseクラスの2つを使用する。実際のHTTPプロトコルを用いたWebアクセスでは、サーバにリクエスト・メッセージを送り、それに対応したレスポンス・メッセージを受け取るという動作が基本となっているが、2つのクラスはこの2つの動作に対応している。
次のサンプル・プログラム(webreq.cs)はInsider.NETのトップページにアクセスし、先ほどと同様にページのソースを画面に表示するが、その前にレスポンス・ヘッダの内容を表示する。レスポンス・ヘッダには、サーバやレスポンス・メッセージに関する情報が含まれている。通常は、ページのサイズ(Content-Length)や最終更新日時(Last-Modified)、ページで使用している文字コード(Content-Typeに含まれるcharset)などはここに含まれる(ただしこれらすべてのデータを含むかどうかはサーバの設定次第である)。
|
|
Webページのソースを画面に表示するプログラムwebreq.cs | |
webreq.csのダウンロード
|
単純なWebページのダウンロードはこちらの方法でもいたって簡単だ。まずWebRequestクラスの静的メソッドであるCreateメソッドにアクセスするURLを指定して呼び出す(12行目。ここでnewによりインスタンスを生成せずに、静的メソッドを呼び出しているのには意味があるのだが、それについては後述する)。これによってリクエスト・メッセージを含んだWebRequestオブジェクトを得ることができる。続いてこのオブジェクトに対してGetResponseメソッドを呼び出す(13行目)。これはWebResponseオブジェクトを返す。この時点でレスポンス・ヘッダは取得済みだが、実際のページの内容はまだ取得されていない。
次にレスポンス・ヘッダの内容を表示する。表示に必要な情報はWebResponseオブジェクトのHeadersプロパティを通じて取得することができる。このプロパティはヘッダに含まれる情報を「キー名」と「値」のペアとして格納しているWebHeaderCollectionクラスのオブジェクトである。例えば“Content-Type”キーに対する値は、インデクサにより“res.Headers["Content-Type"]”として得ることができる。またすべてのキーの値は文字列の配列として、この場合ではres.Headers.AllKeysプロパティから得ることができる。今回はこの2つを組み合わせて、ヘッダに含まれるすべてのキー名とその値を表示している(17〜20行目)。
実際のページの内容を取得するには、WebResponseオブジェクトに対してGetResponseStreamメソッドを実行し、Webページへのストリームを得る(24行目)。この後の処理は前出のWebClientクラスの場合と同じだ。
このプログラムを実行し、出力された内容の先頭部分は次のようになった。「<!DOCTYPE HTML〜」以下の行がトップページ(index.html)で記述されている内容で、それ以前に表示された行はレスポンス・ヘッダの内容である。
サンプル・プログラムの実行結果 | ||||||
|
どうやら、@ITのサーバはContent-LengthやLast-Modifiedは返していないようである。また使用している文字コードは、HTMLファイル内のMETAタグで記述されているのが分かる。
関連記事(Insider.NET内) | |
ファイルの入出力の基礎 |
INDEX | ||
C#プログラミングTips | ||
Webページのダウンロード(1) | ||
Webページのダウンロード(2) | ||
「C#プログラミングTips」 |
- 第2回 簡潔なコーディングのために (2017/7/26)
ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている - 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう - 第1回 明瞭なコーディングのために (2017/7/19)
C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える - Presentation Translator (2017/7/18)
Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
|
|