/scrapy-roundrobin-proxy

scrapy中使用到的一些中间件

Primary LanguagePythonMIT LicenseMIT

scrapy-middlewares

设计**

在抓一个指定网站的时候, 保证不能抓这个网站太快, 防止将网站抓跪了

在防止被ban上, 我们的理想条件是每个代理在两次抓取中间隔最大, 这样可以尽量避免被反爬引擎监控到. 随机的获取代理会造成碰撞

第二就是每个页面不允许失败, 如果这个页面是因为被ban然后失败, 那么将这个页面扔到队列的最后, 过阵子再抓.

每次请求都从代理池中拿出一个最长时间未使用的代理.

round_robin

一个用轮询实现的代理中间件, 一般的代理用random方式实现, 如果一个spider的代理数量少, 那么会发生碰撞, 造成代理的利用率下降.

这里采用的模式是如果一个代理是可用的, 那么下次尽可能将这个代理放到优先级队列的尾部, 也就是说, 尽量让一个代理在一个网站上使用的间隔最大.

具体用法参考见这个大佬的(代理插件)[https://github.com/TeamHG-Memex/scrapy-ROUND_ROBIN-proxies]

在settings.py文件中编辑

DOWNLOADER_MIDDLEWARES = {
    # ...
    'round_robin.middlewares.ROUND_ROBINProxyMiddleware': 610,
    'round_robin.middlewares.BanDetectionMiddleware': 620,
    # ...
}

每个spider需要实现下面两个方法, 用来确定哪些页面是被ban掉的:

    def response_is_ban(self, request, response):
        if response.status not in self.NOT_BAN_STATUSES:
            return True
        if response.status == 200 and not len(response.body):
            return True
        return False

    def exception_is_ban(self, request, exception):
        return not isinstance(exception, self.NOT_BAN_EXCEPTIONS)

settings.py中设置下面几个参数:

ROUND_ROBIN_PROXY_LIST_PATH = "proxy.txt" # 存放代理的路径, 格式类似于127.0.0.1:8080
# 或者直接在setting中写
ROUND_ROBIN_PROXY_LIST = [
    'proxy1.com:8000',
    'proxy2.com:8031',
    # ...
]

ROUND_ROBIN_PROXY_CLOSE_SPIDER = True # 代理为空的操作, 默认是关闭
ROUND_ROBIN_PROXY_PAGE_RETRY_TIMES = 2 # 代理失败的重试次数, 这个是重试过失败后会扔到队列最后面, 也就是说, 不允许有失败的页面
PROXY_MAX_ORDER =  100000 # 内存中代理池的最大数量, 这个数字应该比你代理的数量大一倍, 建议
TIMEOUT_IF_NO_PROXY = 300 # 代理池为空的话, 等待多少秒后才抛出没有代理的异常
ROUND_ROBIN_PROXY_DELAY = 3 # 每个代理间隔多久才能用, 默认是3s, 这里是说, 我这个代理再次请求这个网站的间隔
RANDOMIZE_DOWNLOAD_DELAY # True # 代理的延迟间隔是否采用随机, 随机的话是0.5*delay ~ 1.5*delay之间