HttpWebRequest vs Webclient (特殊方案)



我知道这个问题之前在这个线程中已经回答过,但我似乎找不到细节。

在我的场景中,我正在构建一个控制台应用程序,该应用程序将密切关注 html 页面源代码的任何更改。如果发生任何更新/更改,我将执行进一步的操作。此外,我还会在每 1 秒后执行一次请求,或者在上一个请求完成后立即执行。

似乎无法弄清楚我应该使用 HttpWebRequestWebClient来下载 html 页面源代码并进行比较?您认为在我的情况下,什么是理想的解决方案?速度和可靠性:)

我会选择HttpWebRequst,因为它没有那么抽象,并且可以让您经常摆弄HTTP参数。例如,如果服务器返回"文件未更改",它为您提供了不下载整个页面的选项。

如果您在请求中添加一些参数,例如IfModifiedSince(可能是 HEAD 或 GET 请求(,服务器可能会返回响应代码 304 - 未修改。有关进一步说明,请参阅 HTTP 中的缓存说明。

关键是要确保仅在自上次获取页面以来实际修改时下载整个页面。大多数情况下它不会被更改(我想,如果不了解您的域就无法确定(,因此您只需要从服务器获得轻量级响应,该响应仅声明"此处没有任何更改"。

更新:演示IfModifiedSince属性使用的代码示例:

bool IsResourceModified(string url, DateTime dateTime) {            
    try {
        var request = (HttpWebRequest)HttpWebRequest.Create(new Uri(url));
        request.IfModifiedSince = dateTime;
        request.Method = "HEAD";
        var response = (HttpWebResponse)request.GetResponse();
        return true;
    }
    catch(WebException ex) {
        if(ex.Status != WebExceptionStatus.ProtocolError)
            throw;
        var response = (HttpWebResponse)ex.Response;
        if(response.StatusCode != HttpStatusCode.NotModified)
            throw;
        return false;    
    }
}

如果页面自dateTime日期以来被修改,则此方法应返回true,如果没有,则返回false。 如果您发出 HEAD 请求并且服务器返回 304 - 未修改(这有点不幸(,GetResponse方法将抛出WebException。我们必须确保这不是其他 Web 连接问题,这就是为什么我检查 Web 异常的状态和响应中的 HTTP 状态。如果其他任何事情导致异常,我们只是进一步抛出它。

Console.WriteLine(IsResourceModified("http://example.com", new DateTime(2009)));
Console.WriteLine(IsResourceModified("http://example.com", DateTime.Now));

此示例代码生成输出:

True
False

注意:请务必阅读Jim Mischel对这个答案的补充,因为他对这种技术几乎没有给出很好的建议。

我打算把它作为对@Dyppl回应的评论,但它变得太长了。

Dyppl的回答通常是很好的建议,也是我解决这个问题的方式。但是,您应该记住一些事项。

首先,没有理由执行HEAD请求,然后GET页面是否已修改。您可以使用 IfModifiedSince 标头集执行GET,服务器将返回整个页面或 304。首先执行HEAD,然后执行"GET",最终会向服务器发出两个请求,这违背了条件请求的大部分目的。

其次,应将 IfModifiedSince 属性设置为上一个响应返回的LastModified值(即 HttpWebResponse.LastModified (,因为服务器的时间可能与您的计算机不同步。此外,我发现很大一部分网站,尤其是那些生成内容的网站(如WordPress博客(都在撒谎。它们始终在LastModified标头中返回当前日期/时间。因此,在这些站点上进行If-Modified-Since检查没有任何好处。

如果您知道该网站存在谎言并始终返回当前日期/时间,则可以跟踪下载页面时从页面返回的ContentLength标头。然后,当您想要检查页面是否已更改时,请执行HEAD请求并使用保存的值检查返回的ContentLength标头。如果它们匹配,则页面不太可能已更改。如果它们不匹配,请执行GET请求以更新页面副本并保留新ContentLength

此技术确实存在缺点,即如果页面已更改,则需要两个请求。它也不是在所有服务器上都是 100% 可靠的。有些会为HEAD请求返回不同的ContentLength,有些根本不返回有效的ContentLength。也就是说,我发现它对大量网站有效。

最新更新