WebRequest:このcontentType =“ Application/xhtml+xml、text/xml、text/htmlに対してWebRequestを使用して郵便番号を見つける方法。 charset = utf-8 "?
-
12-09-2019 - |
質問
私はこれを最初に投稿しました: httpwebrequest:X-www-form-eclosedを使用したWebrequestを通じてカナダポストで郵便番号を見つける方法は?.
Anthonywjonesの提案に従って、彼の提案に従ってコードを変更しました。
私の問い合わせの継続で、私はカナダポストのコンテンツタイプがそうである可能性が高いことに時間とともに気づきました 「アプリケーション/XHTML+XML、TEXT/XML、TEXT/HTML; CHARSET = UTF-8」.
私の質問は次のとおりです。
- このようなコンテンツタイプのWebサイトに対してどのようにWebRequestを作成しますか?
- namevalueCollectionオブジェクトを継続する必要がありますか?
- 私の前の質問の中で貴重な情報をgeneしみなく提供してくれたスコット・ランスによると、WebRequestはコンテンツタイプが何であれ、情報の種類を返します。
- コンテンツタイプの変更のためにコードを変更する必要がありますか?
私のコードが私のコードを理解しやすいように、私のコードを紹介します。
internal class PostalServicesFactory {
/// <summary>
/// Initializes an instance of GI.BusinessSolutions.Services.PostalServices.Types.PostalServicesFactory class.
/// </summary>
internal PostalServicesFactory() {
}
/// <summary>
/// Finds a Canadian postal code for the provided Canadian address.
/// </summary>
/// <param name="address">The instance of GI.BusinessSolutions.Services.PostalServices.ICanadianCityAddress for which to find the postal code.</param>
/// <returns>The postal code found, otherwise null.</returns>
internal string FindPostalCode(ICanadianCityAddress address) {
if (address == null)
throw new InvalidOperationException("No valid address specified.");
using (ServicesWebClient swc = new ServicesWebClient()) {
var values = new System.Collections.Specialized.NameValueCollection();
values.Add("streetNumber", address.StreetNumber.ToString());
values.Add("numberSuffix", address.NumberSuffix);
values.Add("suite", address.Suite);
values.Add("streetName", address.StreetName);
values.Add("streetDirection", address.StreetDirection);
values.Add("city", address.City);
values.Add("province", address.Province);
byte[] resultData = swc.UploadValues(@"http://www.canadapost.ca/cpotools/apps/fpc/personal/findByCity", "POST", values);
return Encoding.UTF8.GetString(resultData);
}
}
private class ServicesWebClient : WebClient {
public ServicesWebClient()
: base() {
}
protected override WebRequest GetWebRequest(Uri address) {
var request = (HttpWebRequest)base.GetWebRequest(address);
request.CookieContainer = new CookieContainer();
return request;
}
}
}
このコードは、実際には、フォームのHTMLソースコードを返します。1つは、郵便番号検索で処理するために必要な情報を記入する必要があります。私が望んでいるのは、HTMLソースコードなど、発見された郵便番号にあるものを取得することです。
編集: これが私が今得ているWebExceptionです:「このタイプの動詞でコンテンツ本体を送ることができません」。 (これは、フランスの例外「不可能なd'Empoyer un Corps de Contenu Avecce Type de Verbe」からの翻訳です。)
これが私のコードです:
internal string FindPostalCode(string url, ICanadianAddress address) {
string htmlResult = null;
using (var swc = new ServiceWebClient()) {
var values = new System.Collections.Specialized.NameValueCollection();
values.Add("streetNumber", address.StreetNumber.ToString());
values.Add("numberSuffix", address.NumberSuffix);
values.Add("suite", address.Suite);
values.Add("streetName", address.StreetName);
values.Add("streetDirection", address.StreetDirection);
values.Add("city", address.City);
values.Add("province", address.Province);
swc.UploadValues(url, @"POST", values);
string redirectUrl = swc.ResponseHeaders.GetValues(@"Location")[0];
=> swc.UploadValues(redirectUrl, @"GET", values);
}
return htmlResult;
}
例外を引き起こす行は、「=>」で指摘されています。私はメソッドとして取得することはできないようですが、これは私にやるように私に言われたものです...
ここで何が欠けているのか考えてみませんか?私はジャスティン(回答を参照)が私にするように勧めたことをしようとします。
助けてくれてありがとう! :-)
解決
スクリーンスクレイピングの世界への紹介として、あなたは非常に難しいケースを選びました!カナダポストのルックアップページは次のように機能します:
- 最初のページは、アドレス値を受け入れるフォームです
- このページは2番目のURLに投稿します。
- その2番目のURLは、郵便番号を含むHTML応答を実際に表示する3番目のURLに順番にリダイレクト(HTTP 302リダイレクトを使用)を3番目のURLにリダイレクトします。
さらに悪いことに、ステップ#3のページは、ステップ#1で設定されたCookieを知る必要があります。したがって、同じものを使用する必要があります CookieContainer
3つのリクエストすべてについて(同じものを送信するのに十分かもしれませんが CookieContainer
#2と#3のみ)。
さらに、これらのリクエストにも追加のHTTPヘッダーを送信する必要がある場合があります。問題に遭遇している場所は、デフォルトでHTTPWEBREQUESTがあなたのために透過的にリダイレクトを処理するのではないかと疑っていますが、それが透過的にリダイレクトすると、ブラウザになりすまして必要な適切なHTTPヘッダーを追加しない可能性があります。
解決策は、を設定することです HttpWebRequest
's AllowAutoRedirect
財産を偽りにし、自分自身をリダイレクトします。言い換えれば、最初の要求がリダイレクトを返したら、でURLを引き出す必要があります HttpWebResponse
's Location:
ヘッダ。その後、新しいものを作成する必要があります HttpWebRequest
(今回は、投稿ではなく定期的なGETリクエスト)。同じクッキーを送ることを覚えています! ( CookieContainer
クラスはこれを非常に簡単にします)
また、セッションCookieをセットアップするには、追加のリクエスト(上記のリストの#1)を作成する必要がある場合があります。もし私があなただったなら、私はこれが必要であると仮定し、単にそれを問題として排除し、後でそのステップを削除して、あなたのソリューションがまだ機能するかどうかを確認してみてください。
Fiddlerをダウンロードして使用します(www.fiddlertool.com)これらすべてを助けるために。 Fiddlerを使用すると、HTTPリクエストがワイヤーを介して視聴することができ、(リクエストビルダー機能を介して)HTTPリクエストを作成できるようにして、実際にどのヘッダーが必要かを確認できます。