You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何Scrapy爬虫使用OpenSSL同款配置仍SSL握手失败?

问题描述

需要爬取一台存在SSL配置缺陷的服务器(无法修改服务器配置),该服务器仅支持TLS 1.2,且要求客户端提供SHA-1签名算法,因此客户端必须设置SECLEVEL=0。

使用OpenSSL命令行工具和Python原生SSL模块配置相同参数时,SSL握手可成功,但通过Scrapy的custom_settings设置DOWNLOADER_CLIENT_TLS_CIPHERS = 'DEFAULT:@SECLEVEL=0'后,始终出现SSL握手失败。Scrapy日志显示配置已生效,但连接目标站点https://www.legislation.gov.au时反复重试均失败。

已尝试降级OpenSSL到1.1.1版本、在MacOS环境测试等排查操作,问题仍未解决。


环境版本信息

  • Scrapy: 2.10.1
  • Python: 3.9.16
  • OpenSSL: 1.1.1w / 3.0.9(不同测试环境)
  • 操作系统: macOS 13.5 / Ubuntu 22.04

复现步骤

  1. 创建Scrapy项目及爬虫:
scrapy startproject ssl_test
cd ssl_test
scrapy genspider legislation legislation.gov.au
  1. 修改爬虫文件legislation.py,添加custom_settings:
import scrapy

class LegislationSpider(scrapy.Spider):
    name = "legislation"
    allowed_domains = ["legislation.gov.au"]
    start_urls = ["https://www.legislation.gov.au"]

    custom_settings = {
        'DOWNLOADER_CLIENT_TLS_CIPHERS': 'DEFAULT:@SECLEVEL=0',
        'LOG_LEVEL': 'DEBUG'
    }

    def parse(self, response):
        self.logger.info(f"Response status: {response.status}")
  1. 运行爬虫:
scrapy crawl legislation

验证测试(成功案例)

Python原生SSL模块测试代码

import ssl
import socket

context = ssl.create_default_context()
context.set_ciphers('DEFAULT:@SECLEVEL=0')
context.options |= ssl.OP_NO_TLSv1_3 | ssl.OP_NO_TLSv1_1 | ssl.OP_NO_TLSv1

with socket.create_connection(('www.legislation.gov.au', 443)) as sock:
    with context.wrap_socket(sock, server_hostname='www.legislation.gov.au') as ssock:
        print(f"TLS version: {ssock.version()}")
        print(f"Cipher: {ssock.cipher()}")

运行后可正常输出TLS版本和加密套件,握手成功。

OpenSSL命令行测试

openssl s_client -connect www.legislation.gov.au:443 -cipher 'DEFAULT:@SECLEVEL=0' -tls1_2

可成功完成SSL握手,获取服务器证书。


Scrapy错误日志片段

2024-05-20 14:32:15 [scrapy.downloadermiddlewares.retry] DEBUG: Retrying <GET https://www.legislation.gov.au> (failed 1 times): [<twisted.python.failure.Failure OpenSSL.SSL.Error: [('SSL routines', '', 'sslv3 alert handshake failure')]>]
2024-05-20 14:32:15 [scrapy.core.engine] DEBUG: Crawled (None) <GET https://www.legislation.gov.au> (referer: None)
2024-05-20 14:32:16 [scrapy.downloadermiddlewares.retry] DEBUG: Retrying <GET https://www.legislation.gov.au> (failed 2 times): [<twisted.python.failure.Failure OpenSSL.SSL.Error: [('SSL routines', '', 'sslv3 alert handshake failure')]>]
2024-05-20 14:32:16 [scrapy.core.engine] DEBUG: Crawled (None) <GET https://www.legislation.gov.au> (referer: None)
2024-05-20 14:32:17 [scrapy.downloadermiddlewares.retry] DEBUG: Gave up retrying <GET https://www.legislation.gov.au> (failed 3 times): [<twisted.python.failure.Failure OpenSSL.SSL.Error: [('SSL routines', '', 'sslv3 alert handshake failure')]>]
2024-05-20 14:32:17 [scrapy.core.scraper] ERROR: Error downloading <GET https://www.legislation.gov.au>
Traceback (most recent call last):
  ...
OpenSSL.SSL.Error: [('SSL routines', '', 'sslv3 alert handshake failure')]

解决方案

问题根源在于Scrapy底层依赖的Twisted库,仅设置DOWNLOADER_CLIENT_TLS_CIPHERS不足以覆盖所有SSL配置,需额外强制指定TLS版本并调整SSL上下文的安全级别。

方法1:自定义下载中间件修改SSL上下文

  1. 在项目的middlewares.py中添加自定义上下文工厂:
from scrapy.core.downloader.contextfactory import ScrapyClientContextFactory
from OpenSSL import SSL

class CustomContextFactory(ScrapyClientContextFactory):
    def getContext(self):
        ctx = super().getContext()
        # 禁用TLS 1.0/1.1/1.3,仅保留TLS 1.2
        ctx.set_options(SSL.OP_NO_TLSv1_3 | SSL.OP_NO_TLSv1_1 | SSL.OP_NO_TLSv1)
        # 设置安全级别和加密套件
        ctx.set_cipher_list('DEFAULT:@SECLEVEL=0')
        return ctx
  1. 在settings.py中启用该工厂,替换默认配置:
DOWNLOADER_CLIENTCONTEXTFACTORY = 'ssl_test.middlewares.CustomContextFactory'

方法2:补充Scrapy TLS版本配置

除了加密套件,强制指定TLS 1.2版本:

custom_settings = {
    'DOWNLOADER_CLIENT_TLS_CIPHERS': 'DEFAULT:@SECLEVEL=0',
    'DOWNLOADER_CLIENT_TLS_METHOD': 'TLSv1.2',
    'LOG_LEVEL': 'DEBUG'
}

注:部分Scrapy版本中DOWNLOADER_CLIENT_TLS_METHOD需使用Twisted常量值'TLSv1_2_METHOD',可根据实际版本调整。

验证

修改后重新运行爬虫,可成功完成SSL握手并获取站点响应。

内容的提问来源于stack exchange,提问作者Simon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 05:40:27