zoukankan      html  css  js  c++  java
  • 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] = '';
    
    
                if (!trunc_head) {
                    if ((body_ptr = strstr(resp->body, "
    
    ")) != NULL) {
                        *(body_ptr+2) = '';
                        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] = '';
                        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;
    }


  • 相关阅读:
    卷积神经网络与典型结构
    机器学习之信息熵
    机器学习读书笔记第三章(1):线性模型
    神经网络之:S型神经元
    mysql只保留一条有效数据,删除其他重复的数据
    mysql索引
    mysql自定义函数收集
    MySql中循环的使用
    WCF的例子
    C盘满了如何清理
  • 原文地址:https://www.cnblogs.com/new0801/p/6176999.html
Copyright © 2011-2022 走看看