「TIPS:WebRequest/WebResponseクラスでWebページを取得するには?」では、GETメソッドによるWebページの取得について解説しているが、本稿では、POSTメソッドによりWebページにデータを送信してアクセスする方法について解説する。
WebRequestクラス/WebResponseクラス(ともにSystem.Net名前空間)を使用してGETメソッドによりWebページにアクセスするには、上記のTIPSで示しているように、基本的には次のような処理の流れになる。
1. WebRequestクラスによりリクエスト(HttpWebRequestオブジェクト)を作成
2. GetResponseメソッドによりレスポンス(WebResponseオブジェクト)を取得
3. GetResponseStreamメソッドにより得たストリームから結果を取得
POSTメソッドによりデータ(以降、ポスト・データ)を送信する場合には、リクエストであるHttpWebRequestオブジェクトに対して、以下のような設定が上記1.と2.の間に必要となる。
1.1. Methodプロパティを「POST」に設定(デフォルトは「GET」)
1.2. ContentTypeプロパティを「application/x-www-form-urlencoded」に設定して、ポスト・データのコンテンツ・タイプを指定
1.3. ContentLengthプロパティに送信するポスト・データの長さを設定
1.4. GetRequestStreamメソッドにより得たストリームに対してポスト・データを書き込む
以下に実際のWebページの例を取り上げながら、これらの詳細を解説していく。
ここでは、Googleが提供している翻訳機能(現時点ではBETA版)にアクセスするプログラムを作成してみる。Google翻訳機能では、以下のようなページにより、さまざまな言語間での機械翻訳を実行することができる。
Google翻訳機能ページのソース(HTMLデータ)を見ると、翻訳したい文章を入力する部分のフォームは次のようになっている。
<form action=translate_t method=post>
<textarea name=text rows=5 cols=45 wrap=PHYSICAL>
</textarea>
<select name=langpair>
……略……
<option value="ja|en">Japanese to English BETA
</option>
……略……
</select>
<input type=hidden name=hl value="en">
<input type=hidden name=ie value="UTF8">
<input type=submit value="Translate">
</form>
このフォームでは、以下の表に示した4つのデータを、「http://translate.google.com/translate_t」に対してポスト(送信)していることになる。
パラメータ名 | 値 | 内容 |
---|---|---|
text | 翻訳したい文字列 | UTF-8でエンコードが必要 |
langpair | ja|en | 日本語から英語へ翻訳する場合の値 |
hl | en | 結果ページで使用される言語 |
ie | UTF8 | 入力文字列の文字コード |
Google翻訳機能ページでポストされる4つのデータ これらの各データの内容は筆者が独自に調査したものであり、将来的に変更される可能性がある。 |
プログラムからGoogle翻訳機能を利用する場合には、これらのデータをポスト・データとして作成し、上記のURLにアクセスすればよい。
フォームで入力されたデータがWebページに送信される場合、そのデータの形式(コンテンツ・タイプ)にはいくつかの種類があるが、デフォルト(<form>タグのenctype属性で特に指定されていない場合)の形式が「application/x-www-form-urlencoded」という形式である(詳細については「HTML 4.01 Specification」の「17.13.4 Form content types」などを参照)。
これは、「パラメータ名と値」を=記号でペアにし、各ペアを&記号で連結する形式だ(日本語や一部の記号についてはエンコードが必要となる。このエンコードについては「TIPS:文字列をURLエンコードするには?」を参照)。
つまりGoogle翻訳機能の場合には、以下のようなポスト・データが送信されることになる。
text=<エンコードした文字列>&langpair=ja|en&hl=en&ie=UTF8
プログラムからアクセスする場合には、このような文字列を作成して送信すればよい。具体的には、この文字列をバイト列に変換してから、リクエストであるHttpWebRequestオブジェクトのGetRequestStreamメソッドにより得たストリームに対して書き込む。
上記のような文字列が文字列変数paramに入っているとすると、このためのコードは次のようになる(C#の場合。VB.NETの場合は以下のサンプル・プログラムを参照)。
byte[] data = Encoding.ASCII.GetBytes(param);
Stream reqStream = req.GetRequestStream();
reqStream.Write(data, 0, data.Length);
reqStream.Close();
文字列のバイト列への変換については「TIPS:文字列をシフトJISとしてバイト列に変換するには?」で解説している。
以下に、Google翻訳機能を使って日本語の文字列を英語に翻訳するサンプル・プログラムを示す。
なお、このプログラムではポスト・データとなる文字列の作成を分かりやすく記述するためにハッシュテーブルを利用している。これについては「TIPS:ハッシュテーブル(連想配列)を使うには?」で解説している。
// jetrans.cs
using System;
using System.IO;
using System.Net;
using System.Web;
using System.Text;
using System.Collections;
public class GoogleTranslate {
static void Main() {
Encoding enc = Encoding.UTF8;
string input = "私は普通のC#プログラマです。";
string url = "http://translate.google.com/translate_t";
string param = "";
// ポスト・データの作成
Hashtable ht = new Hashtable();
ht["text"] = HttpUtility.UrlEncode(input, enc);
ht["langpair"] = "ja|en";
ht["hl"] = "en";
ht["ie"] = "UTF8";
foreach (string k in ht.Keys) {
param += String.Format("{0}={1}&", k, ht[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;
// ポスト・データの書き込み
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, enc);
string html = sr.ReadToEnd();
sr.Close();
resStream.Close();
// 必要なデータの切り出し
// 結果は「wrap=PHYSICAL>〜</textarea>」にあるという前提
string startmark = "wrap=PHYSICAL>";
int start = html.IndexOf(startmark) + startmark.Length;
int end = html.IndexOf("</textarea>", start);
string result = html.Substring(start, end - start);
Console.WriteLine(result);
// 出力:I am the normal C# programmer.
}
}
// コンパイル方法:jetrans.cs
' jetrans.vb
Imports System
Imports System.IO
Imports System.Net
Imports System.Web
Imports System.Text
Imports System.Collections
Public Class GoogleTranslate
Shared Sub Main()
Dim enc As Encoding = Encoding.UTF8
Dim input As String = "私は普通のC#プログラマです。"
Dim url As String = "http://translate.google.com/translate_t"
Dim param As String = ""
' ポスト・データの作成
Dim ht As Hashtable = new Hashtable()
ht("text") = HttpUtility.UrlEncode(input, enc)
ht("langpair") = "ja|en"
ht("hl") = "en"
ht("ie") = "UTF8"
For Each k As String In ht.Keys
param = param & String.Format("{0}={1}&", k, ht(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
' ポスト・データの書き込み
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, enc)
Dim html As String = sr.ReadToEnd()
sr.Close()
resStream.Close()
' 必要なデータの切り出し
' 結果は「wrap=PHYSICAL>〜</textarea>」にあるという前提
Dim startmark As String = "wrap=PHYSICAL>"
Dim rstart As Integer = html.IndexOf(startmark) + startmark.Length
Dim rend As Integer = html.IndexOf("</textarea>", rstart)
Dim result As String = html.Substring(rstart, rend - rstart)
Console.WriteLine(result)
' 出力:I am the normal C# programmer.
End Sub
End Class
' コンパイル方法:vbc /r:System.dll /r:System.Web.dll jetrans.vb
結果ページ(レスポンス)の取得についてはGETメソッドを使う場合と同様であるため、詳しくは「TIPS:WebRequest/WebResponseクラスでWebページを取得するには?」を参照していただきたい。
カテゴリ:クラス・ライブラリ 処理対象:ネットワーク
使用ライブラリ:WebRequestクラス(System.Net名前空間)
使用ライブラリ:WebResponseクラス(System.Net名前空間)
使用ライブラリ:HttpWebRequestクラス(System.Net名前空間)
使用ライブラリ:HttpUtilityクラス(System.Web名前空間)
使用ライブラリ:Hashtableクラス(System.Collections名前空間)
関連TIPS:WebRequest/WebResponseクラスでWebページを取得するには?
関連TIPS:文字列をURLエンコードするには?
関連TIPS:文字列をシフトJISとしてバイト列に変換するには?
関連TIPS:ハッシュテーブル(連想配列)を使うには?
Copyright© Digital Advantage Corp. All Rights Reserved.