Как сделать urllib2-запросы через Tor в Python?
Я пытаюсь сканировать сайты, используя сканер, написанный на Python. Я хочу интегрировать Tor с Python, что означает, что я хочу сканировать сайт анонимно, используя Tor.
Я пытался сделать это. Это не похоже на работу. Я проверил свой IP-адрес, он все еще такой же, как тот, который я использовал перед тем как использовать tor Я проверил это через Python.
import urllib2
proxy_handler = urllib2.ProxyHandler({"tcp":"http://127.0.0.1:9050"})
opener = urllib2.build_opener(proxy_handler)
urllib2.install_opener(opener)
12 ответов
Вы пытаетесь подключиться к порту SOCKS - Tor отклоняет любой трафик, отличный от SOCKS. Вы можете подключиться через посредника - Privoxy - используя порт 8118.
Пример:
proxy_support = urllib2.ProxyHandler({"http" : "127.0.0.1:8118"})
opener = urllib2.build_opener(proxy_support)
opener.addheaders = [('User-agent', 'Mozilla/5.0')]
print opener.open('http://www.google.com').read()
Также обратите внимание, что свойства переданы в ProxyHandler, http не префикс ip:port
pip install PySocks
Затем:
import socket
import socks
import urllib2
ipcheck_url = 'http://checkip.amazonaws.com/'
# Actual IP.
print(urllib2.urlopen(ipcheck_url).read())
# Tor IP.
socks.setdefaultproxy(socks.PROXY_TYPE_SOCKS5, '127.0.0.1', 9050)
socket.socket = socks.socksocket
print(urllib2.urlopen(ipcheck_url).read())
Используя только urllib2.ProxyHandler
как в /questions/15439175/kak-sdelat-urllib2-zaprosyi-cherez-tor-v-python/15439189#15439189 не удается с:
Tor is not an HTTP Proxy
Упоминается в: Как я могу использовать прокси SOCKS 4/5 с urllib2?
Протестировано на Ubuntu 15.10, Tor 0.2.6.10, Python 2.7.10.
Следующий код на 100% работает на Python 3.4
(Вы должны держать TOR Browser открытым, используя этот код)
Этот скрипт подключается к TOR через socks5, получает IP с checkip.dyn.com, меняет личность и повторно отправляет запрос на получение нового IP (повторяется 10 раз)
Вам нужно установить соответствующие библиотеки, чтобы это работало. (Наслаждайтесь и не злоупотребляйте)
import socks
import socket
import time
from stem.control import Controller
from stem import Signal
import requests
from bs4 import BeautifulSoup
err = 0
counter = 0
url = "checkip.dyn.com"
with Controller.from_port(port = 9151) as controller:
try:
controller.authenticate()
socks.setdefaultproxy(socks.PROXY_TYPE_SOCKS5, "127.0.0.1", 9150)
socket.socket = socks.socksocket
while counter < 10:
r = requests.get("http://checkip.dyn.com")
soup = BeautifulSoup(r.content)
print(soup.find("body").text)
counter = counter + 1
#wait till next identity will be available
controller.signal(Signal.NEWNYM)
time.sleep(controller.get_newnym_wait())
except requests.HTTPError:
print("Could not reach URL")
err = err + 1
print("Used " + str(counter) + " IPs and got " + str(err) + " errors")
Следующее решение работает для меня в Python 3. Адаптировано из ответа Сиро Сантилли:
С urllib
(имя urllib2 в Python 3):
import socks
import socket
from urllib.request import urlopen
url = 'http://icanhazip.com/'
socks.setdefaultproxy(socks.PROXY_TYPE_SOCKS5, '127.0.0.1', 9150)
socket.socket = socks.socksocket
response = urlopen(url)
print(response.read())
С requests
:
import socks
import socket
import requests
url = 'http://icanhazip.com/'
socks.setdefaultproxy(socks.PROXY_TYPE_SOCKS5, '127.0.0.1', 9150)
socket.socket = socks.socksocket
response = requests.get(url)
print(response.text)
С Selenium
+ PhantomJS:
from selenium import webdriver
url = 'http://icanhazip.com/'
service_args = [ '--proxy=localhost:9150', '--proxy-type=socks5', ]
phantomjs_path = '/your/path/to/phantomjs'
driver = webdriver.PhantomJS(
executable_path=phantomjs_path,
service_args=service_args)
driver.get(url)
print(driver.page_source)
driver.close()
Примечание: если вы планируете часто использовать Tor, подумайте о том, чтобы сделать пожертвование для поддержки их потрясающей работы!
Использование privoxy в качестве http-прокси перед Tor работает для меня - вот шаблон-сканер:
import urllib2
import httplib
from BeautifulSoup import BeautifulSoup
from time import sleep
class Scraper(object):
def __init__(self, options, args):
if options.proxy is None:
options.proxy = "http://localhost:8118/"
self._open = self._get_opener(options.proxy)
def _get_opener(self, proxy):
proxy_handler = urllib2.ProxyHandler({'http': proxy})
opener = urllib2.build_opener(proxy_handler)
return opener.open
def get_soup(self, url):
soup = None
while soup is None:
try:
request = urllib2.Request(url)
request.add_header('User-Agent', 'foo bar useragent')
soup = BeautifulSoup(self._open(request))
except (httplib.IncompleteRead, httplib.BadStatusLine,
urllib2.HTTPError, ValueError, urllib2.URLError), err:
sleep(1)
return soup
class PageType(Scraper):
_URL_TEMPL = "http://foobar.com/baz/%s"
def items_from_page(self, url):
nextpage = None
soup = self.get_soup(url)
items = []
for item in soup.findAll("foo"):
items.append(item["bar"])
nexpage = item["href"]
return nextpage, items
def get_items(self):
nextpage, items = self._categories_from_page(self._START_URL % "start.html")
while nextpage is not None:
nextpage, newitems = self.items_from_page(self._URL_TEMPL % nextpage)
items.extend(newitems)
return items()
pt = PageType()
print pt.get_items()
Обновление - последнее (до версии v2.10.0) requests
библиотека поддерживает прокси-носители с дополнительным требованием requests[socks]
,
Установка -
pip install requests requests[socks]
Основное использование -
import requests
session = requests.session()
# Tor uses the 9050 port as the default socks port
session.proxies = {'http': 'socks5://127.0.0.1:9050',
'https': 'socks5://127.0.0.1:9050'}
# Make a request through the Tor connection
# IP visible through Tor
print session.get("http://httpbin.org/ip").text
# Above should print an IP different than your public IP
# Following prints your normal public IP
print requests.get("http://httpbin.org/ip").text
Старый ответ. Несмотря на то, что это старый пост, отвечаю, потому что, кажется, никто не упомянул requesocks
библиотека.
Это в основном порт requests
библиотека. Обратите внимание, что библиотека является старым форком (последнее обновление 2013-03-25) и может не иметь тех же функций, что и библиотека последних запросов.
Установка -
pip install requesocks
Основное использование -
# Assuming that Tor is up & running
import requesocks
session = requesocks.session()
# Tor uses the 9050 port as the default socks port
session.proxies = {'http': 'socks5://127.0.0.1:9050',
'https': 'socks5://127.0.0.1:9050'}
# Make a request through the Tor connection
# IP visible through Tor
print session.get("http://httpbin.org/ip").text
# Above should print an IP different than your public IP
# Following prints your normal public IP
import requests
print requests.get("http://httpbin.org/ip").text
Вот код для загрузки файлов с использованием Tor Proxy в Python: (обновление URL)
import urllib2
url = "http://www.disneypicture.net/data/media/17/Donald_Duck2.gif"
proxy = urllib2.ProxyHandler({'http': '127.0.0.1:8118'})
opener = urllib2.build_opener(proxy)
urllib2.install_opener(opener)
file_name = url.split('/')[-1]
u = urllib2.urlopen(url)
f = open(file_name, 'wb')
meta = u.info()
file_size = int(meta.getheaders("Content-Length")[0])
print "Downloading: %s Bytes: %s" % (file_name, file_size)
file_size_dl = 0
block_sz = 8192
while True:
buffer = u.read(block_sz)
if not buffer:
break
file_size_dl += len(buffer)
f.write(buffer)
status = r"%10d [%3.2f%%]" % (file_size_dl, file_size_dl * 100. / file_size)
status = status + chr(8)*(len(status)+1)
print status,
f.close()
Возможно, у вас есть проблемы с сетевым подключением? Вышеупомянутый скрипт работал для меня (я заменил другой URL - я использовал http://stackru.com/
- и я получаю страницу, как ожидалось:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd" >
<html> <head>
<title>Stack Overflow</title>
<link rel="stylesheet" href="/content/all.css?v=3856">
(так далее.)
Чтобы расширить комментарий выше об использовании torify и браузера Tor (и не требует Privoxy):
pip install PySocks
pip install pyTorify
(установите браузер Tor и запустите его)
Использование командной строки:
python -mtorify -p 127.0.0.1:9150 your_script.py
Или встроен в скрипт:
import torify
torify.set_tor_proxy("127.0.0.1", 9150)
torify.disable_tor_check()
torify.use_tor_proxy()
# use urllib as normal
import urllib.request
req = urllib.request.Request("http://....")
req.add_header("Referer", "http://...") # etc
res = urllib.request.urlopen(req)
html = res.read().decode("utf-8")
Обратите внимание, что браузер Tor использует порт 9150, а не 9050
Думаю, я бы просто поделился решением, которое работало для меня (python3, windows10):
Шаг 1: Включите ваш Tor ControlPort на 9151
,
Сервис Tor работает на порте по умолчанию 9150
и ControlPort на 9151
, Вы должны увидеть местный адрес 127.0.0.1:9150
а также 127.0.0.1:9151
когда ты бежишь netstat -an
,
[go to windows terminal]
cd ...\Tor Browser\Browser\TorBrowser\Tor
tor --service remove
tor --service install -options ControlPort 9151
netstat -an
Шаг 2: скрипт Python, как следует.
# library to launch and kill Tor process
import os
import subprocess
# library for Tor connection
import socket
import socks
import http.client
import time
import requests
from stem import Signal
from stem.control import Controller
# library for scraping
import csv
import urllib
from bs4 import BeautifulSoup
import time
def launchTor():
# start Tor (wait 30 sec for Tor to load)
sproc = subprocess.Popen(r'.../Tor Browser/Browser/firefox.exe')
time.sleep(30)
return sproc
def killTor(sproc):
sproc.kill()
def connectTor():
socks.setdefaultproxy(socks.PROXY_TYPE_SOCKS5, "127.0.0.1", 9150, True)
socket.socket = socks.socksocket
print("Connected to Tor")
def set_new_ip():
# disable socks server and enabling again
socks.setdefaultproxy()
"""Change IP using TOR"""
with Controller.from_port(port=9151) as controller:
controller.authenticate()
socks.setdefaultproxy(socks.PROXY_TYPE_SOCKS5, "127.0.0.1", 9150, True)
socket.socket = socks.socksocket
controller.signal(Signal.NEWNYM)
def checkIP():
conn = http.client.HTTPConnection("icanhazip.com")
conn.request("GET", "/")
time.sleep(3)
response = conn.getresponse()
print('current ip address :', response.read())
# Launch Tor and connect to Tor network
sproc = launchTor()
connectTor()
# list of url to scrape
url_list = [list of all the urls you want to scrape]
for url in url_list:
# set new ip and check ip before scraping for each new url
set_new_ip()
# allow some time for IP address to refresh
time.sleep(5)
checkIP()
'''
[insert your scraping code here: bs4, urllib, your usual thingy]
'''
# remember to kill process
killTor(sproc)
Этот скрипт обновит IP-адрес для каждого URL, который вы хотите очистить. Просто убедитесь, что вы спите достаточно долго для изменения IP. Последняя проверка вчера. Надеюсь это поможет!
Tor является прокси-сервером. Соединение с ним напрямую в примере, который вы цитируете, завершается с ошибкой "urlopen error Ошибка подключения к туннелю: 501 Tor не является прокси-сервером HTTP". Как уже упоминали другие, вы можете обойти это с Privoxy.
В качестве альтернативы вы также можете использовать PycURL или SocksiPy. Примеры использования обоих с tor смотрите...
https://stem.torproject.org/tutorials/to_russia_with_love.html