这个问题必然有两种形式,因为我不知道找到解决方案的更好途径。
我正在爬网的网站经常将我踢到重定向的“用户被阻止”页面,但是频率(按请求/时间)似乎是随机的,并且它们似乎有一个黑名单阻止了我正在使用的许多“开放”代理列表通过Proxymesh。所以...
DEBUG: Redirecting (302) to (GET http://.../you_got_blocked.aspx) from (GET http://.../page-544.htm)
)时,它会继续尝试访问第544.htm页,还是继续到第545.htm页并永久丢失第544页。 htm?如果它“忘记”(或将其视为已访问),是否有办法告诉它继续重试该页面? (如果它自然地这样做,那么很好,并且很了解...)(a)我目前正在做什么:通过http_proxy环境变量使用proxymesh旋转Proxy,该变量似乎经常旋转代理以至少相当定期地通过目标站点的重定向。 (缺点:开放代理ping的速度很慢,只有太多代理服务器,proxymesh最终会在超过10个演出后向我收取每笔演出的费用,我只需要在重定向时旋转它们,我不知道要多久或多久一次触发它们旋转,然后执行上面的操作:我不知道重定向的页面是否被Scrapy重新排队...)(如果Proxymesh在每个请求上都在旋转,那么我可以合理地支付费用。)
(b)使用中间件在每个重定向上重新选择一个新的代理是否有意义(并且很简单)?那么每一个单独的请求呢?通过诸如TOR或Proxifier之类的东西会更有意义吗?如果这相对简单,我将如何设置?我已经在几个地方阅读过类似的内容,但是大多数链接已损坏或不推荐使用的Scrapy命令已经过时了。
作为引用,我确实为Proxy Mesh设置了中间件(是的,我使用的是http_proxy环境变量,但是当遇到麻烦时,我是冗余的粉丝)。所以这是我目前拥有的,以防万一:
class ProxyMiddleware(object):
def process_request(self, request, spider):
request.meta['proxy'] = "http://open.proxymesh.com:[port number]"
proxy_user_pass = "username:password"
encoded_user_pass = base64.encodestring(proxy_user_pass)
request.headers['Proxy-Authorization'] = 'Basic ' + encoded_user_pass
最佳答案
昨天,我在代理和防御DDoS方面也完成了类似的任务。 (我已经解析了一个网站)
这个想法在random.choice
中。每个请求都有机会更改IP。
Scrapy使用Tor和telnetlib3。您需要配置ControlPort密码。
from scrapy import log
from settings import USER_AGENT_LIST
import random
import telnetlib
import time
# 15% ip change
class RetryChangeProxyMiddleware(object):
def process_request(self, request, spider):
if random.choice(xrange(1,100)) <= 15:
log.msg('Changing proxy')
tn = telnetlib.Telnet('127.0.0.1', 9051)
tn.read_until("Escape character is '^]'.", 2)
tn.write('AUTHENTICATE "<PASSWORD HERE>"\r\n')
tn.read_until("250 OK", 2)
tn.write("signal NEWNYM\r\n")
tn.read_until("250 OK", 2)
tn.write("quit\r\n")
tn.close()
log.msg('>>>> Proxy changed. Sleep Time')
time.sleep(10)
# 30% useragent change
class RandomUserAgentMiddleware(object):
def process_request(self, request, spider):
if random.choice(xrange(1,100)) <= 30:
log.msg('Changing UserAgent')
ua = random.choice(USER_AGENT_LIST)
if ua:
request.headers.setdefault('User-Agent', ua)
log.msg('>>>> UserAgent changed')