TCP与HTTP协议以及爬虫

一、TCP协议相关内容

(一)TCP头部标志

TCP头部包含多种标志位,各标志位功能明确,具体如下:

  • SYN:作为请求连接的标志物,用于发起TCP连接请求。
  • ACK:响应报文标志位,表明此报文为对之前收到的报文的响应。
  • PSH:携带数据标志位,通知接收方应从缓冲区读取数据。
  • FIN:请求断开连接标志位,用于主动请求终止TCP连接。
  • RST:复位标志位(重置),当出现错误或连接异常时,用于重置连接。
  • URG:紧急指针标志位,指示报文中存在需要优先处理的紧急数据。

同时,TCP首部结构包含20字节固定首部与长度可变的选项部分,固定首部涵盖源端口、目的端口、序号、确认号、窗口、偏移、检验和、紧急指针等字段,还包含上述标志位;选项部分长度可变,填充字段用于使首部长度符合要求。TCP报文段由TCP首部和TCP数据部分组成,在网络传输中,TCP报文段作为IP数据部分,加上IP首部后形成IP数据报进行传输。

(二)TCP核心机制

TCP协议通过一系列机制保障数据传输的安全可靠,并提升传输效率。

1. 确保数据安全可靠的机制
  • 三次握手与四次挥手:三次握手用于建立可靠的TCP连接,第一次握手由客户端发送SYN报文请求连接,第二次握手服务器端回复SYN+ACK报文响应,第三次握手客户端发送ACK报文确认,连接建立;四次挥手用于断开TCP连接,客户端先发送FIN报文请求断开,服务器端回复ACK报文确认,待服务器端数据发送完毕后发送FIN报文,客户端再回复ACK报文,连接断开。
  • 应答机制:TCP对每一包数据都会给出响应应答。发送数据时,序列号表示该包数据的起始编号;响应报文中的确认号是接收方收到的最后一个字节编号加1,以此确保数据有序接收。
  • 超时重传机制:当数据发送出去后,若在指定时间内未收到接收方的响应,TCP会认为数据丢失,进而对该数据进行重传,保证数据不丢失。
  • 滑动窗口机制:设置一段缓冲区,用于缓存TCP已发送但未收到响应、以及准备发送的数据,通过窗口的滑动来动态调整数据的发送节奏,提高数据传输的连续性和可靠性。
2. 提高传输效率的机制
  • 延迟应答:发送数据的同时等待应答,避免频繁发送单独的应答报文,减少网络开销。
  • 流量控制机制:结合TCP头部的窗口大小字段,接收方根据自身缓冲区的空闲情况,动态调整窗口大小并告知发送方,发送方据此调整发送速率,防止接收方因缓冲区溢出而丢失数据。
  • 捎带应答机制:ACK报文(应答报文)可能与应用层的数据同时发送,将应答信息附着在数据报文中,减少单独发送应答报文的次数,提升网络资源利用率。

二、HTTP协议相关内容

HTTP(超文本传输协议)是万维网(WWW)体系中客户端与服务器之间通信的核心应用层协议,其相关内容围绕万维网数据标记、通信方式、数据展示及自身协议特性展开。

(一)万维网核心要素

  • 数据标记:万维网服务器后台通过URL(统一资源定位符)标记万维网数据,URL格式为<协议>://<主机>:<端口><路径>,可精准定位网络中的资源。
  • 通信方式:万维网客户端与服务器之间使用HTTP协议进行通信,HTTP基于传输层的TCP协议,默认端口为80,备用端口为8080。
  • 数据展示:万维网客户端通过HTML(超文本标记语言)展示请求到的数据,HTML能对文本、图片、链接等多种元素进行排版和描述,呈现丰富的网页内容。

(二)HTTP通信过程

HTTP通信需经历以下4个步骤,依赖TCP连接保障数据传输:

  1. 建立TCP连接:客户端向服务器发起TCP连接请求,通过三次握手建立可靠连接。
  2. 发送HTTP请求报文:TCP连接建立后,客户端向服务器发送HTTP请求报文,请求所需资源。
  3. 接收HTTP响应报文:服务器接收并处理请求后,向客户端发送HTTP响应报文,包含请求结果及相关数据。
  4. 断开TCP连接:客户端接收响应报文后,通过四次挥手断开与服务器的TCP连接。

(三)HTTP报文格式

HTTP报文分为请求报文和响应报文两类,均为面向文本的协议,报文字段由ASCII码串组成,字段长度不确定。

1. 请求报文
  • 请求行:包含方法、URL、版本,方法指定对资源的操作,常见方法及意义如下表所示:
    方法(操作)意义
    OPTION请求一些选项的信息
    GET请求读取由URL所标志的信息
    HEAD请求读取由URL所标志的信息的首部
    POST给服务器添加信息(例如,注释)
    PUT在指明的URL下存储一个文档
    DELETE删除指明的URL所标志的资源
    TRACE用来进行环回测试的请求报文
    CONNECT用于代理服务器
  • 首部行:由多个“首部字段名:值”组成,每个字段后接CRLF(回车换行),用于传递请求的附加信息,如客户端信息、请求内容类型等。
  • 实体主体:通常不用,仅在部分请求(如POST)中用于携带向服务器提交的数据。
2. 响应报文
  • 状态行:包含版本、状态码、短语,状态码为三位数字,分为5大类共33种,不同类别代表不同响应状态:
    • 1xx:通知信息,如请求收到或正在处理。
    • 2xx:表示成功,如接受或知道请求。
    • 3xx:表示重定向,需进一步行动完成请求。
    • 4xx:表示客户差错,如请求语法错误或无法完成。
    • 5xx:表示服务器差错,如服务器失效无法完成请求。
      常见状态行示例:
    • HTTP/1.1 202 Accepted(接受)
    • HTTP/1.1 400 Bad Request(错误的请求)
    • HTTP/1.1 404 Not Found(找不到)
  • 首部行:与请求报文的首部行格式类似,由“首部字段名:值”组成,传递响应的附加信息,如服务器信息、响应内容长度等。
  • 实体主体:部分响应报文包含,用于携带服务器返回给客户端的数据,如网页的HTML内容、图片数据等。

代码训练

1、爬虫 

#include "head.h"

int create_tcp_connect()
{
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if(sockfd < 0)
    {
        perror("socket error");
        close(sockfd); 
        return -1;
    }

    struct sockaddr_in seraddr;
    seraddr.sin_family = AF_INET;
    seraddr.sin_port = htons(80);
    seraddr.sin_addr.s_addr = inet_addr("117.34.49.212");

    int ret = connect(sockfd, (struct sockaddr *)&seraddr, sizeof(seraddr));
    if(ret < 0)
    {
        perror("connect error");
        return -1;
    }
    return sockfd;
}

int send_http_request(int sockfd)
{
    const char *prqus = "GET / HTTP/1.1\r\n"
                  "Host: news.sohu.com\r\n"
                  "User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/113.0\r\n"
                  "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8\r\n"
                  "Accept-Language: en-US,en;q=0.5\r\n"
                  "Connection: close\r\n"     // keep_alive   close
                  "\r\n";

    ssize_t cnt = send(sockfd, prqus, strlen(prqus), 0);
    if(cnt < 0)
    {
        perror("send error");
        return -1;
    } 
    return 0;
}

int recv_http_response(int sockfd)
{
    char buff[1024] = {0};
    while(1)
    {
        ssize_t cnt = recv(sockfd, buff, sizeof(buff), 0);
        if(cnt < 0)
        {
            perror("recv error");
            return -1;
        }
        else if(cnt == 0)
        {
            printf("off\n");
            break;
        }

        write(1, buff, cnt);  
    }
    return 0;
}

int main(int argc, char const *argv[])
{
    int sockfd = create_tcp_connect();
    if(sockfd < 0)
    {
        return -1;
    }

    send_http_request(sockfd);

    recv_http_response(sockfd);

    close(sockfd);

    return 0;
}

首先需要了解得物网站的数据结构和爬取方式,得物网站比较复杂,需要使用Selenium+BeautifulSoup进行爬取。 以下是一个简单的得物爬虫Python代码实现(注:仅供学习参考,请勿用于商业用途): ```python import time from selenium import webdriver from selenium.webdriver.chrome.options import Options from bs4 import BeautifulSoup options = Options() options.add_argument('--no-sandbox') # 解决DevToolsActivePort文件不存在报错的问题 options.add_argument('window-size=1920x3000') # 指定浏览器分辨率 options.add_argument('--disable-gpu') # 谷歌文档提到需要加上这个属性来规避bug options.add_argument('--hide-scrollbars') # 隐藏滚动条, 应对一些特殊页面 options.add_argument('blink-settings=imagesEnabled=false') # 不加载图片, 提升速度 options.add_argument('--headless') # 无界面 driver = webdriver.Chrome(options=options) url = 'https://www.dewu.com/' driver.get(url) # 等待页面加载完成 time.sleep(3) # 模拟鼠标点击,展开商品列表 driver.find_element_by_xpath('//div[text()="全部商品"]').click() # 等待页面加载完成 time.sleep(3) # 获取页面源代码 html = driver.page_source # 解析页面 soup = BeautifulSoup(html, 'html.parser') # 获取商品列表 items = soup.find_all('div', {'class': 'item-card'}) for item in items: # 获取商品标题 title = item.find('div', {'class': 'title'}).text.strip() # 获取商品价格 price = item.find('div', {'class': 'price'}).text.strip() # 获取商品链接 link = item.find('a', {'class': 'item-link'})['href'] print(title, price, link) # 关闭浏览器 driver.quit() ``` 这里的代码仅仅是一个简单的爬虫示例,如果想要更加深入地了解得物网站的数据结构和爬取方式,需要结合具体的需求进行更加详细的分析和实现。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值