欢迎光临
我们一直在努力

Python requests 模块在网络爬虫与网络安全中的应用

1. 引言

Python 的 requests 模块是当下最流行的 HTTP 客户端库之一,它以「让 HTTP 服务人类」为设计理念,把复杂的网络请求封装成了简洁、直观的 API。无论是编写网络爬虫抓取网页数据,还是在授权范围内开展网络安全测试、分析与工具开发,requests 都是绕不开的基础组件。

本文将围绕两条主线展开:

  • 网络爬虫:如何用 requests 高效、稳定地抓取网页数据;
  • 网络安全:如何借助 requests 进行授权范围内的安全测试、接口分析与漏洞验证。

同时,本文会强调合法合规边界:所有安全相关内容仅用于授权测试、安全学习与防御建设,请勿用于未授权访问。

2. requests 模块快速入门

2.1 安装与基本用法

pip install requests

发起一个最简单的 GET 请求只需要两行代码:

import requests

resp = requests.get("https://httpbin.org/get")
print(resp.status_code) # 状态码
print(resp.text) # 响应正文
print(resp.json()) # 若响应为 JSON,可直接解析

2.2 核心对象与常用方法

requests 提供与 HTTP 方法一一对应的函数:get、post、put、delete、patch、head、options。这些函数都会返回一个 Response 对象,常用的属性如下:

属性/方法说明
status_code HTTP 状态码
text 响应正文(字符串)
content 响应正文(字节,适合图片/文件)
json() 将 JSON 响应解析为 Python 对象
headers 响应头
cookies 响应 Cookie
url 最终请求 URL(重定向后)
encoding 响应编码
elapsed 请求耗时

2.3 请求头、参数与请求体

import requests

# 自定义请求头
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)",
"Referer": "https://example.com/",
}

# URL 查询参数
params = {"page": 1, "size": 20}

# POST 表单数据
data = {"username": "demo", "password": "123456"}

# POST JSON 数据
json_data = {"key": "value"}

resp = requests.post(
"https://httpbin.org/post",
headers=headers,
params=params,
data=data,
timeout=10,
)
print(resp.json())

timeout 参数非常重要。生产环境中的爬虫若不加超时,一旦目标无响应,线程可能长时间挂起,导致资源耗尽。

3. requests 在网络爬虫中的应用

3.1 会话保持与 Cookie 管理

很多网站依赖 Cookie 维持登录状态。使用 Session 对象可以自动保存 Cookie,并在后续请求中自动携带:

import requests

s = requests.Session()

# 第一次请求:登录
login_data = {"username": "your_name", "password": "your_pass"}
s.post("https://example.com/login", data=login_data)

# 后续请求会自动携带登录后的 Cookie
profile = s.get("https://example.com/profile")
print(profile.text)

Session 还支持统一的请求头、代理和证书配置,避免重复传参。

3.2 代理与反爬策略

爬虫实践中,代理是应对 IP 限制的常用手段:

import requests

proxies = {
"http": "http://127.0.0.1:7890",
"https": "http://127.0.0.1:7890",
}

resp = requests.get(
"https://httpbin.org/ip",
proxies=proxies,
timeout=10,
)
print(resp.json())

配合随机 User-Agent、请求间隔控制和重试机制,可以显著提升爬虫的稳定性。下面是一个带重试的简单封装:

import time
import requests
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry

def create_session():
s = requests.Session()
retry = Retry(
total=3,
backoff_factor=1,
status_forcelist=[500, 502, 503, 504],
)
adapter = HTTPAdapter(max_retries=retry)
s.mount("http://", adapter)
s.mount("https://", adapter)
return s

s = create_session()
try:
resp = s.get("https://example.com", timeout=10)
resp.raise_for_status()
print(resp.text)
except requests.RequestException as e:
print(f"请求失败: {e}")

3.3 响应编码处理

中文网页容易出现乱码,常见原因是响应头声明的编码与实际编码不一致。可以手动修正编码:

import requests

resp = requests.get("https://example.com")
resp.encoding = resp.apparent_encoding # 根据内容推断编码
print(resp.text)

apparent_encoding 使用 charset-normalizer 的启发式算法,对中文站点通常比服务器返回的编码更准确。

3.4 流式下载大文件

爬取图片、视频等大文件时,应使用流式下载,避免一次性将全部内容加载到内存:

import requests

url = "https://example.com/big_file.zip"
with requests.get(url, stream=True, timeout=30) as resp:
resp.raise_for_status()
with open("big_file.zip", "wb") as f:
for chunk in resp.iter_content(chunk_size=8192):
f.write(chunk)

3.5 常用爬虫场景综合示例

假设我们需要抓取一个分页 API 并保存数据:

import requests
import time

base_url = "https://api.example.com/articles"
headers = {"User-Agent": "Mozilla/5.0 (compatible; DemoCrawler/1.0)"}
all_items = []

for page in range(1, 6):
resp = requests.get(
base_url,
params={"page": page, "size": 50},
headers=headers,
timeout=10,
)
resp.raise_for_status()
data = resp.json()
items = data.get("data", [])
if not items:
break
all_items.extend(items)
time.sleep(1) # 礼貌性间隔,降低目标压力

print(f"共抓取 {len(all_items)} 条数据")

对于结构化的 HTML 页面,可以结合 requests 与 BeautifulSoup 解析 DOM 并提取字段。下面是一个完整示例:抓取文章列表页的标题、链接和发布时间,带异常处理与结果保存。

import csv
import time
import requests
from bs4 import BeautifulSoup

BASE_URL = "https://example.com/news"
HEADERS = {"User-Agent": "Mozilla/5.0 (compatible; DemoCrawler/1.0)"}
OUTPUT_FILE = "articles.csv"

def fetch_html(url, retries=3):
"""下载页面并返回 BeautifulSoup 对象,失败重试。"""
for attempt in range(1, retries + 1):
try:
resp = requests.get(url, headers=HEADERS, timeout=10)
resp.raise_for_status()
resp.encoding = resp.apparent_encoding
return BeautifulSoup(resp.text, "html.parser")
except requests.RequestException as exc:
print(f"[重试 {attempt}/{retries}] 请求失败: {exc}")
time.sleep(2)
return None

def parse_articles(soup):
"""从页面中提取结构化数据。"""
items = []
if soup is None:
return items

# 这里的选择器需要根据目标站点实际结构调整
for card in soup.select(".article-list .article-item"):
title_tag = card.select_one("h2 a")
if title_tag is None:
continue

title = title_tag.get_text(strip=True)
link = title_tag.get("href", "")
date = card.select_one(".date")
date_text = date.get_text(strip=True) if date else ""

items.append(
{
"title": title,
"link": link,
"date": date_text,
}
)
return items

def save_to_csv(items, filename):
"""将结果保存为 CSV 文件。"""
if not items:
print("没有解析到数据,不生成文件。")
return

with open(filename, "w", encoding="utf-8", newline="") as f:
writer = csv.DictWriter(f, fieldnames=["title", "link", "date"])
writer.writeheader()
writer.writerows(items)

print(f"已保存 {len(items)} 条数据到 {filename}")

def main():
all_items = []

for page in range(1, 4):
url = f"{BASE_URL}?page={page}"
soup = fetch_html(url)
items = parse_articles(soup)

if not items:
print(f"第 {page} 页无数据,停止抓取。")
break

all_items.extend(items)
print(f"第 {page} 页解析到 {len(items)} 条数据")
time.sleep(1) # 礼貌性间隔

save_to_csv(all_items, OUTPUT_FILE)

if __name__ == "__main__":
main()

代码说明:

  • fetch_html 封装了请求、编码修正和重试逻辑,网络异常不会直接中断整个脚本;
  • parse_articles 使用 CSS 选择器提取标题、链接和日期,选择器需按目标站点实际 HTML 结构调整;
  • save_to_csv 通过 csv.DictWriter 将字典列表写为 UTF-8 编码的 CSV,避免中文乱码;
  • 主流程按页遍历,遇到空页即停止,并在请求之间加入 time.sleep(1) 控制访问频率。

4. requests 在网络安全中的应用

本节内容仅面向授权范围内的安全测试、漏洞验证与防御研究。未经授权对目标系统发起扫描或攻击属于违法行为。

4.1 信息收集与指纹识别

在授权的渗透测试前期,经常需要判断目标 Web 服务的指纹信息。requests 可以方便地读取响应头中的 Server、X-Powered-By 等字段:

import requests

def fingerprint(url):
try:
resp = requests.get(url, timeout=10, verify=False)
server = resp.headers.get("Server", "unknown")
powered_by = resp.headers.get("X-Powered-By", "unknown")
return {
"status": resp.status_code,
"server": server,
"powered_by": powered_by,
"content_type": resp.headers.get("Content-Type"),
}
except requests.RequestException as e:
return {"error": str(e)}

print(fingerprint("https://target.example.com"))

注意:verify=False 会忽略 SSL 证书校验,仅建议在内部测试环境使用,生产代码应确保证书有效。

4.2 目录与接口探测

授权测试中,常用字典对 Web 目录或 API 接口做存在性探测:

import requests

base = "https://target.example.com"
wordlist = ["/admin", "/login", "/api", "/backup", "/config"]

for path in wordlist:
url = base + path
try:
resp = requests.get(url, timeout=5, allow_redirects=False)
if resp.status_code in (200, 301, 302, 403):
print(f"[{resp.status_code}] {url}")
except requests.RequestException:
pass

allow_redirects=False 可避免被重定向干扰判断,403 也值得记录,因为它说明路径存在但被访问控制拦截。

4.3 API 安全测试:参数校验与越权检查

在授权 API 测试中,需要构造各种异常参数,观察服务端的返回逻辑。例如测试 ID 越权:

import requests

s = requests.Session()
# 使用测试账号登录,获取鉴权信息
login = s.post(
"https://target.example.com/api/login",
json={"username": "tester", "password": "test123"},
)
token = login.json().get("token")
s.headers.update({"Authorization": f"Bearer {token}"})

# 尝试访问不同用户的资源,验证是否有越权返回
for uid in [1001, 1002, 1003]:
resp = s.get(f"https://target.example.com/api/user/{uid}", timeout=10)
print(f"uid={uid} -> {resp.status_code}: {resp.text[:200]}")

4.4 SQL 注入验证(授权环境)

requests 常被用于漏洞验证。以下是授权环境中一个基础的 SQL 注入测试脚本,通过观察响应差异判断注入点:

import requests

url = "https://target.example.com/product"
payloads = [
"1",
"1'",
"1' AND '1'='1",
"1' AND '1'='2",
"1 OR 1=1 — ",
]

for p in payloads:
resp = requests.get(url, params={"id": p}, timeout=10)
print(f"payload={p!r:30} status={resp.status_code} len={len(resp.text)}")

通过对比响应长度与内容差异,可以辅助判断是否存在注入风险。生产级测试应使用专业工具(如 sqlmap)并严格限制在授权范围内。

4.5 弱口令检测

授权测试中,对登录接口做弱口令检测是常见任务:

import requests

login_url = "https://target.example.com/login"
usernames = ["admin", "root", "test"]
passwords = ["123456", "admin", "password", "admin123"]

for u in usernames:
for p in passwords:
resp = requests.post(
login_url,
data={"username": u, "password": p},
timeout=5,
allow_redirects=False,
)
if resp.status_code == 302 or "成功" in resp.text:
print(f"[+] 发现弱口令: {u}/{p}")
break

4.6 安全工具开发:批量漏洞检查器

将前面的片段整合,可以封装成一个可复用的基础请求客户端,统一处理超时、重试、代理和日志:

import requests
import logging

logging.basicConfig(level=logging.INFO)

class SecurityClient:
def __init__(self, timeout=10, retries=2):
self.session = requests.Session()
adapter = HTTPAdapter(max_retries=retries)
self.session.mount("http://", adapter)
self.session.mount("https://", adapter)
self.timeout = timeout

def request(self, method, url, **kwargs):
try:
resp = self.session.request(
method, url, timeout=self.timeout, **kwargs
)
logging.info(f"{method} {url} -> {resp.status_code}")
return resp
except requests.RequestException as e:
logging.error(f"{method} {url} 请求异常: {e}")
return None

client = SecurityClient()
resp = client.request("GET", "https://target.example.com/health")
if resp and resp.status_code == 200:
print(resp.json())

5. 爬虫与安全测试的通用进阶技巧

5.1 自定义请求头与 cookies 绕过简单防护

很多 WAF 或反爬策略会校验请求头。可以完整构造浏览器级请求头:

headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
"Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8",
"Accept-Encoding": "gzip, deflate, br",
"Connection": "keep-alive",
}
resp = requests.get("https://example.com", headers=headers, timeout=10)

5.2 使用 verify 与证书处理

访问内网自签名 HTTPS 服务时可能需要跳过证书校验(仅限内部测试):

resp = requests.get("https://192.168.1.100", verify=False, timeout=10)

更规范的做法是传入 CA 证书路径:

resp = requests.get("https://example.com", verify="/path/to/ca.pem", timeout=10)

5.3 会话、代理与超时的工程化配置

s = requests.Session()
s.headers.update({
"User-Agent": "SecCrawler/1.0",
})
s.proxies.update({
"http": "http://127.0.0.1:7890",
"https": "http://127.0.0.1:7890",
})
s.timeout = 15 # 对 Session 全局默认超时

6. 合法合规与道德边界

无论爬虫还是安全测试,都必须遵守以下原则:

  • 授权优先:安全测试仅针对本人拥有或已获得书面授权的目标;
  • 尊重 robots.txt:爬虫应遵守网站的爬取协议;
  • 控制频率:避免高频请求对目标造成压力,影响正常服务;
  • 数据合规:抓取和存储数据须符合《网络安全法》《数据安全法》《个人信息保护法》等法律法规;
  • 漏洞处理:发现漏洞应通过正规渠道报告,不传播、不利用。

《刑法》第二百八十五条、第二百八十六条对非法侵入、破坏计算机信息系统等行为有明确罚则。技术学习应以防御与合法测试为目的。

7. 总结

requests 模块凭借简洁的 API 和强大的功能,成为 Python 网络编程的基础设施:

  • 在网络爬虫中,它提供会话管理、代理、重试、流式下载等能力,支撑稳定高效的数据采集;
  • 在授权网络安全测试中,它是信息收集、接口探测、漏洞验证与工具开发的核心组件。

掌握 requests 的高级用法,能显著提升爬虫工程的健壮性与安全工具的编写效率。但技术是中立的,使用者的目的决定了它的价值——请始终在合法、合规、授权的框架下开展实践。

8. 延伸阅读

  • requests 官方文档:https://docs.python-requests.org/
  • HTTP 协议详解:MDN Web Docs
  • OWASP Top 10:https://owasp.org/www-project-top-ten/
  • 《Python 网络数据采集》
赞(0)
未经允许不得转载:171主机测评 » Python requests 模块在网络爬虫与网络安全中的应用
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址