Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 15 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,23 @@
Pytor
=====
PyTor
python wrapper for anonymizing (web scraping?) requests using Tor.

Intially forked from https://github.com/bdheath/pytor (not properly written)

But I am **rewriting** the entire thing with some extensions (see #TODOs)

### Need to update this readme



Pytor is a Python wrapper for scraping over the Tor network. This is useful if you've been blocked (either locally or remotely) from the server you're attempting to scrape, or if it's otherwise important to not reveal your identity.

Pytor allows you to channel simple http requests through a Tor proxy. It also allows you to route more complex Mechanize requests through the proxy if your script needs to emulate a browser. Pytor also allows you to periodically establish a new Tor identity, either directly or by setting a custom interval for the use of a particular identity.

Requirements
============
* A functioning (and running) instance of Tor. This could be the basic Tor Browser Bundle. For more configuration options, consider using the Tor Expert Bundle, available from https://www.torproject.org/download/download.html.en.
* Mechanize (install through pip)
* A functioning (and running) instance of Tor. This could be the basic Tor Browser Bundle. For more configuration options, consider using the Tor Expert Bundle, available from https://www.torproject.org/download/download.html.en.
* Stem (install through pip or apt-get)

Basic usage
Expand All @@ -23,7 +32,7 @@ html = tor.get('http://bradheath.org')
Or, if your Tor configuration requires a different host or port:
```python
from pytor import pytor
tor = pytor(host='localhost', port=9055)
tor = pytor(host='localhost', socks_port=9055)
html = tor.get('http://bradheath.org')
```

Expand All @@ -44,14 +53,16 @@ tor = pytor( port = 9050, controller = True, controlPort = 9051, password='Your-

Request a new identity from Tor: (Note that the network won't always assign you one, and even when it does, you may end up with the same exit node and therefore the same IP address. Also note that you shouldn't change your identity too ofen to avoid stressing the network.)
```python
tor.newIdentity()
tor.getNewIdentity()
```

Have Pytor periodically assign a new identity. (Note that this currently works with get() and download_file() requests, but does not currently force a new identity when using a mechanize browser. More on that later.)
```python
tor.identityTime(1200) # Request a new identity every 1,200 seconds (20 minutes)
```

deprecated:

To create a new instance of a mechanize browser:
```python
br = tor.mechanizeBrowser()
Expand Down
Empty file added __init__.py
Empty file.
Binary file added __pycache__/pytor.cpython-35.pyc
Binary file not shown.
11 changes: 0 additions & 11 deletions pytor-test.py

This file was deleted.

155 changes: 50 additions & 105 deletions pytor.py
Original file line number Diff line number Diff line change
@@ -1,118 +1,63 @@
# PYTOR
# Lightweight wrapper for web scraping on the Tor network
# Brad Heath, brad.heath@gmail.com, @bradheath
#
# REQUIREMENTS
# - Functioning (and active) TOR proxy
# - SocksiPy (socks.py installed to lib/site-packages)
# - Stem (pip install stem)
# - Mechanize
#
#
"""
PyTor
python wrapper for anonymizing (web scraping?) requests using Tor.

Intially forked from https://github.com/bdheath/pytor
But I am rewriting the entire thing for my purpose

"""

import stem
from stem.control import Controller
from stem import Signal
import mechanize
import datetime
import requests

class pytor:
from datetime import datetime


#TODO - some sites block tor exit nodes - add user agent randomizer etc to fix this
#TODO - renew id interval (multi threading)
#TODO - get post : pass along the kwargs

class PyTor:
def __init__(self, host='localhost', socks_port=9050, need_control=False, control_port=9051, password=''):

controlPort = 9051
port = 9050
host = 'localhost'
password = ''
_version = 0.1
_last_result = None
_last_request = None
_id_time = None
_last_id_time = None
_ip = None
_connected = False
browser = None
controller = False

_proxies = {}

def __init__(self, host='localhost', port=9050, controller=False, controlPort = 9051, password=''):
self.controlPort = controlPort
self.port = port
self.controller = controller
self._proxies['http'] = 'socks5://localhost:' + str(self.port)
self._proxies['https'] = 'socks5://localhost:' + str(self.port)
if self.controller:
self.torControl = Controller.from_port(port=controlPort)
self.torControl.authenticate(self.password)
self._connected = True
self._last_id_time = datetime.datetime.now()
return

def request(self, url, timeout = 30):
self._checkIdentityTime()
r = requests.get(url, timeout=timeout, proxies=self._proxies)
self._last_request = url
self._last_result = r.text
return r

def get(self, url, t=30):
self._checkIdentityTime()
self.host = host
self.socks_port = socks_port
self.need_control = need_control
self.control_port = control_port
self.password=password
self.proxies = {}
self.proxies['http'] = 'socks5://' + str(self.host) + ':' + str(self.socks_port)
self.proxies['https'] = 'socks5://' + str(self.host) + ':' + str(self.socks_port)

r = self.request(url, timeout = t)

if r.status_code == 200:
self._last_result = r.text
self._last_request = url
return self._last_result
else:
return False
if self.need_control:
self.controller = Controller.from_port(address=self.host, port=control_port)
self.controller.authenticate(self.password)
else:
self.controller = None
return

def ip(self):
self._ip = self.get('http://bradheath.org/ip')
return self._ip

def timeForNew(self):
self._checkIdentityTime()
return

def saveLastResult(file):
with open(file, 'wb') as local_file:
local_file.write(self._last_result)
return

def downloadFile(self, url, file):
self._checkIdentityTime()
r = requests.get(url, stream = True, proxies = self._proxies)
with open(file, 'wb') as local_file:
for chunk in r.iter_content ( chunk_size = 1024)
if chunk:
local_file.write(chunk)
self._last_request = url
return True
def get(self, url, timeout=30):
response = requests.get(url, timeout=timeout, proxies=self.proxies)
return response

def newIdentity(self):
print "## NEW IDENTITY ## "
if not self._connected:
self.torControl = Controller.from_port(port=self.controlPort)
self.torControl.authenticate(self.password)
self._connected = True
self.torControl.authenticate(self.password)
self.torControl.signal(Signal.NEWNYM)
self._last_id_time = datetime.datetime.now()
return True
def post(self):
#TODO
pass

def _checkIdentityTime(self):
if self._id_time != None and self._last_id_time != None:
if (datetime.datetime.now() - self._last_id_time).seconds >= self._id_time:
print 'Getting new identity'
self.newIdentity()
return

def identityTime(self, time = 600):
self._id_time = time
return

def mechanizeBrowser(self):
self.browser = mechanize.Browser()
return self.browser
def ip(self):
response = self.get('http://icanhazip.com/') # standard url
if response.status_code==200:
self._ip=response.text
return self._ip
else:
return None

def get_new_identity(self):
if not self.controller:
self.controller = Controller.from_port(address=self.host, port=self.control_port)
self.controller.authenticate(self.password)
self.controller.signal(Signal.NEWNYM)
return self.ip()
3 changes: 3 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
stem
requests
requests[socks]
12 changes: 12 additions & 0 deletions test/ip.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import requests

tor_proxy = 'socks5://10.130.4.162:9050' #lab machine
socks_proxy = { 'http': tor_proxy,
'https': tor_proxy
}

current_ip = requests.get(url='http://icanhazip.com/',proxies=socks_proxy,verify=False)

print(current_ip.text)


11 changes: 11 additions & 0 deletions test/new-ip.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from stem import Signal
from stem.control import Controller


def get_new_ip():
"""Change IP using TOR"""
with Controller.from_port(address = '10.130.4.162', port=9051) as controller:
controller.authenticate(password='password')
controller.signal(Signal.NEWNYM)

get_new_ip()
15 changes: 15 additions & 0 deletions test/privoxy.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import requests

local_proxy = '10.130.4.162:8118'
http_proxy = {
'http': local_proxy,
'https': local_proxy
}

current_ip = requests.get(
url='http://icanhazip.com/',
proxies=http_proxy,
verify=False
)

print(current_ip.text)
23 changes: 23 additions & 0 deletions test/pytor-test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import sys
sys.path.append('../')

from pytor import PyTor
import requests

r = requests.get(url='http://icanhazip.com/')
if (r.status_code == 200):
ip = r.text

tor = PyTor(host='10.130.4.162', need_control=True, control_port=9051, socks_port=9050, password='password')

print("Without Tor, my IP address is : " + str(ip))
print("With Tor, my IP address is : " + tor.ip())
print("Getting new Ip from Tor #####")
tor.get_new_identity()
print("Now my IP address is : " + tor.ip())


r=tor.get(url="http://www.thehindu.com/")

if(r.status_code==200):
print(r.text)