核心原理
Python 不能直接解析 Shadowsocks 协议。标准做法是:
Python
↓ SOCKS5
sslocal (本地 1080 端口)
↓ Shadowsocks 协议
远端 SS 服务器
↓ 明文
目标网站
先用 Shadowsocks 客户端在本地起一个 SOCKS5 代理,Python 通过这个代理访问外网。
方法一:requests[socks](推荐)
安装:
pip install requests[socks]
使用:
import requests
proxies = {
"http": "socks5://127.0.0.1:1080",
"https": "socks5://127.0.0.1:1080"
}
r = requests.get(
"https://httpbin.org/ip",
proxies=proxies,
timeout=10
)
print(r.json())
socks5:// 使用远端 DNS 解析;如果想让本地 DNS 解析,换成 socks5h://。
方法二:PySocks 全局劫持
安装:
pip install pysocks
设置全局默认代理,之后所有 socket 连接都走 SOCKS5:
import socket
import socks
socks.set_default_proxy(socks.SOCKS5, "127.0.0.1", 1080)
socket.socket = socks.socksocket
import requests
r = requests.get("https://httpbin.org/ip")
print(r.json())
适合需要代理所有网络调用(requests、httpx、urllib 等)的场景,但会影响进程内所有 socket,慎用。
方法三:环境变量
export ALL_PROXY=socks5://127.0.0.1:1080
export HTTPS_PROXY=socks5://127.0.0.1:1080
export HTTP_PROXY=socks5://127.0.0.1:1080
或者在 Python 代码里设置:
import os
os.environ["ALL_PROXY"] = "socks5://127.0.0.1:1080"
import requests
r = requests.get("https://httpbin.org/ip")
print(r.json())
requests 会自动读取 HTTP_PROXY / HTTPS_PROXY / ALL_PROXY 环境变量。
在代码里启动 sslocal
如果想让 Python 程序自己管理 Shadowsocks 子进程:
import subprocess
import time
import requests
proc = subprocess.Popen([
"sslocal",
"-s", "服务器IP",
"-p", "8388",
"-k", "密码",
"-m", "aes-256-gcm",
"-l", "1080"
], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
time.sleep(1) # 等待 sslocal 就绪
proxies = {
"http": "socks5://127.0.0.1:1080",
"https": "socks5://127.0.0.1:1080"
}
try:
r = requests.get("https://httpbin.org/ip", proxies=proxies, timeout=10)
print(r.json())
finally:
proc.terminate()
sslocal 来自 shadowsocks-libev 或 shadowsocks-rust 包,需要提前安装。
验证代理是否生效
import requests
proxies = {
"http": "socks5://127.0.0.1:1080",
"https": "socks5://127.0.0.1:1080"
}
r = requests.get("https://httpbin.org/ip", proxies=proxies, timeout=10)
print(r.json()) # 返回的 origin IP 应为代理服务器 IP,不是本机 IP