资讯详情

Python3用scrapy爬取https页面,提示[(‘SSL routines‘, ‘tls_process_ske_dhe‘, ‘dh key too small‘)...

在Python3中,使用scrapy爬取https在网页数据过程中,遇到以下错误提示,经过不断调试,解决问题的办法终于完成了:

1.问题错误提示信息

Traceback (most recent call last): File “/usr/lib/python3/dist-packages/scrapy/core/downloader/middleware.py”, line 44, in process_request defer.returnValue((yield download_func(request=request, spider=spider))) twisted.web._newclient.ResponseNeverReceived: [<twisted.python.failure.Failure OpenSSL.SSL.Error: [(‘SSL routines’, ‘tls_process_ske_dhe’, ‘dh key too small’)]>]

2.问题分析: 根据SSL实验室测试,网站确实使用了不安全HTTPS配置,OpenSSL拒绝与之交谈。

三、解决方案: 方案一: 将Scrapy.core.downloader.contextfactory.ScrapyClientContextFactory默认情况下,用可接受的密码代替子类化\u密码。从OpenSSLCipherString(‘DEFAULT:!DH然后将downloader\u CLIENTCONTEXTFACTORY设置为此新类。如果这样做有效,可能值得将密码字符串设置为粗略设置,但现在你需要这样做。添加以下代码:

from twisted.internet.ssl import AcceptableCiphers from scrapy.core.downloader import contextfactory contextfactory.DEFAULT_CIPHERS = AcceptableCiphers.fromOpenSSLCipherString('DEFAULT:!DH') 

方案二: 修改 twisted 库里面的 _sslverify.py 文件 修改 C:\Users{您的用户名}\AppData\Local\Programs\Python\Python36-32\Lib\sitepackages\twisted\internet_sslverify.py (就是pip 插件安装目录)

//全局变量需要添加 _DEFAULT_CIPHERS = (     'ECDH AESGCM:ECDH CHACHA20:DH AESGCM:DH CHACHA20:ECDH AES256:DH AES256:'     'ECDH AES128:DH AES:ECDH HIGH:DH HIGH:RSA AESGCM:RSA AES:RSA HIGH:'     '!aNULL:!eNULL:!MD5:!3DES'     'HIGH:!DH:!aNULL'     ) //需要修改的方法 def _expandCipherString(cipherString, method, options):     ctx = SSL.Context(method)     ctx.set_options(options)     try:         //需要修改的地方,注释原代码,在下面添加新代码         #ctx.set_cipher_list(cipherString.encode('ascii'))         ctx.set_cipher_list(_DEFAULT_CIPHERS)     except SSL.Error as e:         if e.args[0][0][2] == 'no cipher match':             return []         else:             raise     conn = SSL.Connection(ctx
      
       , 
       None
       ) ciphers 
       = conn
       .get_cipher_list
       (
       ) 
       if 
       isinstance
       (ciphers
       [
       0
       ]
       , 
       unicode
       )
       : 
       return 
       [OpenSSLCipher
       (cipher
       ) 
       for cipher 
       in ciphers
       ] 
       else
       : 
       return 
       [OpenSSLCipher
       (cipher
       .decode
       (
       'ascii'
       )
       ) 
       for cipher 
       in ciphers
       ] 
      

方案3: 修改 OpenSLL库里面 SLL.py 文件 修改 C:\Users{你的用户名}\AppData\Local\Programs\Python\Python36-32\Lib\site-packages\OpenSSL\SLL.py (就是pip 安装插件的目录) 将指定位置的代码修改。 这里的_DEFAULT_CIPHERS 变量需要自己定义一个全局变量

//需要添加的全局变量
_DEFAULT_CIPHERS = (
    'ECDH+AESGCM:ECDH+CHACHA20:DH+AESGCM:DH+CHACHA20:ECDH+AES256:DH+AES256:'
    'ECDH+AES128:DH+AES:ECDH+HIGH:DH+HIGH:RSA+AESGCM:RSA+AES:RSA+HIGH:'
    '!aNULL:!eNULL:!MD5:!3DES'
    'HIGH:!DH:!aNULL'
    )
//需要修改的方法
def set_cipher_list(self, cipher_list):
        需要修改的地方,将原代码注释掉,在下面添加新代码
        #cipher_list = _text_to_bytes_and_warn("cipher_list", cipher_list)
        cipher_list = _text_to_bytes_and_warn("cipher_list", _DEFAULT_CIPHERS )

        if not isinstance(cipher_list, bytes):
            raise TypeError("cipher_list must be a byte string.")

        _openssl_assert(
            _lib.SSL_CTX_set_cipher_list(self._context, cipher_list) == 1
        )

后两个方法也可以用,自己选择,记住一定不能删除原有代码,因为两个方法都是要修改库的源代码。这种修改可能在其他方面的使用时,会出现问题,所以不能删除源代码,以后出问题,可以再改回源代码。 这两个方法都不是很好,需要修改库源码,但可以临时用一下。 如有更好的方案,麻烦私信告诉我,谢谢

标签: ske线绕电阻器制动电阻器

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台