WebRequest :이 contentType =“Application/XHTML+XML, Text/XML, Text/Html; charset = utf-8”?
-
12-09-2019 - |
문제
나는 이것을 먼저 게시했다 : httpwebrequest : x-www-form enclosed가있는 웹 레퀴즈를 통해 Canada Post에서 우편 번호를 찾는 방법?.
Anthonywjones의 제안에 따라 그의 제안에 따라 코드를 변경했습니다.
내 문의가 계속되면 시간이 지남에 따라 캐나다의 콘텐츠 유형이 "Application/XHTML+XML, Text/XML, Text/Html; charset = utf-8".
내 질문은 다음과 같습니다.
- 이러한 컨텐츠 유형 웹 사이트에 대해 어떻게 웹 레퀴스트를 사용합니까?
- 이름 valuecollection 객체를 계속 유지해야합니까?
- 이전 질문 내에서 저에게 귀중한 정보를 관대하게 제공 한 Scott Lance에 따르면, 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 소스 코드를 반환합니다. 내가 원하는 것은 HTML 소스 코드 또는 발견 된 우편 번호와 관련된 모든 것을 얻는 것입니다.
편집하다: 다음은 내가 지금 얻는 WebException입니다. "이러한 유형의 동사로 콘텐츠 본문을 보낼 수 없습니다." (이것은 프랑스 예외의 번역입니다.
내 코드는 다음과 같습니다.
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;
}
예외를 일으키는 줄은 "=>"로 가리 킵니다. 나는 방법으로 얻을 수 없지만 이것은 나에게 말한 것입니다 ...
내가 여기서 무엇을 놓치고 있는지 아십니까? 저스틴 (답변 참조)이 저에게 제안한 일을하려고합니다.
도움을 주셔서 감사합니다! :-)
해결책
스크린 스크래핑의 세계에 대한 소개로서, 당신은 매우 어려운 경우를 선택했습니다! Canada Post의 조회 페이지는 다음과 같이 작동합니다.
- 첫 번째 페이지는 주소 값을 수락하는 양식입니다.
- 이 페이지는 두 번째 URL에 게시합니다.
- 이 두 번째 URL은 (HTTP 302 리디렉션 사용) 세 번째 URL로 리디렉션하여 우편 번호가 포함 된 HTML 응답을 실제로 보여줍니다.
설상가상으로, 3 단계의 페이지는 1 단계에서 쿠키 세트를 알아야합니다. 따라서 똑같이 사용해야합니다 CookieContainer
세 가지 요청 모두에 대해 (동일하게 보내기에 충분할 수도 있지만 CookieContainer
#2와 #3에만 해당).
또한 수락과 같이 이러한 요청에 추가 HTTP 헤더를 보내야 할 수도 있습니다. 문제가 발생하는 위치는 기본적으로 HTTPWebRequest가 투명하게 투명하게 리디렉션되지만 투명하게 리디렉션되면 브라우저를 가장하는 데 필요한 올바른 HTTP 헤더를 추가하지 않을 수 있습니다.
해결책은 다음을 설정하는 것입니다 HttpWebRequest
'에스 AllowAutoRedirect
속성을 거짓으로하고 리디렉션을 처리하십시오. 다시 말해, 첫 번째 요청이 리디렉션을 반환하면 URL을 꺼내야합니다. HttpWebResponse
'에스 Location:
헤더. 그러면 새로운 것을 만들어야합니다 HttpWebRequest
(이번에는 게시물이 아닌 정기적 인 GET 요청) 해당 URL에 대한. 같은 쿠키를 보내기 위해 기억하십시오! (그만큼 CookieContainer
수업은 이것을 매우 쉽게 만듭니다)
세션 쿠키를 설정하려면 추가 요청 (위의 내 목록에서 1 위)을 만들어야 할 수도 있습니다. 내가 당신이라면, 나는 이것이 필요하다고 가정하고, 단순히 문제로 제거하고 그 단계를 제거하고 솔루션이 여전히 작동하는지 확인하십시오.
Fiddler를 다운로드하고 사용하고 싶을 것입니다 (www.fiddlertool.com)이 모든 것을 도와 드리겠습니다. Fiddler는 HTTP 요청이 와이어를 넘어가는 것을 볼 수 있으며 (요청 빌더 기능을 통해) HTTP 요청을 만들 수 있으므로 실제로 필요한 헤더가 있는지 확인할 수 있습니다.