【问题标题】:Download files given their url and store the filename same as in content disposition下载给定 url 的文件并将文件名存储在内容配置中
【发布时间】:2014-01-10 20:14:43
【问题描述】:

我从How to download a file using python in a 'smarter' way?得到这个代码?

但它会抛出一个错误:

   in download
   r.close()
   UnboundLocalError: local variable 'r' referenced before assignment

我还想添加一个条件,即要下载的文件只能是 pdf。

import urllib2
import shutil
import urlparse
import os


def download(url, fileName=None):
    def getFileName(url,openUrl):
        if 'Content-Disposition' in openUrl.info():
            # If the response has Content-Disposition, try to get filename from it
            cd = dict(map(lambda x: x.strip().split('=') if '=' in x else (x.strip(),''),openUrl.info()['Content-Disposition'].split(';')))
            if 'filename' in cd:
                filename = cd['filename'].strip("\"'")
                if filename: return filename
         # if no filename was found above, parse it out of the final URL.
    return os.path.basename(urlparse.urlsplit(openUrl.url)[2])

    req = urllib2.Request(url)
    try:
        r = urllib2.urlopen(req)
    except urllib2.HTTPError, e:
            print e.fp.read()
    try:
            fileName = fileName or getFileName(url,r)
            with open(fileName, 'wb') as f:
                 shutil.copyfileobj(r,f)
    finally:
            r.close()

download('http://www.altria.com/Documents/Altria_10Q_Filed10242013.pdf#?page=24')

这完全适用于 url:http://www.gao.gov/new.items/d04641.pdf 所以我的问题是为什么它不适用于某些 url,但对上面提到的 url 完全有效。

【问题讨论】:

  • 您已经描述了您的问题,并且包含了一个示例程序。那挺好的。您仍然缺少 SO 帖子的关键要素:一个问题。 SO 是一个问答网站。像你这样的读者提出问题,而其他读者试图回答这些问题。你有什么问题?

标签: python


【解决方案1】:

这是一个范围问题。

在函数的开头,定义:

    r=None

然后,不要调用 r.close(),而是执行以下操作:

    if r:
      r.close()

【讨论】:

  • 投反对票的人可以发表评论吗?原始代码尝试在“finally”块中调用 r 上的 close(),即使它可能尚未初始化。确定它有什么问题?原始发布者试图优雅地处理错误,如果他/她尝试访问无法访问的 URL,这可以解决该问题。
  • 我没有否决它,但您的建议将以静默失败告终。最后的问题不是关于如何消除错误,而是关于为什么会发生错误。也就是说,您的回答当然不值得投反对票。有一些代表。
【解决方案2】:

发生的情况是第一个异常被捕获:except urllib2.HTTPError 但代码继续,即使 r 未定义(因为发生了异常)

我认为您想在try/except 块中使用else 子句,仅在r = urllib2.urlopen(req) 成功时才执行其余代码:

def download(url, fileName=None):
    def getFileName(url,openUrl):
        if 'Content-Disposition' in openUrl.info():
            # If the response has Content-Disposition, try to get filename from it
            cd = dict(map(lambda x: x.strip().split('=') if '=' in x else (x.strip(),''),openUrl.info()['Content-Disposition'].split(';')))
            if 'filename' in cd:
                filename = cd['filename'].strip("\"'")
                if filename: return filename
        # if no filename was found above, parse it out of the final URL.
        return os.path.basename(urlparse.urlsplit(openUrl.url)[2])

    req = urllib2.Request(url)
    try:
        r = urllib2.urlopen(req)
    except urllib2.HTTPError, e:
        print e.fp.read()
    else:
        try:
            fileName = fileName or getFileName(url,r)
            with open(fileName, 'wb') as f:
                 shutil.copyfileobj(r,f)
        finally:
            r.close()

【讨论】:

    【解决方案3】:

    我假设它会打印出一条错误消息,说明 urllib2.urlopen(req) 在给您未绑定的本地错误之前是如何失败的。如果是这样,请在print e.fp.read() 之后的行中添加raise,您的问题看起来会有所不同。

    【讨论】:

    • 它说:urllib2.HTTPError:HTTP 错误 403:禁止
    • 那是你的问题。服务器拒绝您的脚本访问该页面。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-11-12
    • 1970-01-01
    • 1970-01-01
    • 2019-11-25
    • 1970-01-01
    • 2016-12-01
    • 2011-11-12
    相关资源
    最近更新 更多