Linux企业级项目实践之网络爬虫(12)——处理HTTP应答头
Web服务器的HTTP应答一般由以下几项构成:一个状态行,一个或多个应答头,一个空行,内容文档。设置HTTP应答头往往和设置状态行中的状态代码结合起来。例如,有好几个表示“文档位置已经改变”的状态代码都伴随着一个Location头,而401(Unauthorized)状态代码则必须伴随一个WWW-Authenticate头。
然而,即使在没有设置特殊含义的状态代码时,指定应答头也是很有用的。应答头可以用来完成:设置Cookie,指定修改日期,指示浏览器按照指定的间隔刷新页面,声明文档的长度以便利用持久HTTP连接,……等等许多其他任务。
设置应答头最常用的方法是HttpServletResponse的setHeader,该方法有两个参数,分别表示应答头的名字和值。和设置状态代码相似,设置应答头应该在发送任何文档内容之前进行。
HTTP应答头 说明:
Allow 服务器支持哪些请求方法(如GET、POST等)。
Content-Encoding 文档的编码(Encode)方法。只有在解码之后才可以得到Content-Type头指定的内容类型。利用gzip压缩文档能够显著地减少HTML文档的下载时间。Java的GZIPOutputStream可以很方便地进行gzip压缩,但只有Unix上的Netscape和Windows上的IE 4、IE 5才支持它。因此,Servlet应该通过查看Accept-Encoding头(即request.getHeader("Accept-Encoding"))检查浏览器是否支持gzip,为支持gzip的浏览器返回经gzip压缩的HTML页面,为其他浏览器返回普通页面。
Content-Length 表示内容长度。只有当浏览器使用持久HTTP连接时才需要这个数据。如果你想要利用持久连接的优势,可以把输出文档写入ByteArrayOutputStram,完成后查看其大小,然后把该值放入Content-Length头,最后通过byteArrayStream.writeTo(response.getOutputStream()发送内容。
Content-Type 表示后面的文档属于什么MIME类型。Servlet默认为text/plain,但通常需要显式地指定为text/html。由于经常要设置Content-Type,因此HttpServletResponse提供了一个专用的方法setContentType。
Date 当前的GMT时间。你可以用setDateHeader来设置这个头以避免转换时间格式的麻烦。
Expires 应该在什么时候认为文档已经过期,从而不再缓存它?
void * recv_response(void * arg)
{
begin_thread(); int i, n, trunc_head = 0, len = 0;
char * body_ptr = NULL;
evso_arg * narg = (evso_arg *)arg;
Response *resp = (Response *)malloc(sizeof(Response));
resp->header = NULL;
resp->body = (char *)malloc(HTML_MAXLEN);
resp->body_len = 0;
resp->url = narg->url; regex_t re;
if (regcomp(&re, HREF_PATTERN, 0) != 0) {/* compile error */
SPIDER_LOG(SPIDER_LEVEL_ERROR, "compile regex error");
} SPIDER_LOG(SPIDER_LEVEL_INFO, "Crawling url: %s/%s", narg->url->domain, narg->url->path); while(1) {
/* what if content-length exceeds HTML_MAXLEN? */
n = read(narg->fd, resp->body + len, 1024);
if (n < 0) {
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) {
/**
* TODO: Why always recv EAGAIN?
* should we deal EINTR
*/
//SPIDER_LOG(SPIDER_LEVEL_WARN, "thread %lu meet EAGAIN or EWOULDBLOCK, sleep", pthread_self());
usleep(100000);
continue;
}
SPIDER_LOG(SPIDER_LEVEL_WARN, "Read socket fail: %s", strerror(errno));
break; } else if (n == 0) {
/* finish reading */
resp->body_len = len;
if (resp->body_len > 0) {
extract_url(&re, resp->body, narg->url);
}
/* deal resp->body */
for (i = 0; i < (int)modules_post_html.size(); i++) {
modules_post_html[i]->handle(resp);
} break; } else {
//SPIDER_LOG(SPIDER_LEVEL_WARN, "read socket ok! len=%d", n);
len += n;
resp->body[len] = '\0'; if (!trunc_head) {
if ((body_ptr = strstr(resp->body, "\r\n\r\n")) != NULL) {
*(body_ptr+2) = '\0';
resp->header = parse_header(resp->body);
if (!header_postcheck(resp->header)) {
goto leave; /* modulues filter fail */
}
trunc_head = 1; /* cover header */
body_ptr += 4;
for (i = 0; *body_ptr; i++) {
resp->body[i] = *body_ptr;
body_ptr++;
}
resp->body[i] = '\0';
len = i;
}
continue;
}
}
} leave:
close(narg->fd); /* close socket */
free_url(narg->url); /* free Url object */
regfree(&re); /* free regex object */
/* free resp */
free(resp->header->content_type);
free(resp->header);
free(resp->body);
free(resp); end_thread();
return NULL;
}
Linux企业级项目实践之网络爬虫(12)——处理HTTP应答头的更多相关文章
- Linux企业级项目实践之网络爬虫(1)——项目概述及准备工作
我们在学习了Linux系统编程之后,需要一些实战项目来提高自己的水平,本系列我们通过编写一个爬虫程序,将我们学习的知识进行综合应用,同时在实现项目的过程中逐渐养成一些有用的思维方式,并具有初步的软件开 ...
- Linux企业级项目实践之网络爬虫(29)——遵守robots.txt
Robots协议(也称为爬虫协议.机器人协议等)的全称是"网络爬虫排除标准"(Robots Exclusion Protocol),网站通过Robots协议告诉搜索引擎哪些页面可以 ...
- Linux企业级项目实践之网络爬虫(21)——扩展为多任务爬虫
高效的网络爬虫是搜索引擎的重要基础.采用多任务并发执行,实现类似于CPU的流水线(pipeline)运行方式,可极大地提高网络和计算资源的利用率等性能. #include "threads. ...
- Linux企业级项目实践之网络爬虫(2)——网络爬虫的结构与工作流程
网络爬虫是捜索引擎抓取系统的重要组成部分.爬虫的主要目的是将互联网上的网页下载到本地形成一个或联网内容的镜像备份. 一个通用的网络爬虫的框架如图所示:
- Linux企业级项目实践之网络爬虫(23)——系统测试:找出系统中的bug
为了验证爬虫的业务流程.性能和健壮性需要进行测试. 软件测试是描述一种用来促进鉴定软件的正确性.完整性.安全性和质量的过程.软件测试的经典定义是:在规定的条件下对程序进行操作,以发现程序错误,衡量软件 ...
- Linux企业级项目实践之网络爬虫(30)——通过查阅RFC文档扩充更加复杂的功能
HTTP是一种很简单的请求.响应式协议,客户端发送一个请求.服务器返回一个响应.HTTP 1.1 版本规范由 RFC2616 定义.了解了 HTTP请求.响应消息在TCP数据流中的格式,很容易使用纯 ...
- Linux企业级项目实践之网络爬虫(28)——爬虫socket处理
Socket是进程之间交换数据的机制.这些进程即可以是同一台机器上的,也可以是通过网络连接起来的不同机器.一旦一个Socket连接建立,那么数据就能够双向传输,直到其中一端关闭连接. 通常,请求数据的 ...
- Linux企业级项目实践之网络爬虫(19)——epoll接口
由于要实现爬虫程序的快速抓取,显然如果采用阻塞型的I/O方式,那么系统可能很长时间都处在等待内核响应的状态中,这样爬虫程序将大大地降低效率.然而,如果采用非阻塞I/O,那么就要一直调用应用进程,反复对 ...
- Linux企业级项目实践之网络爬虫(6)——将程序设计成为守护进程
在linux或者unix操作系统中在系统的引导的时候会开启很多服务,这些服务就叫做守护进程.为了增加灵活性,root可以选择系统开启的模式,这些模式叫做运行级别,每一种运行级别以一定的方式配置系统. ...
随机推荐
- 运营总监招聘-e袋洗招聘-拉勾网
运营总监招聘-e袋洗招聘-拉勾网 运营总监
- 异步的 SQL 数据库封装
引言 我一直在寻找一种简单有效的库,它能在简化数据库相关的编程的同时提供一种异步的方法来预防死锁. 我找到的大部分库要么太繁琐,要么灵活性不足,所以我决定自己写个. 使用这个库,你可以轻松地连接到任何 ...
- 数据采集工具flume
概述 flume是在2011年被首次引入到Cloudera的CDH3分发中,2011年6月,Cloudera将flume项目捐献给Apache基金会.2012年,flume项目从孵化器变成了顶级项目, ...
- ORACLE REFERENCES FRO TEST
[JSU]LJDragon's Oracle course notes In the first semester, junior year Oracle考前复习 试题结构分析: 1.选择题2x10, ...
- EBuild-API常见问题汇总
问题1:用户访问被防火墙屏蔽检查处理流程 E-Build API(原IBE)是面向航空公司和代理人,以及第三方的航空预订服务产品.用户通过客户端,使用固定IP访问E-Build API服务器,航信网络 ...
- XCode 打包问题巧遇
XCode 打包问题巧遇 太阳火神的漂亮人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非商业用途-保持一致"创作公用协议 转载请保留此句: ...
- HBase学习(十四)LINUX下用Eclipse构建HBase开发环境
Eclipse,HBase版本号眼下没有发现须要特别指定 1:从HBase集群中复制一份Hbase部署文件,放置在开发端某一文件夹下(如在/app/hadoop/hbase096文件夹下). 2:在e ...
- 【转】在写一个iOS应用之前必须做的7件事(附相关资源)
转自:http://www.cocoachina.com/ios/20160316/15687.html 本文由CocoaChina--不再犹豫(tao200610704@126.com)翻译 作者: ...
- 服务 远程服务 AIDL 进程间通讯 IPC
Activity aidl接口文件 package com.bqt.aidlservice; interface IBinderInterface { /* 更改文件后缀为[.aidl]去掉 ...
- php设计模式——单例模式
单例模式概念 单例模式是指整个应用中类只有一个对象实例的设计模式. 单例模式的特点 一个类在整个应用中只有一个实例 类必须自行创建这个实例 必须自行向整个系统提供这个实例 php中使用单例模式的原因 ...