python网络爬虫实战-requests 反爬虫技术

添加请求头(headers)

某些网站会发现这不是一个由正常游览器发送的请求,于是可能返回异常结果,导致网页爬取失败,于是请求头就解决这个问题。

headers = {
    'User-Agent': 'Mozilla/5.0',
}
response = requests.get('https://example.com', headers=headers)

什么是 HTTP Headers

在我们访问一个网站时,本质上是在进行一次 HTTP 请求(HTTP Request)

一次完整的 HTTP 请求,主要由三部分组成:

  1. 请求行(Request Line)
  2. 请求头(Headers)
  3. 请求体(Body,可选)

例如:

GET /index.html HTTP/1.1
Host: example.com
User-Agent: Mozilla/5.0
Accept: text/html

其中:

  • GET /index.html HTTP/1.1 是请求行
  • HostUser-AgentAccept 等,就是 Headers

Headers 的本质,是一组 键值对(Key-Value),用于描述:

  • 请求来自哪里
  • 使用什么客户端
  • 希望服务器返回什么格式的数据
  • 是否携带 Cookie、Token 等身份信息

服务器会根据 Headers 来判断:

“你是一个真实的浏览器用户,还是一个程序?”


为什么爬虫一定要设置 Headers

不设置 Headers 的后果

在 Python 中,如果你直接这样写:

import requests

url = "https://example.com"
response = requests.get(url)
print(response.status_code)

你发出的请求,其 Headers 非常简单,类似于:

User-Agent: python-requests/2.xx

对服务器来说:

  • 这不是 Chrome
  • 不是 Firefox
  • 不是 Edge
  • 而是一个自动化脚本

结果往往是:

  • 403 Forbidden
  • 429 Too Many Requests
  • 返回空页面
  • 触发验证码

Headers 的核心作用

在爬虫中,Headers 的主要作用包括:

  1. 伪装成浏览器(Browser Spoofing)
  2. 绕过基础反爬虫规则
  3. 获取正确格式的数据
  4. 维持登录状态(配合 Cookie)

一句话总结:

Headers 决定了服务器“怎么看你”。

添加 URL 参数

如果要附加额外信息,利用params参数就能直接传递这种信息

params = {'q': 'python', 'lang': 'en'}
response = requests.get('https://httpbin.org/get', params=params)

处理超时和异常

try:
    response = requests.get('https://example.com', timeout=5)
except requests.Timeout:
    print('请求超时')
except requests.RequestException as e:
    print(f'请求失败: {e}')

使用会话(Session)保持登录状态

session = requests.Session()
session.get('https://httpbin.org/cookies/set/sessioncookie/123456789')
r = session.get('https://httpbin.org/cookies')
print(r.text)

代理设置

proxies = {
    'http': 'http://127.0.0.1:8080',
    'https': 'https://127.0.0.1:8080',
}
response = requests.get('https://httpbin.org/get', proxies=proxies)

自带身份验证

import requests 
from requests.auth import HTTPBasicAuth

r = requests.get('https://ssr3.scrape.center/',verify=False,auth=HTTPBasicAuth('admin','admin'))

print(r.status_code)