Heroku 上的 Scrapy 爬虫返回 503 Service Unavailable

问题描述

我有一个抓取网站上的数据并将抓取的数据上传到远程 MongoDB 服务器的爬虫。我想在 heroku 上托管它以自动抓取很长时间。 我使用scrapy-user-agents 在不同的用户代理之间轮换。 当我在我的电脑上本地使用 scrapy crawl <spider> 时,spider 正确运行并将数据返回到 MongoDB 数据库

但是,当我在 heroku 上部署项目时,我的 heroku 日志中有以下几行:

2020-12-22T12:50:21.132731+00:00 app[web.1]: 2020-12-22 12:50:21 [scrapy.downloadermiddlewares.retry] 调试:重试 https://indiankanoon.org/browse/> (失败 1 次):503 服务不可用

2020-12-22T12:50:21.134186+00:00 app[web.1]: 2020-12-22 12:50:21 [scrapy_user_agents.middlewares] 调试:分配的用户代理 Mozilla/5.0 (Windows NT) 6.1; WOW64) AppleWebKit/537.36 (KHTML,like Gecko) Chrome/53.0.2785.143 Safari/537.36

(它同样失败了 9 次,直到:)

2020-12-22T12:50:23.594655+00:00 app[web.1]: 2020-12-22 12:50:23 [scrapy.downloadermiddlewares.retry] 错误:放弃重试

2020-12-22T12:50:23.599310+00:00 app[web.1]: 2020-12-22 12:50:23 [scrapy.core.engine] 调试:爬网 (503)

2020-12-22T12:50:23.701386+00:00 app[web.1]: 2020-12-22 12:50:23 [scrapy.spidermiddlewares.httperror] 信息:忽略响应

2020-12-22T12:50:23.714834+00:00 app[web.1]: 2020-12-22 12:50:23 [scrapy.core.engine] 信息:关闭蜘蛛(已完成)

总而言之,我的本地 IP 地址能够抓取数据,而 Heroku 尝试时却无法抓取。更改 settings.py 文件中的某些内容可以纠正它吗?

我的 settings.py 文件

    BOT_NAME = 'indkanoon'
    
    SPIDER_MODULES = ['indkanoon.spiders']
    NEWSPIDER_MODULE = 'indkanoon.spiders'
    MONGO_URI = ''
    MONGO_DATABASE = 'casecounts'    
    ROBOTSTXT_OBEY = False
    CONCURRENT_REQUESTS = 32
    DOWNLOAD_DELAY = 3
    COOKIES_ENABLED = False
    DOWNLOADER_MIDDLEWARES = {
        'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware': None,'scrapy_user_agents.middlewares.RandomUserAgentMiddleware': 400,}
    ITEM_PIPELInes = {
   'indkanoon.pipelines.IndkanoonPipeline': 300,}
    RETRY_ENABLED = True
    RETRY_TIMES = 8
    RETRY_HTTP_CODES = [500,502,503,504,522,524,408]

解决方法

这可能是由于 DDoS 保护或您试图从中抓取的服务器的 IP 黑名单。

为了克服这种情况,您可以使用代理。

我会推荐一个中间件,比如scrapy-proxys。使用它,您可以轮换、过滤不良代理或为您的请求使用单个代理。而且,这样可以省去您每次设置代理的麻烦。

这直接来自开发者 GitHub README (Github Link)。

安装scrapy-rotating-proxy 库

pip install scrapy_proxies

在 settings.py 中添加以下设置

# Retry many times since proxies often fail
RETRY_TIMES = 10
# Retry on most error codes since proxies fail for different reasons
RETRY_HTTP_CODES = [500,503,504,400,403,404,408]

DOWNLOADER_MIDDLEWARES = {
    'scrapy.downloadermiddlewares.retry.RetryMiddleware': 90,'scrapy_proxies.RandomProxy': 100,'scrapy.downloadermiddlewares.httpproxy.HttpProxyMiddleware': 110,}

# Proxy list containing entries like
# http://host1:port
# http://username:password@host2:port
# http://host3:port
# ...
PROXY_LIST = '/path/to/proxy/list.txt'

# Proxy mode
# 0 = Every requests have different proxy
# 1 = Take only one proxy from the list and assign it to every requests
# 2 = Put a custom proxy to use in the settings
PROXY_MODE = 0

# If proxy mode is 2 uncomment this sentence :
#CUSTOM_PROXY = "http://host1:port"

在这里您可以更改重试次数,设置单个或轮换代理

然后将您的代理添加到这样的 list.txt 文件中

http://host1:port
http://username:password@host2:port
http://host3:port

使用它,您的所有请求都将通过代理发送,代理会随机轮换每个请求,因此不会影响并发性。

其他类似的中间件也可用,如

scrapy-rotating-proxies

scrapy-proxies-tool

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...