.NET TIPS

クッキーを使ってWebページを取得するには?

デジタルアドバンテージ 遠藤 孝信
2005/07/15

 最近ではユーザーの認証にクッキーを用いているWebサイトは多い(ASP.NETの「フォーム認証」もクッキーを利用している)。本稿では、このようなクッキー認証を行っているWebページにプログラムからアクセスする方法について解説する。

クッキー認証を行うWebサイトの仕組み

 最初にクッキー認証の仕組みについて簡単にまとめておこう。

 たいていの場合、クッキー認証を行っているWebサイトでは、ユーザーは最初にログイン・ページにアクセスし、ユーザーIDやパスワードを入力する。ログインが成功すれば、ブラウザはWebサイトからクッキーを受け取る(クッキーはファイルあるいはメモリ上に保存される)。

クッキー認証の基本的な仕組み
  ログイン・ページで認証が成功すればクッキーがもらえる。
  そのクッキーを持っていれば、認証が必要なページにアクセスできる。

 以降のページ(認証が必要なページ)へのアクセスには、このクッキーが必要となる。クッキーを持っているユーザーがそれらのページにアクセスすると、ページ取得のリクエストとともにクッキーがWebサイトに送信される。これによりページの閲覧が許可されるため、ユーザーはそれらのページを見ることができる。

HttpWebRequestクラスのCookieContainerプロパティ

 クッキー認証を行っているWebサイトにプログラムからアクセスする場合にも、上記と同じような手順を行うことになる。

 以下では、WebRequestクラス/WebResponseクラス(ともにSystem.Net名前空間)のペアを利用してWebページにアクセスする場合のクッキーの利用について述べる。なおこれらのクラスを利用して、HTTPプロトコルのGETあるいはPOSTメソッドによりWebページにアクセスする基本的な方法については以下のTIPSでまとめているので、ご存じない方はまずそちらを参考にしていただきたい。

 プログラムでは、受け取ったクッキーを格納するためのCookieContainerクラス(System.Net名前空間)のオブジェクトをまず用意する。このオブジェクトは複数サイトの複数クッキーを格納できるストレージである(以降のコード例はC#の場合。VB.NETの場合はページ末尾のサンプル・プログラムを参照)。

CookieContainer cc = new CookieContainer();

 そして、ログイン・ページに対してIDやパスワードをPOSTする際のリクエスト(HttpWebRequestオブジェクト)を作成するときに、いま作成したCookieContainerオブジェクトをCookieContainerプロパティにセットしておく。

string url1 = "http://ログイン・ページのURL";
HttpWebRequest req1 = (HttpWebRequest)WebRequest.Create(url1);
req1.Method = "POST";
req1.CookieContainer = cc;
……

 このようにしてWebページにアクセスすれば(HttpWebRequestオブジェクトのGetRequestStreamメソッドを呼び出せば)、Webサイトから受け取ったクッキーがすべてCookieContainerオブジェクト(上記のコードでは変数cc)に格納される。

 以降、クッキー認証が必要なページにアクセスする場合には、クッキーが格納されているCookieContainerオブジェクトをリクエストのCookieContainerプロパティにセットしておくだけでよい。

string url2 = "http://認証が必要なページのURL";
HttpWebRequest req2 = (HttpWebRequest)WebRequest.Create(url2);
req2.Method = "GET"; // GETは既定値なのでこの行は省略可
req2.CookieContainer = cc;
……

 これにより、リクエストを発行する際にクッキーが送信されることになる。

クッキー認証を行うWebサイトにアクセスするサンプル・プログラム

 以下に、クッキー認証を行っているWebサイトのページにアクセスするサンプル・プログラムを示す。ここではアクセスするWebサイトとしてmixi(ミクシィ)を利用する。

 このプログラムでは、まずIDやパスワードをログイン・ページにPOSTし、クッキーを受け取る。そして受け取ったクッキーを用いて「足あと」ページ(アクセス・ログを閲覧できるページ)の内容を取得し、ログ部分を切り出して表示する。

// mixilog.cs

using System;
using System.IO;
using System.Net;
using System.Text;
using System.Collections;

public class MixiTool {
  static Encoding encoder = Encoding.GetEncoding("EUC-JP");

  static string HttpGet(string url, CookieContainer cc) {

    // リクエストの作成
    HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
    req.CookieContainer = cc;

    WebResponse res = req.GetResponse();

    // レスポンスの読み取り
    Stream resStream = res.GetResponseStream();
    StreamReader sr = new StreamReader(resStream, encoder);
    string result = sr.ReadToEnd();
    sr.Close();
    resStream.Close();

    return result;
  }

  static string HttpPost(string url, Hashtable vals, CookieContainer cc) {
    string param = "";
    foreach (string k in vals.Keys) {
      param += String.Format("{0}={1}&", k, vals[k]);
    }
    byte[] data = Encoding.ASCII.GetBytes(param);

    // リクエストの作成
    HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
    req.Method = "POST";
    req.ContentType = "application/x-www-form-urlencoded";
    req.ContentLength = data.Length;
    req.CookieContainer = cc;

    // ポスト・データの書き込み
    Stream reqStream = req.GetRequestStream();
    reqStream.Write(data, 0, data.Length);
    reqStream.Close();

    WebResponse res = req.GetResponse();

    // レスポンスの読み取り
    Stream resStream = res.GetResponseStream();
    StreamReader sr = new StreamReader(resStream, encoder);
    string result = sr.ReadToEnd();
    sr.Close();
    resStream.Close();

    return result;
  }

  static string Login(string id, string password, CookieContainer cc) {
    // ログイン・ページへのアクセス
    Hashtable vals = new Hashtable();
    vals["next_url"] = "/home.pl";
    vals["email"] = id;
    vals["password"] = password;

    string login = "http://mixi.jp/login.pl";
    return HttpPost(login, vals, cc);
  }

  static string ReadLog(CookieContainer cc) {
    // 足あとページへのアクセス
    string showlog = "http://mixi.jp/show_log.pl";
    return HttpGet(showlog, cc);
  }

  static void Main() {
    string id = "あなたのメールアドレス";
    string password = "あなたのパスワード";

    CookieContainer cc = new CookieContainer();

    Login(id, password, cc);
    string html = ReadLog(cc);

    // ログ部分の切り出し(簡易版)
    string[] lines = html.Split('\n');
    foreach (string line in lines) {
      if (line.IndexOf("年") >= 0) {
        string[] t = line.Split('<', '>');
        Console.WriteLine(t[0] + t[2]);
      }
    }
    // 出力例:
    // 2005年07月13日 16:54 XXXX
    // 2005年07月12日 05:43 YY
    // 2005年07月11日 22:50 ZZZ
    // ……
  }

}

// コンパイル方法:csc mixilog.cs
mixi.jpにアクセスしログ・ページを取得するC#のサンプル・プログラム(mixilog.cs)
 
' mixilog.vb

Imports System
Imports System.IO
Imports System.Net
Imports System.Text
Imports System.Collections
Imports Microsoft.VisualBasic

Public Class MixiTool
  Dim Shared encoder As Encoding = Encoding.GetEncoding("EUC-JP")

  Shared Function HttpGet(url As String, cc As CookieContainer) As String

    ' リクエストの作成
    Dim req As HttpWebRequest _
      = CType(WebRequest.Create(url), HttpWebRequest)
    req.CookieContainer = cc

    Dim res As WebResponse = req.GetResponse()

    ' レスポンスの読み取り

    Dim resStream As Stream = res.GetResponseStream()
    Dim sr As StreamReader = new StreamReader(resStream, encoder)
    Dim result As String = sr.ReadToEnd()
    sr.Close()
    resStream.Close()

    Return result
  End Function

  Shared Function HttpPost(url As String, vals As Hashtable, cc As CookieContainer) As String
    Dim param As String = ""
    For Each k As String In vals.Keys
      param += String.Format("{0}={1}&", k, vals(k))
    Next
    Dim data As byte() = Encoding.ASCII.GetBytes(param)

    ' リクエストの作成
    Dim req As HttpWebRequest _
      = CType(WebRequest.Create(url), HttpWebRequest)
    req.Method = "POST"
    req.ContentType = "application/x-www-form-urlencoded"
    req.ContentLength = data.Length
    req.CookieContainer = cc

    ' ポスト・データの書き込み
    Dim reqStream As Stream = req.GetRequestStream()
    reqStream.Write(data, 0, data.Length)
    reqStream.Close()

    Dim res As WebResponse = req.GetResponse()

    ' レスポンスの読み取り
    Dim resStream As Stream = res.GetResponseStream()
    Dim sr As StreamReader = new StreamReader(resStream, encoder)
    Dim result As String = sr.ReadToEnd()
    sr.Close()
    resStream.Close()

    Return result
  End Function

  Shared Function Login(id As String, password As String, cc As CookieContainer) As String
    ' ログイン・ページへのアクセス
    Dim vals As Hashtable = new Hashtable()
    vals("next_url") = "/home.pl"
    vals("email") = id
    vals("password") = password

    Dim loginUrl As String = "http://mixi.jp/login.pl"
    Return HttpPost(loginUrl, vals, cc)
  End Function

  Shared Function ReadLog(cc As CookieContainer) As String
    ' 足あとページへのアクセス
    Dim showlog As String = "http://mixi.jp/show_log.pl"
    Return HttpGet(showlog, cc)
  End Function

  Shared Sub Main()
    Dim id As String = "あなたのメールアドレス"
    Dim password As String = "あなたのパスワード"

    Dim cc As CookieContainer = new CookieContainer()

    Login(id, password, cc)
    Dim html As String = ReadLog(cc)

    ' ログ部分の切り出し(簡易版)
    Dim lines As String() = html.Split(vbLf)
    For Each line As String In lines
      If line.IndexOf("年") >= 0
        Dim t As String() = line.Split(New Char() {"<", ">"})
        Console.WriteLine(t(0) + t(2))
      End If
    Next
    ' 出力例:
    ' 2005年07月13日 16:54 XXXX
    ' 2005年07月12日 05:43 YY
    ' 2005年07月11日 22:50 ZZZ
    ' ……
  End Sub
End Class

' コンパイル方法:vbc /r:System.dll mixilog.vb
mixi.jpにアクセスしログ・ページを取得するVB.NETのサンプル・プログラム(mixilog.vb)

 実際にこのプログラムを利用する場合には、Mainメソッド内で定義している文字列変数idおよびpasswordの内容を自分のアカウントのものに書き換える必要がある。End of Article

カテゴリ:クラス・ライブラリ 処理対象:ネットワーク
使用ライブラリ:CookieContainerクラス(System.Net名前空間)
使用ライブラリ:WebRequestクラス(System.Net名前空間)
使用ライブラリ:WebResponseクラス(System.Net名前空間)
使用ライブラリ:HttpWebRequestクラス(System.Net名前空間)
関連TIPS:
WebRequest/WebResponseクラスでWebページを取得するには?
関連TIPS:
WebRequest/WebResponseクラスでPOSTメソッドによりデータを送信するには?
 
この記事と関連性の高い別の.NET TIPS
[ASP.NET]クッキーをサポートしないクライアントでセッション機能を利用するには?
[ASP.NET]フォーム認証後に強制的に先頭ページへ誘導するには?
[ASP.NET]構成ファイルのみでフォーム認証を実現するには?
[ASP.NET AJAX]クライアントサイド・スクリプトからカスタムの認証機能を利用するには?
WebClientクラスでWebページを取得するには?
このリストは、(株)デジタルアドバンテージが開発した
自動関連記事探索システム Jigsaw(ジグソー) により自動抽出したものです。
generated by

「.NET 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 記事ランキング

本日 月間