WebRequest“HEAD”轻量级替代品

Posted

技术标签:

【中文标题】WebRequest“HEAD”轻量级替代品【英文标题】:WebRequest "HEAD" light weight alternative 【发布时间】:2011-07-18 06:01:35 【问题描述】:

我最近发现以下内容不适用于某些网站,例如 IMDB.com。

class Program
    
        static void Main(string[] args)
        
            try
            
                System.Net.WebRequest wc = System.Net.WebRequest.Create("http://www.imdb.com"); //args[0]);

                ((HttpWebRequest)wc).UserAgent = "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/525.19 (Khtml, like Gecko) Chrome/0.2.153.1 Safari/525.19";
                wc.Timeout = 1000;
                wc.Method = "HEAD";
                WebResponse res = wc.GetResponse();
                var streamReader = new System.IO.StreamReader(res.GetResponseStream());

                Console.WriteLine(streamReader.ReadToEnd());
            
            catch (Exception ex)
            
                Console.WriteLine(ex.Message);
            
        
    

它返回一个 HTTP 405(不允许的方法)。我的问题是,我使用与上面非常相似的代码来检查链接是否有效以及绝大多数情况下它是否正常工作。我可以将它切换到等于 GET 的方法并且它可以工作(随着超时的增加),但这会使事情减慢一个数量级。我假设 405 响应是 IMDB 服务器端的服务器配置。

有没有办法让我在 .NET 中以轻量级的方式做与上述相同的事情?或者,有没有办法修复上述代码,使其作为与 imdb 一起使用的 GET 请求工作?

【问题讨论】:

我不得不增加超时时间,但您在上面发布的代码对我有用。将其更改为 POST 没有任何意义,因为您没有任何数据要发布。你的标题谈到了 HEAD,但你没有做 HEAD 请求。请澄清问题是什么,因为您的“损坏”代码工作正常。 呃,标题中的错字真的很愚蠢。现已修复...思考一件事并输入另一件事的经典示例。当您运行上述代码时,您没有收到 405 响应?编辑:好的,意识到我的代码也有缺陷。以上是我要发布的内容,并经过编辑以给出 405 错误(并且有意义.....) 【参考方案1】:

使用套接字(而不是 HttpRequest 或 WebClient)自行打开连接,并在阅读状态代码后立即关闭流。幸运的是,状态码靠近响应流的顶部 :)

【讨论】:

【参考方案2】:

您必须澄清“轻量级”的含义。你想达到什么目的?

您是否可以使用 GET/POST/HEAD/DELETE/etc 将取决于 URL 以及在该 URL 的服务器上运行的应用程序中配置的内容。

如果您只想查看是否可以在不实际下载内容的情况下建立连接,您可以尝试使用sockets 启动与端口 80 的连接,但没有真正可靠或普遍支持只需更改 HTTP 方法即可。

【讨论】:

好吧,基本上我现在使用的 HEAD 请求是 a) 检查站点是否实际存在 b) 如果站点存在,对于其中的每个链接,验证它们是否确实存在(因此每个图像、样式表等...)。因此,在一些图像重的页面上,它实际上可以被调用数百次。所以,我所说的轻量级主要是指网络流量。 对...关于带宽,我能想到的唯一更轻量级的方法是使用套接字手动构建您的 HTTP 请求,获取足够的响应以确定 HTTP 状态代码,然后关闭连接。 走手工制作的 HTTP 路线真的会绕过 405 错误结果吗?编辑:呃,我应该说的状态结果,我想技术上 HTTP 405 实际上并不是一个错误。只有少数网站返回 405,我实际上不知道是什么部分导致了该响应。现在,我假设它是 HEAD 请求,但我不确定。 HEAD 请求是导致问题的原因。我所说的手工制作 HTTP 请求的意思是您将使用 GET,这是服务器所期望的,但是由于您可以控制下载的内容,因此您可以只下载响应标头然后在下载正文之前终止连接。【参考方案3】:

如果 HEAD 返回 405,则意味着服务器不支持 HEAD(至少对于该 URL),您将转而使用 GET。大多数网站都应该支持 HEAD,因此您可能希望默认使用 HEAD,但如果它抛出 405,您可能会回退到该域的 GET。或者,也许您想为每个请求先尝试 HEAD; YMMV。

如果服务器需要 GET 并且您想减少网络流量,您可以尝试执行条件 GET 和/或部分 GET(参见例如 RFC2616)。我从来没有尝试过用 WebRequest 做这些,但我认为它可以让你添加自定义的传出 HTTP 标头,所以你应该可以做到。

另外,不要忘记,如果你正在编写一个蜘蛛(你显然是),你应该尊重服务器的 robots.txt,并且将你的请求限制为每两秒一个请求也是有礼貌的,所以你不会在服务器上划线。

【讨论】:

感谢您的回复。我实际上并不是在写蜘蛛,最终产品在本质上比其他任何东西都更接近网络浏览器。我按照您之前的建议做了( HEAD 请求,然后在 405 上执行了完整的 GET ),这是我目前的做事方式,但不是最佳的。我将研究部分 GET,这可能是完美的。谢谢。

以上是关于WebRequest“HEAD”轻量级替代品的主要内容,如果未能解决你的问题,请参考以下文章

Tornado入门

检测 WebRequest 的 HTTP 代理错误

C# - WebRequest 不返回不同的页面

Web 浏览器组件的好替代品?

nginx

日志分析系统ELK之Kibanaes的替代metricbeat