'NoneType' 对象在 scrapy\twisted\openssl 中没有属性“_app_data”

'NoneType' object has no attribute '_app_data' in scrapy\twisted\openssl

在使用scrapy进行抓取的过程中,我的日志中不时出现一个错误。 它似乎不在我的代码中的任何地方,看起来像是 twisted\openssl 中的某个东西。 知道是什么原因造成的以及如何摆脱它吗?

此处的堆栈跟踪:

[Launcher,27487/stderr] Error during info_callback
    Traceback (most recent call last):
      File "/opt/webapps/link_crawler/lib/python2.7/site-packages/twisted/protocols/tls.py", line 415, in dataReceived
        self._write(bytes)
      File "/opt/webapps/link_crawler/lib/python2.7/site-packages/twisted/protocols/tls.py", line 554, in _write
        sent = self._tlsConnection.send(toSend)
      File "/opt/webapps/link_crawler/lib/python2.7/site-packages/OpenSSL/SSL.py", line 1270, in send
        result = _lib.SSL_write(self._ssl, buf, len(buf))
      File "/opt/webapps/link_crawler/lib/python2.7/site-packages/OpenSSL/SSL.py", line 926, in wrapper
        callback(Connection._reverse_mapping[ssl], where, return_code)
    --- <exception caught here> ---
      File "/opt/webapps/link_crawler/lib/python2.7/site-packages/twisted/internet/_sslverify.py", line 1055, in infoCallback
        return wrapped(connection, where, ret)
      File "/opt/webapps/link_crawler/lib/python2.7/site-packages/twisted/internet/_sslverify.py", line 1157, in _identityVerifyingInfoCallback
        transport = connection.get_app_data()
      File "/opt/webapps/link_crawler/lib/python2.7/site-packages/OpenSSL/SSL.py", line 1589, in get_app_data
        return self._app_data
      File "/opt/webapps/link_crawler/lib/python2.7/site-packages/OpenSSL/SSL.py", line 1148, in __getattr__
        return getattr(self._socket, name)
    exceptions.AttributeError: 'NoneType' object has no attribute '_app_data'

乍一看,这似乎是由于 scrapy 中的一个错误。 Scrapy 定义了自己的 Twisted "context factory": https://github.com/scrapy/scrapy/blob/ad36de4e6278cf635509a1ade30cca9a506da682/scrapy/core/downloader/contextfactory.py#L21-L28

此代码使用它打算 return 的上下文实例化 ClientTLSOptions。实例化此 class 的副作用是在上下文工厂中安装了 "info callback"。信息回调要求 Twisted TLS 实现已在连接上设置为 "app data"。但是,由于没有任何东西使用 ClientTLSOptions 实例(它会立即被丢弃),因此永远不会设置应用程序数据。

当信息回调回来获取 Twisted TLS 实现(完成其部分工作所必需的)时,它反而发现没有应用程序数据并且失败并出现您报告的异常。

ClientTLSOptions 的副作用有点令人不快,但我认为这显然是由 ClientTLSOptions 的 mis-use/abuse 引起的一个 scrapy 错误。我认为这段代码不可能经过很好的测试,因为每次证书验证失败时都会发生此错误。

我建议将错误报告给 Scrapy。希望他们可以修复 ClientTLSOptions 的使用并为您消除此错误。

我能够通过安装 service_identity 软件包解决这个问题:

pip install service_identity

在将所有图像链接发送到图像管道之前,我将所有图像链接中的 https:// 替换为 http://,从而解决了这个问题