Skip to content

HTTP 协议与爬虫基础

一、爬虫的基本概念

网络爬虫(又称网页蜘蛛、网络机器人)是模拟浏览器发送网络请求、接收响应,并按照一定规则自动抓取互联网信息的程序。原则上,浏览器(客户端)能做的事,爬虫都能做。

1. 数据的来源与用途

获取数据的常见途径:

  • 向第三方数据公司购买(如企查查)
  • 从免费数据网站下载(如国家统计局)
  • 通过爬虫采集(最高效的途径)
  • 人工收集(问卷、录入)

爬取到的数据通常用于:

  • 网页 / App 的聚合展示(如今日热榜这类聚合站点)
  • 数据分析与机器学习训练

2. 爬虫的分类

  • 通用爬虫:如搜索引擎的爬虫,抓取全网页面建立索引
  • 聚焦爬虫:针对特定网站、特定数据进行的定向采集

3. 爬虫的工作流程

text
获取资源地址(URL) → 发送请求获取响应 → 提取数据 → 保存数据
        ↑___________________________________|
                     (解析出新的 URL 继续爬取)
  1. 获取资源地址:拿到准确的数据接口或页面 URL;
  2. 发送请求:获取网页源代码或接口 JSON;
  3. 提取信息:用正则、XPath、BeautifulSoup 等解析出目标字段;
  4. 保存数据:存为 TXT / JSON / CSV,或写入 MySQL、MongoDB 等数据库。

二、HTTP 基础

1. URL 的组成

text
https://www.baidu.com/s?wd=python#flg
协议     域名        资源路径 查询参数   锚点
  • 协议http(默认端口 80)或 https(HTTP + SSL/TLS,默认端口 443)
  • 域名:也可以直接写 IP;域名:端口 用冒号分隔
  • 查询参数? 之后、# 之前的 key=value 部分
  • 锚点# 之后,用于页面内定位,不会发送给服务器

2. HTTP 协议的发展

版本年代核心变化
HTTP/0.91991只有 GET 方法,无请求头、无状态码
HTTP/1.01996引入 POST/HEAD、状态码、请求头与更多内容类型
HTTP/1.11997第一个标准版:持久连接、分块传输、缓存控制、虚拟主机
HTTP/22015二进制分帧、多路复用、头部压缩、服务器推送
HTTP/32021基于 QUIC(UDP),解决队头阻塞,内置 TLS 1.3

3. 浏览器渲染与爬虫的关系

浏览器拿到第一个 HTML 响应后,会继续加载其中的 CSS、JS、图片和 Ajax 接口,逐步渲染出最终页面——这个过程叫渲染。以一个典型的评论列表为例:

  1. 浏览器请求 https://example.com/article/1,服务器返回 HTML 骨架(此时评论区域是空的);
  2. HTML 里的 <script> 被执行,页面中的 JS 向 https://api.example.com/comments?page=1 发起 Ajax 请求;
  3. 接口返回 JSON(评论数据),JS 把它拼成一个个 <div> 插进页面;
  4. 你在页面上「看到」了评论——但它们来自第 2 步的接口,而不是第 1 步的 HTML。

而爬虫只请求 URL 并获取对应的响应:如果只请求第 1 步的 HTML,拿到的源码里根本没有评论。浏览器里看到的页面和爬虫拿到的源码经常不一样,所以做爬虫必须先在 Network 面板里找到真正装着数据的那个请求(往往是接口返回的 JSON),以它为准来提取数据。

三、HTTP 请求与响应

1. 请求的四个部分

  1. 请求方法GET(获取页面)、POST(提交表单/上传数据)、PUTDELETEHEADOPTIONS
  2. 请求 URL:唯一确定请求的资源
  3. 请求头:常用的有:
请求头作用
User-Agent浏览器标识,爬虫最基本的伪装
Referer来源页面,常用于防盗链
Cookie维持登录态、通过部分反爬校验
Accept / Accept-Encoding可接受的内容类型与编码
X-Requested-With: XMLHttpRequest标识 Ajax 异步请求
  1. 请求体:POST 请求携带的表单或 JSON 数据,GET 请求一般为空

2. 响应的三个部分

  1. 状态码:判断请求是否成功的第一依据
状态码含义爬虫中的典型场景
200成功正常返回数据
301 / 302永久 / 临时重定向requests 默认自动跟随
304未修改命中缓存
403禁止访问常见于 UA / Referer / Cookie 校验失败
404未找到URL 拼接错误
412前置条件失败瑞数等 Cookie 反爬的典型特征
429请求过多触发频率限制
500 / 502 / 504服务器错误服务端异常或被反爬拦截
  1. 响应头Content-Type(数据类型)、Set-Cookie(设置 Cookie)、Server
  2. 响应体:最重要的部分——请求什么,响应体里装的就是什么:请求网页装的是 HTML 源码,请求接口装的是 JSON 字符串,请求图片装的是二进制数据。爬虫后续的所有解析工作(提取、存储)都围绕响应体展开。

HTTP 是无状态协议——每个请求都是独立的,服务器天生无法记住"上一次请求是谁发的"。打个比方:奶茶店每次接单都把你当陌生顾客,你出示一次会员卡(Cookie),店员才认得你,而且每次下单都得再出示一次。Cookie 就是解决这个问题的机制:

  • Cookie:网站为辨别用户身份而存储在浏览器本地的数据,每次请求自动携带
  • 常见属性:Name/ValueExpires(过期时间)、PathDomainHttpOnly(禁止 JS 读取)、Secure(仅 HTTPS 传输)
  • Session:会话数据保存在服务端,浏览器只保存对应的 Session ID

爬虫中带上 Cookie 的利弊:

  • ✅ 能访问登录后的页面、通过部分反爬校验
  • ❌ 一套 Cookie 对应一个用户身份,请求过频繁更容易被识别——解决办法是多账号轮换

五、浏览器开发者工具

先解释一下抓包这个词:浏览器与服务器之间的每一笔请求和响应,都会完整地经过你的电脑。抓包工具(DevTools 的 Network 面板、后面章节的 Charles 等)就像在通信线路上装了一个「监听器」,把这些来来往往的数据包原样记录下来供你查看。做爬虫的第一步永远是抓包——先搞清楚「数据到底在哪个请求里、请求带了哪些参数」,再动手写代码。

以 Chrome 为例(F12 或右键「检查」打开),爬虫最常用的面板:

  • 元素(Elements):查看渲染后的 DOM 树,适合分析页面结构
  • 网络(Network):抓包核心面板,按时间列出所有请求;点击某条请求可查看:
    • 标头(Headers):URL、方法、状态码、请求头与响应头
    • 载荷(Payload):查询参数与 POST 请求体
    • 预览 / 响应(Preview / Response):响应体内容,判断数据是 HTML 还是 JSON
    • 启动器(Initiator):请求由哪段代码发起,逆向时用来追调用栈
  • 控制台(Console):执行 JS 片段、Hook 代码
  • 源代码(Sources):断点调试 JS(Web 逆向的主要战场)
  • 应用(Application):查看 / 删除 Cookie、LocalStorage

抓包小技巧

网络面板的过滤器支持按域名、类型(Fetch/XHR)过滤;勾选 Preserve log 可以在页面跳转后保留请求记录;Disable cache 避免缓存干扰分析。

六、用 Socket 发送 HTTP 请求

requests 之前,可以先用最原始的 Socket 感受一下 HTTP 协议本身就是一段文本:

python
import socket
import re

url = 'http://image11.m1905.cn/uploadfile/2021/0922/thumb_0_647_500_20210922030733993182.jpg'

# 1. 创建 TCP 套接字并连接服务器(80 端口)
client = socket.socket()
client.connect(('image11.m1905.cn', 80))

# 2. 手工构造 HTTP 请求报文(\r\n 分隔,空行结束)
http_req = (
    'GET ' + url + ' HTTP/1.0\r\n'
    'Host: image11.m1905.cn\r\n'
    'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) '
    'AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36\r\n\r\n'
)
client.send(http_req.encode())

# 3. 循环接收响应
result = b''
data = client.recv(1024)
while data:
    result += data
    data = client.recv(1024)

# 4. 用 \r\n\r\n 分隔响应头与响应体,把图片存下来
image = re.findall(b'\r\n\r\n(.*)', result, re.S)[0]
with open('image.jpg', 'wb') as f:
    f.write(image)

注意:HTTP/1.1 默认开启长连接(Connection: keep-alive),recv 会一直等待;若不希望保持连接,可在请求头加 Connection: close,或像上面一样使用 HTTP/1.0。

七、小结

  • 爬虫 = 模拟浏览器发请求 + 解析响应 + 存储数据,一切以 URL 对应的响应为准
  • 请求方法、请求头(UA / Referer / Cookie)、状态码是日常抓包分析的三要素
  • 浏览器渲染后的页面 ≠ 源码,动态数据要去 Network 面板找接口
  • 下一章开始用 requests 把上面的流程代码化
最近更新