在Python中从HTTP服务器下载文件

5
使用urllib2,我们可以从Web服务器获取http响应。如果该服务器仅持有文件列表,我们可以解析文件并逐个下载。但是,我不确定解析文件的最简单、最pythonic的方法是什么。
当您通过urllib2的urlopen()方法获得通用文件服务器列表的完整http响应时,如何整洁地下载每个文件?

你能否给我们提供“文件列表”中三到四行样本源代码,这样我们就可以看到可能涉及的额外格式化类型? - Hugh Bothwell
7个回答

12

使用urllib2可能可以获取文件列表。但对于下载大量二进制文件,PycURL http://pycurl.sourceforge.net/ 是更好的选择。这适用于我的基于IIS的文件服务器:

import re
import urllib2
import pycurl

url = "http://server.domain/"
path = "path/"
pattern = '<A HREF="/%s.*?">(.*?)</A>' % path

response = urllib2.urlopen(url+path).read()

for filename in re.findall(pattern, response):
    with open(filename, "wb") as fp:
        curl = pycurl.Curl()
        curl.setopt(pycurl.URL, url+path+filename)
        curl.setopt(pycurl.WRITEDATA, fp)
        curl.perform()
        curl.close()

我没有进行速度测试,但也可以使用BeautifulSoup获取所有的<a>,然后从中提取.text - boldnik

9
您可以使用urllib.urlretrieve(在Python 3.x中:urllib.request.urlretrieve):
import urllib
urllib.urlretrieve('http://site.com/', filename='filez.txt')

这应该可以工作:)

下面是一段使用urllib完成同样功能的函数:

def download(url):
    webFile = urllib.urlopen(url)
    localFile = open(url.split('/')[-1], 'w')
    localFile.write(webFile.read())
    webFile.close()
    localFile.close()

3
你能保证所请求的URL是一个目录列表吗?如果是,你能保证目录列表的格式吗?
如果可以的话,您可以使用 lxml 解析返回的文档,并找到所有保存文件路径的元素,然后遍历这些元素并下载每个文件。

1
有些人喜欢使用pyquery ;) - Esteban Feldman

2
  1. 下载索引文件。

    如果文件非常大,则可以分批处理;否则,将整个文件读入内存可能更容易。

  2. 提取所需文件列表。

    如果列表是xml或html格式,请使用适当的解析器;否则,如果需要进行大量字符串处理,请使用正则表达式;否则,使用简单的字符串方法。

    同样,您可以一次性解析所有内容,也可以渐进式地解析。 渐进式处理效率更高、更优雅, 但除非您正在处理数万行数据, 否则通常不会太关键。

  3. 对于每个文件,下载并将其保存到文件中。

    如果您想尝试加速下载速度,可以尝试运行多个下载线程;

    另一种(明显更快)方法可能是 将工作委托给专用下载程序,例如 Aria2 http://aria2.sourceforge.net/ - 请注意,Aria2 可以作为服务运行,并通过 XMLRPC 进行控制,详情请参见 http://sourceforge.net/apps/trac/aria2/wiki/XmlrpcInterface#InteractWitharia2UsingPython


2
我的建议是使用BeautifulSoup(一种HTML/XML解析器)来解析页面上的文件列表。然后,pycURL肯定会很有用。
另一种方法是,在获取文件列表之后,可以使用urllib.urlretrieve类似于wget的方式将文件简单地下载到您的文件系统中的位置。

2

这是一种非传统的方式,但尽管它能够起作用。

fPointer = open(picName, 'wb')
self.curl.setopt(self.curl.WRITEFUNCTION, fPointer.write) 


urllib.urlretrieve(link, picName) - correct way

1

这是一个未经测试的解决方案:

import urllib2

response = urllib2.urlopen('http://server.com/file.txt')
urls = response.read().replace('\r', '').split('\n')

for file in urls:
  print 'Downloading ' + file

  response = urllib2.urlopen(file)

  handle = open(file, 'w')
  handle.write(response.read())
  handle.close()

这是未经测试的,可能不会起作用。这是假设您在另一个文件中有一个实际的文件列表。祝你好运!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接