"WindowsError:[错误5]访问被拒绝"使用urllib2

Boa*_*Boa 6 python windows urllib2

在使用urllib2阅读网站时,我收到"WindowsError:[错误5]访问被拒绝"消息.

from urllib2 import urlopen, Request
from bs4 import BeautifulSoup

hdr = {'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11'}
req = Request('https://' + url, headers=hdr)
soup = BeautifulSoup( urlopen( req ).read() )
Run Code Online (Sandbox Code Playgroud)

完整的追溯是:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Python27\lib\urllib2.py", line 154, in urlopen
    return opener.open(url, data, timeout)
  File "C:\Python27\lib\urllib2.py", line 431, in open
    response = self._open(req, data)
  File "C:\Python27\lib\urllib2.py", line 449, in _open
    '_open', req)
  File "C:\Python27\lib\urllib2.py", line 409, in _call_chain
    result = func(*args)
  File "C:\Python27\lib\urllib2.py", line 1240, in https_open
    context=self._context)
  File "C:\Python27\lib\urllib2.py", line 1166, in do_open
    h = http_class(host, timeout=req.timeout, **http_conn_args)
  File "C:\Python27\lib\httplib.py", line 1258, in __init__
    context = ssl._create_default_https_context()
  File "C:\Python27\lib\ssl.py", line 440, in create_default_context
    context.load_default_certs(purpose)
  File "C:\Python27\lib\ssl.py", line 391, in load_default_certs
    self._load_windows_store_certs(storename, purpose)
  File "C:\Python27\lib\ssl.py", line 378, in _load_windows_store_certs
    for cert, encoding, trust in enum_certificates(storename):
WindowsError: [Error 5] Access is denied
Run Code Online (Sandbox Code Playgroud)

我已尝试使用管理员权限从命令提示符运行脚本,如此处所示,但它不能解决问题.

有关如何解决此错误的任何建议?

tin*_*tin 3

看起来这是 Windows 证书存储不一致。httplib- 这是内部调用的urllib2- 最近从无服务器证书验证更改为默认情况下强制执行服务器证书验证。因此,您将在任何基于 并在您的用户配置文件中运行的 python 脚本中遇到此urllib问题httplib

也就是说,您的 Windows 证书存储区似乎存在严重问题。httplib尝试枚举指定证书存储的证书(如中CA certification authority所示)时失败,但对于正常的受信任根证书存储则成功(请参阅问题评论)。因此,我建议检查所有证书中最近添加的证书和/或 Windows 日志中的一般错误。在您的情况下,发生的情况是内部调用,然后尝试设置默认的 ssl 上下文并强制执行证书验证,并且作为此过程的一部分,它通过调用 来枚举系统的可信证书锚点。该函数在as中实现,内部调用 WINAPI和. 对于证书存储位置,它只是在两个 winapi 调用之一中失败并拒绝访问。Intermediate Certification Authoritiescertmgr.mscROOTcertmgr:intermediate certificate authoritiesurllib2httplibssl.enum_certificatesC_ssl_enum_certificates_implCertOpenSystemStoreCertEnumCertificatesInStoreCA

如果您想进一步调试它,您还可以尝试手动调用with作为参数并尝试从这一侧调试它,尝试其他 Windows certstore 管理工具和/或致电 microsoft 支持人员寻求帮助。WINAPI:CertOpenSystemStoreLPTCSTR::'CA'

也有迹象表明其他人在连接该 api 调用时也遇到了类似的问题,请参阅 google:访问被拒绝 CertOpenSystemStore

如果您只是想让它工作而不修复根本原因,您可以尝试使用以下解决方法来临时修补_windows_cert_stores以不包含损坏的CA证书库或完全禁用信任锚加载逻辑。(所有其他ssl.SSLContext调用将在当前进程中修补)

请注意,这实际上会禁用服务器证书验证。

ssl.SSLContext._windows_cert_stores = ("ROOT",)         # patch windows_cert_stores default to only include "ROOT" as "CA" is broken for you.
#ssl.SSLContext.load_default_certs = lambda s,x:None    # alternative, fully NOP load_default_certs to do nothing instead.
ctx = ssl.create_default_context()                      # create new sslcontext, not veryfing any certificates, hostnames.
ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE                         

hdr = {'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11'}
req = Request('https://' + url, headers=hdr)
x = urlopen( req , context=ctx).read() 
ssl.SSLContext._windows_cert_stores = ("ROOT","CA")   # UNDO PATCH
Run Code Online (Sandbox Code Playgroud)

我希望这些信息能够帮助您解决问题。祝你好运。