문제

나는 이것을 먼저 게시했다 : httpwebrequest : x-www-form enclosed가있는 웹 레퀴즈를 통해 Canada Post에서 우편 번호를 찾는 방법?.

Anthonywjones의 제안에 따라 그의 제안에 따라 코드를 변경했습니다.

내 문의가 계속되면 시간이 지남에 따라 캐나다의 콘텐츠 유형이 "Application/XHTML+XML, Text/XML, Text/Html; charset = utf-8".

내 질문은 다음과 같습니다.

  1. 이러한 컨텐츠 유형 웹 사이트에 대해 어떻게 웹 레퀴스트를 사용합니까?
  2. 이름 valuecollection 객체를 계속 유지해야합니까?
  3. 이전 질문 내에서 저에게 귀중한 정보를 관대하게 제공 한 Scott Lance에 따르면, WebRequest는 내용 유형이 무엇이든간에 정보의 유형을 반환해야합니다.
  4. 컨텐츠 유형 변경으로 인해 코드를 변경해야합니까?

내 코드는 내 코드가 있습니다.

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의 조회 페이지는 다음과 같이 작동합니다.

  1. 첫 번째 페이지는 주소 값을 수락하는 양식입니다.
  2. 이 페이지는 두 번째 URL에 게시합니다.
  3. 이 두 번째 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 요청을 만들 수 있으므로 실제로 필요한 헤더가 있는지 확인할 수 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top