代码之家  ›  专栏  ›  技术社区  ›  PabloG

在下载Python之前获取文件的大小

  •  38
  • PabloG  · 技术社区  · 18 年前

    我正在从web服务器下载整个目录。它工作正常,但我不知道如何在下载之前获得文件大小,以比较它是否在服务器上更新。这可以像从FTP服务器下载文件一样完成吗?

    import urllib
    import re
    
    url = "http://www.someurl.com"
    
    # Download the page locally
    f = urllib.urlopen(url)
    html = f.read()
    f.close()
    
    f = open ("temp.htm", "w")
    f.write (html)
    f.close()
    
    # List only the .TXT / .ZIP files
    fnames = re.findall('^.*<a href="(\w+(?:\.txt|.zip)?)".*$', html, re.MULTILINE)
    
    for fname in fnames:
        print fname, "..."
    
        f = urllib.urlopen(url + "/" + fname)
    
        #### Here I want to check the filesize to download or not #### 
        file = f.read()
        f.close()
    
        f = open (fname, "w")
        f.write (file)
        f.close()
    

    示例:

    Local Size  Server Size
     2.223.533  2.115.516
       664.603    662.121
    

    7 回复  |  直到 13 年前
        1
  •  36
  •   Jonathan Works    18 年前

    我复制了您看到的内容:

    import urllib, os
    link = "http://python.org"
    print "opening url:", link
    site = urllib.urlopen(link)
    meta = site.info()
    print "Content-Length:", meta.getheaders("Content-Length")[0]
    
    f = open("out.txt", "r")
    print "File on disk:",len(f.read())
    f.close()
    
    
    f = open("out.txt", "w")
    f.write(site.read())
    site.close()
    f.close()
    
    f = open("out.txt", "r")
    print "File on disk after download:",len(f.read())
    f.close()
    
    print "os.stat().st_size returns:", os.stat("out.txt").st_size
    

    输出如下:

    opening url: http://python.org
    Content-Length: 16535
    File on disk: 16535
    File on disk after download: 16535
    os.stat().st_size returns: 16861
    

    我做错了什么?os.stat().st_size是否返回了正确的大小?


    好的,我知道问题出在哪里了:

    import urllib, os
    link = "http://python.org"
    print "opening url:", link
    site = urllib.urlopen(link)
    meta = site.info()
    print "Content-Length:", meta.getheaders("Content-Length")[0]
    
    f = open("out.txt", "rb")
    print "File on disk:",len(f.read())
    f.close()
    
    
    f = open("out.txt", "wb")
    f.write(site.read())
    site.close()
    f.close()
    
    f = open("out.txt", "rb")
    print "File on disk after download:",len(f.read())
    f.close()
    
    print "os.stat().st_size returns:", os.stat("out.txt").st_size
    

    这将产生:

    $ python test.py
    opening url: http://python.org
    Content-Length: 16535
    File on disk: 16535
    File on disk after download: 16535
    os.stat().st_size returns: 16535
    

    确保打开这两个文件进行二进制读/写。

    // open for binary write
    open(filename, "wb")
    // open for binary read
    open(filename, "rb")
    
        2
  •  26
  •   Rizwan rhys    4 年前

    info() ,您可以获取检索到的文档的各种信息。抓取当前Google徽标的示例:

    >>> import urllib
    >>> d = urllib.urlopen("http://www.google.co.uk/logos/olympics08_opening.gif")
    >>> print d.info()
    
    Content-Type: image/gif
    Last-Modified: Thu, 07 Aug 2008 16:20:19 GMT  
    Expires: Sun, 17 Jan 2038 19:14:07 GMT 
    Cache-Control: public 
    Date: Fri, 08 Aug 2008 13:40:41 GMT 
    Server: gws 
    Content-Length: 20172 
    Connection: Close
    

    这是一个dict,所以要得到文件的大小,你需要 urllibobject.info()['Content-Length']

    print f.info()['Content-Length']
    

    要获取本地文件的大小(用于比较),可以使用os.stat()命令:

    os.stat("/the/local/file.zip").st_size
    
        3
  •  9
  •   ccpizza    9 年前

    A. requests -基于HEAD而不是GET的解决方案(还打印HTTP头):

    #!/usr/bin/python
    # display size of a remote file without downloading
    
    from __future__ import print_function
    import sys
    import requests
    
    # number of bytes in a megabyte
    MBFACTOR = float(1 << 20)
    
    response = requests.head(sys.argv[1], allow_redirects=True)
    
    print("\n".join([('{:<40}: {}'.format(k, v)) for k, v in response.headers.items()]))
    size = response.headers.get('content-length', 0)
    print('{:<40}: {:.2f} MB'.format('FILE SIZE', int(size) / MBFACTOR))
    

    $ python filesize-remote-url.py https://httpbin.org/image/jpeg
    ...
    Content-Length                          : 35588
    FILE SIZE (MB)                          : 0.03 MB
    
        4
  •  7
  •   Jonathan Works    18 年前

    文件大小作为内容长度标头发送。以下是如何使用urllib获取它:

    >>> site = urllib.urlopen("http://python.org")
    >>> meta = site.info()
    >>> print meta.getheaders("Content-Length")
    ['16535']
    >>>
    
        5
  •  6
  •   Jonathan Works    18 年前

    另外,如果您连接的服务器支持它,请查看 Etags 和 If-Modified-Since 和 If-None-Match

    使用这些将利用Web服务器的缓存规则,并将返回 304 Not Modified

        6
  •  3
  •   yukashima huksay    8 年前

    对于python3(在3.5上测试)方法,我建议:

    with urlopen(file_url) as in_file, open(local_file_address, 'wb') as out_file:
        print(in_file.getheader('Content-Length'))
        out_file.write(response.read())
    
        7
  •  1
  •   Madhusudhan    12 年前

    在Python3中:

    >>> import urllib.request
    >>> site = urllib.request.urlopen("http://python.org")
    >>> print("FileSize: ", site.length)
    
        8
  •  0
  •   Rizwan rhys    4 年前

    @关于本地/服务器文件大小差异的PabloG

    以下是可能发生的原因的高级说明性解释:

    它取决于底层文件系统及其对数据的操作方式。 正如您在Windows中看到的那样,格式化闪存驱动器时,会要求您提供“块/群集大小”,大小会有所不同[512b-8kb]。 当文件写入磁盘时,它存储在磁盘块的“排序链表”中。 当某个块用于存储文件的一部分时,其他文件内容不会存储在同一个blok中,因此即使该块没有占用整个块空间,该块也会被其他文件呈现为不可用。

    例子: 当文件系统被划分为512b块时,我们需要存储600b文件,两个块将被占用。第一个块将被充分利用,而第二个块将只有88b被利用,剩余的(512-88)b将不可用,导致“磁盘上的文件大小”为1024b。 这就是为什么Windows对“文件大小”和“磁盘大小”有不同的标记。

    有不同的利弊;缺点是FS块越小/越大,所以在使用文件系统之前,请进行更好的研究。