Python Urllib Urlopen在新行后不会返回?

时间:2013-06-17 23:44:02

标签: python parsing urlencode urllib urlopen

我正在尝试通过我尝试访问的API进行身份验证。我正在使用urllib.parse.urlencode来编码我的URL中的参数。我正在使用urllib.request.urlopen来获取内容。

这应该从服务器返回3个值,例如:

SID=AAAAAAAAAAA
LSID=BBBBBBBBBBB
AUTH=CCCCCCCCCCC

问题是它只返回第一个值和尾随换行符。

import urllib.request
import urllib.parse

Emailparamx = 'Email'
Emailparam = Emailparamx.encode('utf-8')
email = 'myemail@stackoverflow.com'
email = email.encode('utf-8')
Passwdparam = 'Passwd'
Passwdparam = Passwdparam.encode('utf-8')
password = 'hidden'
password = password.encode('utf-8')
Accounttypeparam = 'accountType'
Accounttypeparam = Accounttypeparam.encode('utf-8')
accounttype = 'GOOGLE'
accounttype = accounttype.encode('utf-8')
Serviceparam = 'service'
Serviceparam = Serviceparam.encode('utf-8')
service = 'adwords'
service = service.encode('utf-8')


url = 'https://accounts.google.com/ClientLogin?'
urlen = url.encode('utf-8')
data = [(Emailparamx, email), (Passwdparam, password),
        (Accounttypeparam, accounttype), (Serviceparam, service)]



auth = ''

dataurl = urllib.parse.urlencode(data)


accessurl = (url + "%s" % dataurl)

fh = urllib.request.urlopen(accessurl)

equals = '='
eqenc = equals.encode('utf-8')

try:
  msg = fh.readline().split(eqenc)
  print (msg)

然后msg打印

[b'SID', b'AAAAAAAAAAAAAAAAA\n']

我知道这是一些非常难看的代码,我在Python中已经有一周了。任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:0)

问题是你只调用readline一次,所以它只读一行。如果你想逐个阅读这些行,你必须在循环中调用readline直到完成:

while True:
    msg = fh.readline()
    if not msg:
        break
    msg = msg.split(eqenc)
    print(msg)

但是,在这里调用readline真的没有理由,因为任何类似文件的对象(包括urlopen对象)已经是一个可迭代的行,所以你可以这样做:

for msg in fh:
    print(msg)

与此同时,您的原始代码的try没有exceptfinally,只会引发SyntaxError。大概你想要这样的东西:

try:
    for msg in fh:
        print(msg)
except Exception as e:
    print('Exception: {}'.format(e))

虽然我们正在努力,但我们可以稍微简化您的代码。

如果你看the examples

  

以下是使用GET方法检索包含参数的网址的示例会话:

这正是你想要做的(除了最后一行)。你用编码字符串做的所有额外的东西不仅是不必要的,而且是不正确的。 UTF-8是错误的编码是用于URL的错误编码(因为所有字符串都是纯ASCII,所以你可以使用它); urlopen需要一个字符串而不是一个编码的字节字符串(尽管至少在CPython 3.0-3.3中,如果你给它正确编码的字节字符串,它就会起作用); urlencode可以使用字节字符串,但可能做不正确的事情(你想给它原始的Unicode,以便它可以正确引用);等

此外,您可能希望解码结果(以ASCII格式发送 - 对于更复杂的示例,您必须解析fh.getheader('Content-Type')或阅读API的文档),并删除换行。

您也可能希望构建一个可以在代码中使用的结构,而不是仅仅将其打印出来。例如,如果您将结果存储在login_info中,并且在稍后的请求中需要SID,那么它只是login_info['SID']

所以,让我们在函数中包装,然后调用该函数:

import urllib.request
import urllib.parse

def client_login(email, passwd, account_type, service):
    params = {'Email': email,
              'Passwd': passwd,
              'accountType': account_type,
              'service': service}
    qs = urllib.parse.urlencode(params)
    url = 'https://accounts.google.com/ClientLogin?'
    with urllib.request.urlopen(url + qs) as fh:
        return dict(line.strip().decode('ascii').split('=', 1) for line in fh)

email = 'myemail@stackoverflow.com'
password = 'hidden'
accounttype = 'GOOGLE'
service = 'adwords'
try:
    results = client_login(email, password, accounttype, service)
    for key, value in results.items():
        print('key "{}" is "{}".format(key, value))
except Exception as e:
    print('Exception: {}'.format(e))