J'ai affaire à Scrapy, Privoxy et Tor. J'ai tout installé et fonctionne correctement. Mais Tor se connecte à chaque fois avec la même IP, donc je peux facilement être banni. Est-il possible de dire à Tor de se reconnecter toutes les X secondes ou connexions?
Merci!
EDIT sur la configuration: Pour le pool d'agent utilisateur, j'ai fait ceci: http://tangww.com/2013/06/UsingRandomAgent/ (J'ai dû mettre un _ init _.py file comme il est dit dans les commentaires), et pour Privoxy et Tor j'ai suivi http://www.andrewwatters.com/privoxy/ = (J'ai dû créer manuellement l'utilisateur privé et le groupe privé avec le terminal). Ça a marché :)
Mon araignée est la suivante:
from scrapy.contrib.spiders import CrawlSpider
from scrapy.selector import Selector
from scrapy.http import Request
class YourCrawler(CrawlSpider):
name = "spider_name"
start_urls = [
'https://example.com/listviews/titles.php',
]
allowed_domains = ["example.com"]
def parse(self, response):
# go to the urls in the list
s = Selector(response)
page_list_urls = s.xpath('///*[@id="tab7"]/article/header/h2/a/@href').extract()
for url in page_list_urls:
yield Request(response.urljoin(url), callback=self.parse_following_urls, dont_filter=True)
# Return back and go to bext page in div#paginat ul li.next a::attr(href) and begin again
next_page = response.css('ul.pagin li.presente ~ li a::attr(href)').extract_first()
if next_page is not None:
next_page = response.urljoin(next_page)
yield Request(next_page, callback=self.parse)
# For the urls in the list, go inside, and in div#main, take the div.ficha > div.caracteristicas > ul > li
def parse_following_urls(self, response):
#Parsing rules go here
for each_book in response.css('main#main'):
yield {
'editor': each_book.css('header.datos1 > ul > li > h5 > a::text').extract(),
}
Dans settings.py j'ai une rotation d'agent utilisateur et privoxy:
DOWNLOADER_MIDDLEWARES = {
#user agent
'scrapy.contrib.downloadermiddleware.useragent.UserAgentMiddleware' : None,
'spider_name.comm.rotate_useragent.RotateUserAgentMiddleware' :400,
#privoxy
'scrapy.downloadermiddlewares.httpproxy.HttpProxyMiddleware': 110,
'spider_name.middlewares.ProxyMiddleware': 100
}
Dans middlewares.py, j'ai ajouté:
class ProxyMiddleware(object):
def process_request(self, request, spider):
request.meta['proxy'] = 'http://127.0.0.1:8118'
spider.log('Proxy : %s' % request.meta['proxy'])
Et je pense que c'est tout ...
EDIT II ---
Ok, j'ai changé mon fichier middlewares.py comme dans le blog @ Tomáš Linhart dit de:
class ProxyMiddleware(object):
def process_request(self, request, spider):
request.meta['proxy'] = 'http://127.0.0.1:8118'
spider.log('Proxy : %s' % request.meta['proxy'])
À
from stem import Signal
from stem.control import Controller
class ProxyMiddleware(object):
def process_request(self, request, spider):
request.meta['proxy'] = 'http://127.0.0.1:8118'
spider.log('Proxy : %s' % request.meta['proxy'])
def set_new_ip():
with Controller.from_port(port=9051) as controller:
controller.authenticate(password='tor_password')
controller.signal(Signal.NEWNYM)
Mais maintenant, c'est vraiment lent, et ne semble pas changer l'ip ...
Cette article de blog pourrait vous aider un peu car elle traite du même problème.
EDIT: Basé sur une exigence concrète (nouvelle IP pour chaque demande ou après [~ # ~] n [~ # ~] requêtes), appelez le set_new_ip
dans process_request
méthode du middleware. Notez cependant que cet appel à set_new_ip
la fonction ne doit pas toujours garantir une nouvelle IP (il y a un lien vers le FAQ avec explication).
EDIT2: Le module avec la classe ProxyMiddleware
ressemblerait à ceci:
from stem import Signal
from stem.control import Controller
def _set_new_ip():
with Controller.from_port(port=9051) as controller:
controller.authenticate(password='tor_password')
controller.signal(Signal.NEWNYM)
class ProxyMiddleware(object):
def process_request(self, request, spider):
_set_new_ip()
request.meta['proxy'] = 'http://127.0.0.1:8118'
spider.log('Proxy : %s' % request.meta['proxy'])
Mais Tor se connecte avec la même IP à chaque fois
C'est une fonctionnalité Tor documentée :
Une chose importante à noter est que un nouveau circuit ne signifie pas nécessairement une nouvelle adresse IP . Les chemins sont sélectionnés au hasard sur la base d'heuristiques comme la vitesse et la stabilité. Il n'y a que tant de grandes sorties dans le réseau Tor, il n'est donc pas rare de réutiliser une sortie que vous avez eu précédemment.
C'est la raison pour laquelle l'utilisation du code ci-dessous peut entraîner la réutilisation de la même adresse IP.
from stem import Signal
from stem.control import Controller
with Controller.from_port(port=9051) as controller:
controller.authenticate(password='tor_password')
controller.signal(Signal.NEWNYM)
https://github.com/DusanMadar/TorIpChanger vous aide à gérer ce comportement. Admission - j'ai écrit TorIpChanger
.
J'ai également élaboré un guide sur la façon d'utiliser Python avec Tor et Privoxy: https://Gist.github.com/DusanMadar/8d11026b7ce0bce6a67f7dd87b999f6b .
Voici un exemple d'utilisation de TorIpChanger
(pip install toripchanger
) dans votre ProxyMiddleware
.
from toripchanger import TorIpChanger
# A Tor IP will be reused only after 10 different IPs were used.
ip_changer = TorIpChanger(reuse_threshold=10)
class ProxyMiddleware(object):
def process_request(self, request, spider):
ip_changer.get_new_ip()
request.meta['proxy'] = 'http://127.0.0.1:8118'
spider.log('Proxy : %s' % request.meta['proxy'])
Ou, si vous souhaitez utiliser une adresse IP différente après 10 demandes, vous pouvez faire quelque chose comme ci-dessous.
from toripchanger import TorIpChanger
# A Tor IP will be reused only after 10 different IPs were used.
ip_changer = TorIpChanger(reuse_threshold=10)
class ProxyMiddleware(object):
_requests_count = 0
def process_request(self, request, spider):
self._requests_count += 1
if self._requests_count > 10:
self._requests_count = 0
ip_changer.get_new_ip()
request.meta['proxy'] = 'http://127.0.0.1:8118'
spider.log('Proxy : %s' % request.meta['proxy'])