2012-03-28 90 views
1

我的代码存在问题。Python在一个循环中下载多个文件

#!/usr/bin/env python3.1 

import urllib.request; 

# Disguise as a Mozila browser on a Windows OS 
userAgent = 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'; 

URL = "www.example.com/img"; 
req = urllib.request.Request(URL, headers={'User-Agent' : userAgent}); 

# Counter for the filename. 
i = 0; 

while True: 
    fname = str(i).zfill(3) + '.png'; 
    req.full_url = URL + fname; 

    f = open(fname, 'wb'); 

    try: 
     response = urllib.request.urlopen(req); 
    except: 
     break; 
    else: 
     f.write(response.read()); 
     i+=1; 
     response.close(); 
    finally: 
     f.close(); 

当我创建urllib.request.Request对象(称为req)时,问题似乎出现了。我用一个不存在的URL创建它,但后来我改变了它应该是的网址。我这样做,以便我可以使用相同的urllib.request.Request对象,而不必在每次迭代中创建新的。在python中可能有一种机制可以完成,但我不确定它是什么。

EDIT 错误信息是:

>>> response = urllib.request.urlopen(req); 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "/usr/lib/python3.1/urllib/request.py", line 121, in urlopen 
    return _opener.open(url, data, timeout) 
    File "/usr/lib/python3.1/urllib/request.py", line 356, in open 
    response = meth(req, response) 
    File "/usr/lib/python3.1/urllib/request.py", line 468, in http_response 
    'http', request, response, code, msg, hdrs) 
    File "/usr/lib/python3.1/urllib/request.py", line 394, in error 
    return self._call_chain(*args) 
    File "/usr/lib/python3.1/urllib/request.py", line 328, in _call_chain 
    result = func(*args) 
    File "/usr/lib/python3.1/urllib/request.py", line 476, in http_error_default 
    raise HTTPError(req.full_url, code, msg, hdrs, fp) 
urllib.error.HTTPError: HTTP Error 403: Forbidden 

编辑2:我的解决方案如下。

import urllib.request; 

# Disguise as a Mozila browser on a Windows OS 
userAgent = 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'; 

# Counter for the filename. 
i = 0; 

while True: 
    fname = str(i).zfill(3) + '.png'; 
    URL = "www.example.com/img" + fname; 

    f = open(fname, 'wb'); 

    try: 
     req = urllib.request.Request(URL, headers={'User-Agent' : userAgent}); 
     response = urllib.request.urlopen(req); 
    except: 
     break; 
    else: 
     f.write(response.read()); 
     i+=1; 
     response.close(); 
    finally: 
     f.close(); 
+1

什么是错误信息?此外,python不需要分号结束一行。 – Dikei 2012-03-28 02:37:03

+0

我已添加错误消息。我知道我不需要分号但我更愿意添加它们。网址和文件存在。唯一的问题是,我用无效的url创建req对象,然后在使用req之前更正了url。这似乎是导致错误。 – s5s 2012-03-28 02:41:08

+0

是的。该网址是有效的。这就是它导致问题的原因。我也可以访问url,wget它并用Python下载它,如果我没有循环,所以我在创建它时将req对象中的url设置为正确。 – s5s 2012-03-28 02:44:11

回答

5

urllib2是适合于小脚本,只需要做一个或两个网络的互动,但如果你正在做更多的工作,你可能会发现,无论是urllib3,或requests(这不是巧合是建立在前者),可能更适合您的需求。你的具体的例子可能看起来像:

from itertools import count 
import requests 

HEADERS = {'user-agent': 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'} 
URL = "http://www.example.com/img%03d.png" 

# with a session, we get keep alive 
session = requests.session() 

for n in count(): 
    full_url = URL % n 
    ignored, filename = URL.rsplit('/', 1) 

    with file(filename, 'wb') as outfile: 
     response = session.get(full_url, headers=HEADERS) 
     if not response.ok: 
      break 
     outfile.write(response.content) 

编辑:如果你可以使用普通的HTTP身份验证(其中403 Forbidden响应强烈建议),那么你可以添加到requests.getauth参数,如:

response = session.get(full_url, headers=HEADERS, auth=('username','password)) 
+0

我喜欢这个答案,而不是仅仅修复一个OP的错误,你实际上展示了一个更好的方法,从而解决了他和其他人的问题。 – Mig 2012-03-28 03:07:47

+0

它知道这是从原来的帖子很长一段时间,但文件名应读取'忽略,文件名= full_url.rsplit('/',1)'而不是'忽略,文件名= URL.rsplit('/',1 )'。否则,文件名将是'img%03d.png'。 – Marius 2016-11-14 21:07:24

-2

当您收到一个异常不要打破:也许应该,因为我知道它会工作在开始这样做了。更改

except: 
    break 

except: 
    #Probably should log some debug information here. 
    pass 

这将跳过所有有问题的请求,这样一个不带下来的全过程。

+0

这将大大改变逻辑。他很可能不希望永远循环。 – SingleNegationElimination 2012-03-28 02:49:15

+0

我正在使用异常作为终止循环的方式。通过将导致无限循环。我不知道有多少文件,所以我正在下载,直到遇到异常。 – s5s 2012-03-28 02:50:08

+0

虽然不会阻止服务器进行调节。 – 2012-03-28 02:50:18

相关问题