2

以下python curl调用有以下成功结果:

>>> import subprocess
>>> args = [
        'curl',
        '-H', 'X-Requested-With: Demo',
        'https://username:password@qualysapi.qualys.com/qps/rest/3.0/count/was/webapp' ] 
>>> xml_output = subprocess.check_output(args).decode('utf-8')
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
138   276    0   276    0     0    190      0 --:--:--  0:00:01 --:--:--   315
>>> xml_output
u'<?xml version="1.0" encoding="UTF-8"?>\n<ServiceResponse xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://qualysapi.qualys.com/qps/xsd/3.0/was/webapp.xsd">\n<responseCode>SUCCESS</responseCode>\n  <count>33</count>\n</ServiceResponse>'

不幸的是,这个调用没有成功转换为 urllib2。我收到一个不同的 XML 响应,指出用户没有提供授权凭据:

>>> import urllib2
>>> # Create a password manager.
... password_mgr = urllib2.HTTPPasswordMgrWithDefaultRealm()
>>> # Add the username and password.
... top_level_url = 'https://qualysapi.qualys.com'
>>> password_mgr.add_password(None, top_level_url, username, password)
>>> handler = urllib2.HTTPBasicAuthHandler(password_mgr)
>>> opener = urllib2.build_opener(handler)
>>> urllib2.install_opener(opener)
>>> headers = {'X-Requested-With':'Demo'}
>>> uri = 'https://qualysapi.qualys.com/qps/rest/3.0/count/was/webapp'
>>> req = urllib2.Request(uri,None,headers)
>>> result = urllib2.urlopen(req)
>>> result
'<ServiceResponse xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://qualysapi.qualys.com/qps/xsd/3.0/was/webapp.xsd">\n  <responseCode>INVALID_CREDENTIALS</responseCode>\n  <responseErrorDetails>\n    <errorMessage>User did not supply any authentication headers</errorMessage>\n  </responseErrorDetails>\n</ServiceResponse>'

顺便说一句,我收到与 httplib 相同的错误消息:

>>> import httplib, base64
>>> auth = 'Basic ' + string.strip(base64.encodestring(username + ':' + password))
>>> h = httplib.HTTPSConnection('qualysapi.qualys.com')
>>> h.request("GET", "/qps/rest/3.0/count/was/webapp/")
>>> r1 = h.getresponse()
>>> print r1.status, r1.reason
200 OK
>>> data1 = r1.read()
>>> data1
'<ServiceResponse xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://qualysapi.qualys.com/qps/xsd/3.0/was/webapp.xsd">\n  <responseCode>INVALID_CREDENTIALS</responseCode>\n  <responseErrorDetails>\n    <errorMessage>User did not supply any authentication headers</errorMessage>\n  </responseErrorDetails>\n</ServiceResponse>'

我知道 httplib 和 urllib2 可能只有在 SSL 被编译成套接字时才能工作,而 SSL 被编译成套接字的模块。事实上,我已经成功地将 urllib2 用于不同 API 上的其他调用。问题与这一特定 API 无关。

urllib2(和 httplib)与 curl 有什么不同?

注意:所有示例中使用的用户名和密码都相同。

更新:

问题出在基本身份验证密码管理器上。当我手动添加基本授权标头时, urllib2 cal 工作:

>>> import base64
>>> base64string = base64.encodestring('%s:%s' % (username, password))[:-1]
>>> req.add_header("Authorization", "Basic %s" % base64string)
>>> # Make request to fetch url.
... result = urllib2.urlopen(req)
>>> # Read xml results.
... xml = result.read()
>>> xml
'<?xml version="1.0" encoding="UTF-8"?>\n<ServiceResponse xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://qualysapi.qualys.com/qps/xsd/3.0/was/webapp.xsd">\n  <responseCode>SUCCESS</responseCode>\n  <count>33</count>\n</ServiceResponse>'
4

2 回答 2

3

来自Python urllib2 基本身份验证问题

问题 [是] Python 库,根据 HTTP 标准,首先发送一个未经身份验证的请求,然后只有当它被 401 重试回答时,才会发送正确的凭据。如果 ... 服务器不执行“完全标准的身份验证”,那么这些库将无法工作。

此特定 API 在第一次尝试时不会以 401 Unauthorized 响应,它会以包含消息的 XML 响应进行响应,其中包含未使用 200 OK 响应代码发送凭据的消息。

于 2012-03-02T17:19:07.803 回答
0

尝试设置用户代理,也许这就是干扰。urllib2 将自己标识为Python-urllib/x.y(其中 x 和 y 是 Python 版本的主要和次要版本号,例如Python-urllib/2.5)这可能是导致站点阻止您的请求的原因。看看他们的 robots.txt .. 这是一个设置用户代理的示例,以便您的脚本被识别为浏览器:

import urllib
import urllib2

url = 'http://www.someserver.com/cgi-bin/register.cgi'
user_agent = 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'
headers = { 'User-Agent' : user_agent }
req = urllib2.Request(url, data, headers)
response = urllib2.urlopen(req)
the_page = response.read()
于 2012-02-29T07:47:27.403 回答