使用curl抓取网页遇到HTTP跳转时得到多个HTTP头部的问题
2012-04-08 00:35
519 查看
Woody的技术Blog » 使用curl抓取网页遇到HTTP跳转时得到多个HTTP头部的问题
Woody Leave a comment
Go to comments
在PHP的CURL扩展中,是可以通过CURL自身的设计自动处理HTTP 30X的跳转的。这个特性在使用起来很简单:
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 的实现:
既然如此,想要把最后跳转到的地址的 Header 和 Body 区别出来,如果能知道跳转的次数就好了。毕竟每多跳一次,就多了一个 Header 部分,而且多个 Header 之间仍然是以 "\r\n\r\n" 分隔的。于是看 PHP curl 的 curl_getinfo,在 Return Values 中看到了 "redirect_count" 一项,正是要找的。
使用curl抓取网页遇到HTTP跳转时得到多个HTTP头部的问题
June 21st, 2011Woody Leave a comment
Go to comments
在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
而我在命令行下直接使用 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" 一项,正是要找的。
相关文章推荐
- 使用curl抓取网页遇到HTTP跳转时得到多个HTTP头部的问题
- 使用curl抓取网页遇到HTTP跳转时得到多个HTTP头部的问题
- 使用HtmlAgilityPack和ScrapySharp抓取网页数据遇到的几个问题解决方法——格式编码问题
- php使用curl抓取网页显示空白的问题.
- C#如何使用HttpWebRequest、HttpWebResponse模拟浏览器抓取网页内容
- 使用HttpClient+Jericho HTML Parser 实现网页抓取
- JSP学习笔记(七十五):使用HttpClient远程抓取网页内容
- c++ curl 的简单使用和从网页上抓取图片的代码
- 关于http强制跳转https遇到的问题, 阿里云埋坑
- 使用Curl进行抓取远程内容时url中文编码问题示例探讨
- ASIHTTPRequest使用过程中遇到的问题及解决办法
- 【C/S通信交互之Http篇】Cocos2dx(Client)使用Curl与Jetty(Server)实现手机网游Http通信框架(内含解决curl.h头文件找不到问题)
- 使用QtWebKit加载网页,编译时遇到的问题
- PHP使用CURL实现多线程抓取网页
- httpclient自动获取页面编码,解决网页抓取乱码问题
- libcurl 使用说明和网页抓取 linux下的curl编程
- 网页版 treeview使用中遇到的问题
- Asp 使用 Microsoft.XMLHTTP 抓取网页内容无乱码处理,并过滤须要的内容
- 使用Curl进行抓取远程内容时url中文编码问题示例探讨
- Java、C#双语版HttpHelper类(解决网页抓取乱码问题)