获取curl命令返回结果(使用curl抓取网页遇到HTTP跳转时得到多个HTTP头部的问题)
使用curl抓取网页遇到HTTP跳转时得到多个HTTP头部的问题
在PHP的CURL扩展中 ,是可以通过CURL自身的设计自动处理HTTP 30X的跳转的 。这个特性在使用起来很简单:
正常情况下 ,$content 中的结果包括了 HTTP 头和 body 的信息 ,且以 "\r\n\r\n" 分隔 。因此可以用
来分别取得这两部分 。不过如果在要访问的地址上发生了 HTTP 跳转 ,这时 curl_exec 执行得到的结果中就包含了两次访问的头部 。例如把上面的代码的 URL 部分换成我这里的:
当访问 cn.programmingnote.com 时 ,会触发一个 302 跳转 。此时 curl_exec 返回内容的开头是:
HTTP/1.1 302 Found
Date: Tue, 21 Jun 2011 08:15:58 GMT
Server: Apache/2.2.16 (Ubuntu)
X-Powered-By: PHP/5.3.3-1ubuntu9.5
Location: blog/
Vary: Accept-Encoding
Content-Length: 0
Content-Type: text/html
HTTP/1.1 200 OK
Date: Tue, 21 Jun 2011 08:15:58 GMT
Server: Apache/2.2.16 (Ubuntu)
X-Powered-By: PHP/5.3.3-1ubuntu9.5
X-Pingback: http://cn.programmingnote.com/blog/xmlrpc.php
Vary: Accept-Encoding
Transfer-Encoding: chunked
Content-Type: text/html; charset=UTF-8
很明显包含了两次的 HTTP 头部信息 。此时再用 explode("\r\n\r\n", $content, 2) 的方法会把下面的头部信息归到 HTTP Body 部分里去 。
而我在命令行下直接使用 curl 来访问包含跳转的地址时 ,却发现可以正确地把头部和 body 部分区别开 。因此我想到可能是 PHP 的 curl 扩展在实现方面有些问题 。于是我在 curl 扩展的代码中找到了 curl_exec 的实现:
从名字上可以看出 ,真正处理 HTTP 访问的代码应该是在 curl_easy_perform 做的 。经查证 ,这个函数是属于 libcurl 这个库的 ,和 PHP 扩展已经没有关系了 。并且 ,我写了一段直接使用 libcurl 库的代码 ,和 PHP 中的用法并没有太大的区别 ,也没有特殊的参数用来设计是保留多次的 HTTP Header 还是只保留最后的一次 Header 。
和在 PHP 中测试的结果一样,依然是记录了两个 Header。
既然如此 ,想要把最后跳转到的地址的 Header 和 Body 区别出来 ,如果能知道跳转的次数就好了 。毕竟每多跳一次,就多了一个 Header 部分 ,而且多个 Header 之间仍然是以 "\r\n\r\n" 分隔的 。于是看 PHP curl 的 curl_getinfo ,在 Return Values 中看到了 "redirect_count" 一项 ,正是要找的。
HTTP/1.1 302 Found
Date: Tue, 21 Jun 2011 08:15:58 GMT
Server: Apache/2.2.16 (Ubuntu)
X-Powered-By: PHP/5.3.3-1ubuntu9.5
Location: blog/
Vary: Accept-Encoding
Content-Length: 0
Content-Type: text/html
HTTP/1.1 200 OK
Date: Tue, 21 Jun 2011 08:15:58 GMT
Server: Apache/2.2.16 (Ubuntu)
X-Powered-By: PHP/5.3.3-1ubuntu9.5
X-Pingback: http://cn.programmingnote.com/blog/xmlrpc.php
Vary: Accept-Encoding
Transfer-Encoding: chunked
Content-Type: text/html; charset=UTF-8
创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!