首页IT科技获取curl命令返回结果(使用curl抓取网页遇到HTTP跳转时得到多个HTTP头部的问题)

获取curl命令返回结果(使用curl抓取网页遇到HTTP跳转时得到多个HTTP头部的问题)

时间2025-04-30 17:21:13分类IT科技浏览3636
导读:使用curl抓取网页遇到HTTP跳转时得到多个HTTP头部的问题...

使用curl抓取网页遇到HTTP跳转时得到多个HTTP头部的问题

在PHP的CURL扩展中            ,是可以通过CURL自身的设计自动处理HTTP 30X的跳转的           。这个特性在使用起来很简单:

$ch = curl_init(); curl_setopt($ch, CURLOPT_URL, http://www.example.com); curl_setopt($ch, CURLOPT_HEADER, true); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); $content = curl_exec($ch);

正常情况下                 ,$content 中的结果包括了 HTTP 头和 body 的信息      ,且以 "\r\n\r\n" 分隔                  。因此可以用

list($header, $body) = explode("\r\n\r\n", $content, 2);

来分别取得这两部分      。不过如果在要访问的地址上发生了 HTTP 跳转         ,这时 curl_exec 执行得到的结果中就包含了两次访问的头部        。例如把上面的代码的 URL 部分换成我这里的:

curl_setopt($ch, CURLOPT_URL, http://cn.programmingnote.com);

当访问 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 的实现:

/* {{{ proto bool curl_exec(resource ch) Perform a cURL session */ PHP_FUNCTION(curl_exec) { CURLcode error; zval *zid; php_curl *ch; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zid) == FAILURE) { return; } ZEND_FETCH_RESOURCE(ch, php_curl *, &zid, -1, le_curl_name, le_curl); _php_curl_cleanup_handle(ch); error = curl_easy_perform(ch->cp); SAVE_CURL_ERROR(ch, error); /* CURLE_PARTIAL_FILE is returned by HEAD requests */ if (error != CURLE_OK && error != CURLE_PARTIAL_FILE) { if (ch->handlers->write->buf.len > 0) { smart_str_free(&ch->handlers->write->buf); } RETURN_FALSE; } // more code ... }

从名字上可以看出      ,真正处理 HTTP 访问的代码应该是在 curl_easy_perform 做的  。经查证                 ,这个函数是属于 libcurl 这个库的            ,和 PHP 扩展已经没有关系了                 。并且   ,我写了一段直接使用 libcurl 库的代码                 ,和 PHP 中的用法并没有太大的区别              ,也没有特殊的参数用来设计是保留多次的 HTTP Header 还是只保留最后的一次 Header               。

#include <curl/curl.h> #include <stdio.h> int main() { CURL *handler = curl_easy_init(); curl_easy_setopt(handler, CURLOPT_HEADER, 1); curl_easy_setopt(handler, CURLOPT_FOLLOWLOCATION, 1); curl_easy_setopt(handler, CURLOPT_URL, "http://cn.programmingnote.com"); int res = curl_easy_perform(handler); printf("%d\n", res); return 0; }

和在 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版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
layui iconfont(layui-icon各种常用动态图标) 网络兼职是什么东西(网络兼职都是做什么的-【网络兼职】正规网上兼职平台有哪些?)