Запрос HttpWebRequest:Как узнать почтовый индекс в Canada Post с помощью веб-запроса с приложенной x-www-формой?
-
22-07-2019 - |
Вопрос
В настоящее время я пишу несколько тестов, чтобы улучшить свои навыки взаимодействия с Интернетом через Windows Forms.Один из таких тестов - найти почтовый индекс, который должен быть возвращен веб-сайтом Canada Post.
- Мой URL-адрес по умолчанию установлен на: http://www.canadapost.ca/cpotools/apps/fpc/personal/findByCity?execution=e4s1
- Обязательными полями формы являются: Номер улицы, Название улицы, город, провинция
- Тип содержимого - "приложение/x-www-form-enclosed".
Редактировать: Пожалуйста, используйте значение "application/x-www-form-encoded" вместо значения пункта 3 в качестве ContentType.(Спасибо EricLaw-MSFT!)
Результат, который я получаю, не соответствует ожидаемому.Я получаю исходный HTML-код страницы, где я мог бы вручную ввести информацию, чтобы найти почтовый индекс, но не исходный HTML-код с найденным почтовым индексом.Есть какие-нибудь идеи о том, что я делаю не так?
Должен ли я рассмотреть возможность перехода по пути XML?Прежде всего, возможно ли осуществлять поиск на Canada Post анонимно?
Вот пример кода для лучшего описания:
public static string FindPostalCode(ICanadadianAddress address) {
var postData = string.Concat(string.Format("&streetNumber={0}", address.StreetNumber)
, string.Format("&streetName={0}", address.StreetName)
, string.Format("&city={0}", address.City)
, string.Format("&province={0}", address.Province));
var encoding = new ASCIIEncoding();
byte[] postDataBytes = encoding.GetBytes(postData);
request = (HttpWebRequest)WebRequest.Create(DefaultUrlSettings);
request.ImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Anonymous;
request.Container = new CookieContainer();
request.Timeout = 10000;
request.ContentType = contentType;
request.ContentLength = postDataBytes.LongLength;
request.Method = @"post";
var senderStream = new StreamWriter(request.GetRequestStream());
senderStream.Write(postDataBytes, 0, postDataBytes.Length);
senderStream.Close();
string htmlResponse = new StreamReader(request.GetResponse().GetResponseStream()).ReadToEnd();
return processedResult(htmlResponse); // Processing the HTML source code parsing, etc.
}
С моей точки зрения, я, похоже, застрял в бутылочном горлышке.Я не нахожу выхода к желаемому результату.
Редактировать: Похоже, что должны быть параметры для ContentType этого сайта.Позвольте мне объяснить.
- Есть один с "мета"-переменными, который оговаривает следующее:
meta http-equiv="Content-Type" content="приложение/xhtml+xml, текст/xml, текст/html;кодировка=utf-8"
- И еще один ниже по коду, который читается как:
идентификатор формы="fpcByAdvancedSearch: fpcSearch" name="fpcByAdvancedSearch: fpcSearch" method="опубликовать" action="/cpotools/apps/fpc/personal/findByCity?execution=e1s1" enctype="приложение/x-www-форма-urlencoded"
Мой вопрос заключается в следующем:Какого из них я должен придерживаться?
Позвольте мне угадать, первый ContentType следует рассматривать, поскольку второй предназначен только для другого запроса к функции или около того при публикации данных?
Редактировать: Согласно запросу, чем ближе я к решению, тем ниже указан этот вопрос: Веб-запрос:Как найти почтовый индекс, используя веб-запрос по этому ContentType=”application/xhtml+xml, text /xml, текст / html;кодировка=utf-8”?
Спасибо за любую помощь!:-)
Решение
Я пытаюсь понять причину, по которой вы не используете класс WebClient:-
var fields = new NameValueCollection();
fields.Add("streetnumber", address.StreetNumber);
fields.Add("streetname", address.StreetName);
fields.Add("city", address.City);
fields.Add("province", address.Province);
var wc = new WebClient();
byte[] resultData = wc.UploadValues(url, fields);
string result = Encoding.Default.GetString(resultData);
Возможно, вы захотите проверить кодировку, используемую сервером при отправке результатов, если он использует UTF-8, измените последнюю строку на:-
string result = Encoding.UTF8.GetString(resultData);
Некоторые проблемы, которые я замечаю в вашем исходном коде:-
- Первое поле имеет префикс &, которого там не должно быть.
- Вам нужно использовать вызов
Uri.EscapeDataString
для каждого значения поля. - Вы пытаетесь построить поток памяти вокруг результата
GetRequestStream
, я не вижу, чего бы это дало, даже если быMemoryStream
был такой конструктор, но он все равно не работает.Просто напишите непосредственно в поток, возвращаемыйGetRequestStream
Если вы уже сделали это, приобретите себе копию скрипач таким образом, вы можете наблюдать, что происходит, когда стандартная форма успешно запрашивает данные, и что делает ваш код.
Редактировать:Если у вас есть доказательства того, что отсутствие контейнера для файлов cookie является причиной того, что WebClient не работает, вы могли бы попробовать этот подход:-
public class MyWebClient : WebClient
{
protected override WebRequest GetWebRequest (Uri address)
{
WebRequest request = (WebRequest) base.GetWebRequest (address);
request.Container = new CookieContainer();
return request;
}
}
Теперь используйте мой приведенный выше код, чтобы, но вместо этого, создать экземпляр WebClient
экземпляр MyWebClient
вместо этого.
Другие советы
HttpWebRequest вернет содержимое запрошенного URL-адреса.Если это HTML-страница, она вернет HTML-разметку.Если содержимое страницы является XML, то оно вернет XML-разметку.
Похоже, вам нужен веб-сервис.Я хотел бы посмотреть, есть ли на этом сайте какие-либо веб-сервисы, доступные для обработки запросов такого типа.Если они это сделают, то он вернет XML, разметку JSON в ответ на ваш запрос.В противном случае вам остается проанализировать выходные данные запроса.