用于以编程方式管理 Tor 实例的 Python 库。
Linux(Debian/Ubuntu):
sudo apt-get install tor obfs4proxy
Windows:
从 torproject.org 下载 Tor Expert Bundle。
pip install xtor
# 或
uv add xtor
from xtor import Tor
with Tor.start(port=9052, control_port=9053, host="127.0.0.1") as tor:
print(f"Connected through IP: {tor.ip}")
resp = tor.client.get("https://api.ipify.org")
print(resp.text)
from xtor import Tor
from xtor.exceptions import TorNotFoundError, PortInUseError
try:
with Tor.start(port=9052, control_port=9053, host="127.0.0.1", password="mypass") as tor:
print(tor.ip)
resp = tor.client.get("https://api.ipify.org")
print(resp.text)
except TorNotFoundError:
print("Tor not found on PATH")
except PortInUseError as e:
print(f"Port in use: {e}")
注意: 为了向后兼容,
Tor.startTor()可作为Tor.start()的别名使用。
with Tor(password="mypass", port=9050, control_port=9051) as tor:
print(tor.ip)
with Tor.start(port=9052, control_port=9053, host="127.0.0.1") as tor:
print(tor.ip)
tor.new_identity(wait=True, timeout=30)
print(tor.ip) # 新 IP
import asyncio
from xtor import Tor
async def main():
with Tor.start(port=9052, control_port=9053, host="127.0.0.1") as tor:
async with tor.async_client as client:
resp = await client.get("https://api.ipify.org")
print(resp.text)
asyncio.run(main())
with Tor.start(port=9052, control_port=9053, host="127.0.0.1") as tor:
# 每个键使用不同的电路
client_a = tor.isolated_client("session-a")
client_b = tor.isolated_client("session-b")
# 通过 client_a 和 client_b 的请求使用不同的电路
with Tor.start(port=9052, control_port=9053, host="127.0.0.1") as tor:
circuits = tor.get_circuits()
for c in circuits:
print(f"Circuit {c.id}: {c.status}, path: {c.path}")
# 关闭特定电路
tor.close_circuit(circuits[0].id)
with Tor.start(port=9052, control_port=9053, host="127.0.0.1") as tor:
info = tor.exit_node
if info:
print(f"Exit: {info.nickname} ({info.country})")
print(f"Flags: {info.flags}")
with Tor.start(port=9052, control_port=9053, host="127.0.0.1") as tor:
service = tor.create_hidden_service({80: 8080})
print(f"Service: {service.onion_address}")
# 完成后移除
tor.remove_hidden_service(service)
with Tor.start(port=9052, control_port=9053, host="127.0.0.1") as tor:
def on_bandwidth(event):
print(f"Read: {event.read}, Written: {event.written}")
tor.add_event_listener("BW", on_bandwidth)
# ... 进行其他操作 ...
tor.remove_event_listener(on_bandwidth)
from xtor import TorPool
with TorPool(size=3, base_port=9100, password="secret") as pool:
# 轮询
tor = pool.next()
print(tor.client.get("https://api.ipify.org").text)
# 轮换所有身份
pool.rotate_all()
# 随机选择
tor = pool.random()
from xtor import Tor
# 启动命名实例
tor = Tor.start(port=9052, control_port=9053, host="127.0.0.1", name="my-tor")
# 稍后,通过名称重新连接
tor = Tor.from_name("my-tor")
with tor:
print(tor.ip)
xtor CLI 将命名 Tor 实例作为后台进程进行管理。
# 启动一个命名实例
xtor start my-tor --port 9052 --control-port 9053
# 列出实例
xtor list
# 连接详情
xtor connect my-tor
# 停止实例
xtor stop my-tor
# 移除实例和数据
xtor remove my-tor
XtorError (基类)
├── TorNotFoundError
├── PortInUseError
├── IdentityChangeTimeout
├── ConnectionError
└── AuthenticationError
全捕获模式:
from xtor.exceptions import XtorError
try:
with Tor.start(port=9052, control_port=9053, host="127.0.0.1") as tor:
...
except XtorError as e:
print(f"xtor 错误: {e}")