C#プログラミングTips

Webページのダウンロード(1)

デジタルアドバンテージ
2002/03/27


 通常、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データ)を画面に表示するサンプル・プログラムを次に示す。ご覧のとおり、非常に単純でお手軽だ。

 1: // openread.cs
 2:
 3: using System;
 4: using System.Net;
 5: using System.IO;
 6: using System.Text;
 7:
 8: class WebOpenRead {
 9:   public static void Main() {
10:
11:     string url = "http://www.atmarkit.co.jp/fdotnet/";
12:
13:     WebClient    wc = new WebClient();
14:     Stream       st = wc.OpenRead(url);
15:
16:     StreamReader sr = new StreamReader(st,
17:                         Encoding.GetEncoding("Shift_JIS"));
18:     Console.WriteLine(sr.ReadToEnd());
19:
20:     sr.Close();
21:     st.Close();
22:   }
23: }
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”というファイル名で保存する。

 1: // download.cs
 2:
 3: using System;
 4: using System.Net;
 5: using System.IO;
 6: using System.Text;
 7:
 8: class WebDownload {
 9:   public static void Main() {
10:
11:     string url  = "http://www.atmarkit.co.jp/fdotnet/images/fdotnet_top2002-03.gif";
12:     string file = "fdotnet.gif";
13:
14:     WebClient wc = new WebClient();
15:     wc.DownloadFile(url, file);
16:   }
17: }
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)などはここに含まれる(ただしこれらすべてのデータを含むかどうかはサーバの設定次第である)。

 1: // webreq.cs
 2:
 3: using System;
 4: using System.IO;
 5: using System.Text;
 6: using System.Net;
 7:
 8: public class WebResReq {
 9:   public static void Main() {
10:     string uri = "http://www.atmarkit.co.jp/fdotnet/";
11:
12:     WebRequest  req = WebRequest.Create(uri);
13:     WebResponse res = req.GetResponse();
14:
15:     // レスポンス・ヘッダの表示
16:     //
17:     foreach (string key in res.Headers.AllKeys) {
18:       Console.WriteLine("[{0}]\n\t{1}",
19:                                    key, res.Headers[key]);
20:     }
21:
22:     // コンテンツの表示
23:     //
24:     Stream       st = res.GetResponseStream();
25:     StreamReader sr = new StreamReader(st,
26:                         Encoding.GetEncoding("Shift_JIS" ));
27:     Console.WriteLine(sr.ReadToEnd());
28:
29:     sr.Close();
30:     st.Close();
31:   }
32: }
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)で記述されている内容で、それ以前に表示された行はレスポンス・ヘッダの内容である。

サンプル・プログラムの実行結果
  レスポンス・ヘッダの内容
  トップページ(index.html)の内容

 どうやら、@ITのサーバはContent-LengthやLast-Modifiedは返していないようである。また使用している文字コードは、HTMLファイル内のMETAタグで記述されているのが分かる。

関連記事(Insider.NET内)
ファイルの入出力の基礎
 
 

 INDEX
  C#プログラミングTips
   Webページのダウンロード(1)
     Webページのダウンロード(2)

「C#プログラミングTips」


Insider.NET フォーラム 新着記事
  • 第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用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Insider.NET 記事ランキング

本日 月間