Python &引用;WindowsError:[错误5]访问被拒绝;使用urllib2

Python &引用;WindowsError:[错误5]访问被拒绝;使用urllib2,python,windows,urllib2,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 =

我在阅读带有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() )
完整回溯是:

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
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
文件“C:\Python27\lib\urllib2.py”,第154行,在urlopen中
返回opener.open(url、数据、超时)
文件“C:\Python27\lib\urllib2.py”,第431行,打开
响应=自身打开(请求,数据)
文件“C:\Python27\lib\urllib2.py”,第449行,处于打开状态
"开放",
文件“C:\Python27\lib\urllib2.py”,第409行,在调用链中
结果=func(*args)
文件“C:\Python27\lib\urllib2.py”,第1240行,https\u open
上下文=自身(上下文)
文件“C:\Python27\lib\urllib2.py”,第1166行,在do_open中
h=http_类(主机,超时=req.timeout,**http_连接参数)
文件“C:\Python27\lib\httplib.py”,第1258行,在_init中__
context=ssl.\u创建\u默认\u https\u上下文()
文件“C:\Python27\lib\ssl.py”,第440行,在create\u default\u上下文中
上下文。加载默认证书(目的)
文件“C:\Python27\lib\ssl.py”,第391行,在load\u default\u certs中
自行下载windows商店证书(商店名称、用途)
文件“C:\Python27\lib\ssl.py”,第378行,在\u load\u windows\u store\u certs中
对于证书、编码、enum_证书中的信任(storename):
WindowsError:[错误5]访问被拒绝
正如建议的那样,我试着从具有管理员权限的命令提示符下运行脚本,但它并没有解决这个问题


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

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

也就是说,您的windows证书存储似乎出了很大问题
httplib
尝试枚举指定证书存储
CA
证书颁发机构
(在
certmgr.msc
中显示为
中间证书颁发机构
)的证书时失败,但在
ROOT
中成功,后者是正常的受信任根证书存储(参见问题注释)。因此,我建议检查
certmgr:intermediate certificate authorities
中的所有证书,查看最近添加的证书和/或windows日志中的一般错误。 您的情况是,
urllib2
在内部调用
httplib
,然后尝试设置默认ssl上下文,并强制执行证书验证,作为这一过程的一部分,它通过调用
ssl.enum_certificates
枚举系统的受信任证书锚。此函数在
C
中作为
\u ssl\u enum\u certificates\u impl
并在内部调用winapi
CertOpenSystemStore
CertEnumCertificateSinstare
。对于证书存储位置
CA
,它只是在两个winapi调用中的一个调用中失败,访问被拒绝

如果您想进一步调试它,还可以尝试使用
LPTCSTR::'CA'
作为参数的
WINAPI:CertOpenSystemStore
,并尝试从这边调试它,尝试其他windows certstore管理工具和/或致电microsoft支持以获取支持

也有迹象表明,其他人在连接该api调用时遇到了类似问题,请参见谷歌:

如果您只是想在不修复根本原因的情况下使其正常工作,您可以尝试使用以下解决方法,临时修补
\u windows\u cert\u stores
,以不包括损坏的
CA
certstore,或完全禁用信任锚加载逻辑。(所有其他
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

我希望此信息将帮助您解决此问题。祝您好运。

使用Windows证书存储区时可能会出现几个问题。(我发现,如果从没有完整用户配置文件的服务帐户运行代码,这几乎是不可能的)。原因有些复杂,但不值得进一步讨论,因为有一个更简单的解决方案。如前所述,关闭SSL验证是一种解决方法,但如果您关心所提供证书的有效性,则可能不是最好的方法

只需使用一个自包含的证书存储就可以完全避免这种情况。对于Python来说,这是一个保持最新的包。可以很容易地从Python包访问它。对于大多数常见的Python发行版,这两个包都应该易于访问

import requests
from bs4 import BeautifulSoup

url = "www.google.com"
hdr = {
    'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11'}

r = requests.get('https://' + url, headers=hdr, verify=True)
soup = BeautifulSoup(r.text)
请注意,requests.get()将在无效地址、无法访问的站点和失败的证书验证上引发异常。因此,您希望准备捕获这些异常。当成功联系站点并验证证书,但未找到页面时(例如404错误),您不会得到异常。因此,在发出请求后,您还应该检查r.status_code==200。(会自动处理30个重定向,因此您不会将这些重定向视为状态代码,除非您告诉它不要遵循它们。)为了清晰起见,示例代码中省略了此检查


还请注意,此处没有明确引用certifi模块。如果已安装,请求将使用该模块。如果未安装,请求将使用更有限的内置根CA集。

您是否运行web2py的源版本,并且是否能够在we之外发出相同的请求b2py上下文(例如,来自标准Python shell或Python脚本)?从外观上看,Windows拒绝访问证书存储。您可以尝试安装吗