1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
|
import stem
from stem.control import Controller
from stem.process import launch_tor_with_config
import requests
import time
import socket
class TorRequest(object):
def __init__(self, password=None):
self.proxy_port, self.ctrl_port = self.choose_tor_ports()
self._tor_proc = None
if not self._tor_process_exists():
self._tor_proc = self._launch_tor()
self.ctrl = Controller.from_port(port=self.ctrl_port)
self.ctrl.authenticate(password=password)
self.session = requests.Session()
self.session.proxies.update({
'http': 'socks5://localhost:%d' % self.proxy_port,
'https:': 'socks5://localhost:%d' % self.proxy_port,
})
# Default port is in use, use auxiliary ports
def choose_tor_ports(self):
if self.is_port_in_use(9050):
proxy_port = 9052
ctrl_port = 9053
else:
# Default port is not in use, use TorRequest default ports
proxy_port = 9050
ctrl_port = 9051
return proxy_port, ctrl_port
def is_port_in_use(self, port):
try:
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.settimeout(1)
s.connect(('127.0.0.1', port))
return True
except (socket.timeout, ConnectionRefusedError):
return False
self.session.proxies.update({
'https': 'socks5h://localhost:%d' % self.proxy_port,
})
def _tor_process_exists(self):
try:
ctrl = Controller.from_port(port=self.ctrl_port)
ctrl.close()
return True
except:
return False
def _launch_tor(self):
return launch_tor_with_config(
config={
'SocksPort': str(self.proxy_port),
'ControlPort': str(self.ctrl_port)
},
take_ownership=True)
def close(self):
try:
self.session.close()
except: pass
try:
self.ctrl.close()
except: pass
if self._tor_proc:
self._tor_proc.terminate()
def reset_identity_async(self):
self.ctrl.signal(stem.Signal.NEWNYM)
#Fix identity change (session renewal) and HTTPs proxies not using tor
def _reset_session(self):
self.session = requests.Session()
self.session.proxies.update({
'http': 'socks5://localhost:%d' % self.proxy_port,
'https': 'socks5://localhost:%d' % self.proxy_port,
})
def reset_identity(self):
self._reset_session()
self.reset_identity_async()
time.sleep(self.ctrl.get_newnym_wait())
def get(self, *args, **kwargs):
return self.session.get(*args, **kwargs)
def post(self, *args, **kwargs):
return self.session.post(*args, **kwargs)
def put(self, *args, **kwargs):
return self.session.put(*args, **kwargs)
def patch(self, *args, **kwargs):
return self.session.patch(*args, **kwargs)
def delete(self, *args, **kwargs):
return self.session.delete(*args, **kwargs)
def __enter__(self):
return self
def __exit__(self, *args):
self.close()
|