3. HTTP协议与网络请求:从协议到实战
做数据采集,说白了就是跟HTTP协议打交道。你写的爬虫、调用的API,底层都在走这套规则。我刚开始学爬虫时,总觉得协议是理论课的东西,直到有一次被一个301重定向坑了整整一天……嗯,从那以后我老实了。
今天咱们就把HTTP协议拆开揉碎,看看它到底怎么工作。
3.1 HTTP协议基础:互联网的通用语言
HTTP(HyperText Transfer Protocol)是客户端和服务器之间的通信协议。它定义了请求该怎么发、响应该怎么回。
我个人习惯把HTTP理解成「点餐流程」:
- 客户端(你)→ 点菜 → 请求
- 服务器(厨房)→ 出菜 → 响应
- 状态码 → 比如「菜已售罄」就是404
HTTP有几个核心特点:
- 无状态:服务器不记得你上次来过。每次请求都是独立的。
- 明文传输:早期HTTP直接传文本,后来才有了HTTPS加密。
- 基于TCP/IP:底层靠TCP保证数据不丢包。
3.2 请求与响应结构:拆开看看里面有什么
一个HTTP请求长什么样?我直接给你看个例子:
POST /api/login HTTP/1.1
Host: example.com
Content-Type: application/json
User-Agent: Mozilla/5.0
Cookie: session_id=abc123
{"username":"admin","password":"123456"}
结构其实很简单:
- 请求行:方法 + 路径 + 协议版本
- 请求头:一堆键值对,告诉服务器你的身份、浏览器、想收什么格式
- 空行:分隔头和体
- 请求体:POST/PUT时带的数据,GET没有
响应也是类似的套路:
HTTP/1.1 200 OK
Content-Type: application/json
Set-Cookie: =xyz789; Path=/
{"status":"success","data":{"id":1,"name":"张三"}}
- 状态行:协议版本 + 状态码 + 状态描述
- 响应头:服务器返回的元信息
- 响应体:真正要的数据
关键点:做数据采集时,响应头里的 Content-Type 决定了你怎么解析数据。如果是 application/json 就用JSON解析,text/html 就得用HTML解析器。我见过有人拿JSON解析器去解析HTML,结果全乱码了。
3.3 状态码详解:服务器在说什么
状态码是服务器给你的「暗号」。记住这几类就够了:
| 分类 | 范围 | 含义 | 常见例子 |
|---|---|---|---|
| 1xx | 100-199 | 信息性,服务器还在处理 | 100 Continue |
| 2xx | 200-299 | 成功,请求已处理 | 200 OK, 201 Created |
| 3xx | 300-399 | 重定向,需要去别处找 | 301 Moved, 302 Found |
| 4xx | 400-499 | 客户端错误,你发错了 | 404 Not Found, 403 Forbidden |
| 5xx | 500-599 | 服务器错误,对方崩了 | 500 Internal Server Error |
做采集时,这几个状态码你一定会遇到:
- 200:一切正常,拿数据就行
- 301/302:页面搬家了。你的爬虫得跟着跳转,否则拿不到数据
- 403:被拒绝了。多半是没带Cookie或User-Agent被识别
- 404:资源不存在。检查URL拼写
- 429:请求太频繁,被限流了。加延时或换IP
- 500/502/503:服务器挂了。等会儿再试
Referer 头。有些网站会检查你是从哪跳转过来的,不带Referer直接拒绝。后来我加上了,问题就解决了。
3.4 常用请求方法:GET、POST、PUT、DELETE
HTTP定义了多种请求方法,但做数据采集最常用的就这四个:
| 方法 | 作用 | 有无请求体 | 幂等性 | 典型场景 |
|---|---|---|---|---|
| GET | 获取资源 | 无 | 是 | 浏览网页、查询数据 |
| POST | 创建资源 | 有 | 否 | 提交表单、登录 |
| PUT | 更新资源 | 有 | 是 | 修改用户信息 |
| DELETE | 删除资源 | 通常无 | 是 | 删除文章 |
GET 是最常用的。参数拼在URL里,比如 ?page=1&size=20。我建议你注意两点:
- URL长度有限制(不同浏览器不一样,一般2048字符以内)
- 敏感信息别放URL里,会暴露
POST 是采集的利器。参数放请求体里,可以传大量数据。常见的格式有:
application/x-www-form-urlencoded:表单格式,key=value&key2=value2application/json:JSON格式,现在最常用multipart/form-data:传文件时用
PUT 和 DELETE 在RESTful API里很常见。做采集时,如果遇到需要修改或删除数据的场景,就会用到它们。
实战建议:我个人习惯用Python的 requests 库。发GET请求就一行 requests.get(url),POST就 requests.post(url, json=data)。但要注意,有些网站会检查 User-Agent,我一般会设置成浏览器的样子:
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
'Referer': 'https://example.com'
}
response = requests.get(url, headers=headers)
3.5 知识结构总览
下面这张图把HTTP协议的核心知识点串起来了。你想想看,从请求到响应,每一步都有对应的规则:
3.6 实战中的坑与技巧
最后分享几个我踩过的坑,希望能帮你少走弯路:
- 重定向陷阱:有些网站用302跳转到登录页。你的爬虫如果不自动跟进,就会一直拿到登录页的HTML。我建议用
requests时设置allow_redirects=True。 - 编码问题:响应头里的
charset可能和实际内容不一致。我习惯用response.apparent_encoding自动检测编码。 - 超时设置:别让爬虫无限等待。我一般设
timeout=10,超过10秒就重试。 - 限流应对:遇到429状态码,先停一下。我常用的策略是「指数退避」——第一次等1秒,第二次等2秒,第三次等4秒,以此类推。
小技巧:调试HTTP请求时,我推荐用 curl 命令先试一下。比如:
curl -v -X POST https://api.example.com/login \
-H "Content-Type: application/json" \
-d '{"username":"admin","password":"123"}'
这样能看到完整的请求和响应,比在代码里调试直观多了。
HTTP协议看起来简单,但细节很多。你只要把请求结构、状态码、常用方法这三块吃透,数据采集的基础就算打牢了。剩下的就是多写多练,遇到问题别慌,抓包看看,多半能找到原因。