我正在创建一个程序,该程序将通过读取同一游戏/应用程序的.jad文件中指定的URL从Web服务器下载.jar(java)文件。我正在使用Python 3.2.1

我设法从JAD文件中提取JAR文件的URL(每个JAD文件都包含该JAR文件的URL),但是正如您想象的那样,提取的值为type()字符串。

这里是相关的功能:

def downloadFile(URL=None):
    import httplib2
    h = httplib2.Http(".cache")
    resp, content = h.request(URL, "GET")
    return content

downloadFile(URL_from_file)


但是我总是收到一个错误,说上面函数的类型必须是字节,不是字符串。我尝试使用URL.encode('utf-8')和字节(URL,encoding ='utf-8'),但是我总是会遇到相同或相似的错误。

所以基本上我的问题是,当URL以字符串类型存储时,如何从服务器下载文件?

评论

@alvas,为此赏金吗?答题者仍然(并且相当)活跃在SO上。为什么不只是添加评论并询问呢?

Cos持续时间考验的好答案值得嘉奖。另外,我们应该对其他许多问题开始这样做,以检查今天的答案是否相关。尤其是当SO答案的排序非常疯狂时,有时过时甚至最差的答案会排在首位。

#1 楼

如果要将网页的内容转换为变量,只需read的响应即可:
import urllib.request
...
url = 'http://example.com/'
response = urllib.request.urlopen(url)
data = response.read()      # a `bytes` object
text = data.decode('utf-8') # a `str`; this step can't be used if data is binary


下载和保存文件的最简单方法是使用urllib.request.urlopen函数:
import urllib.request
...
# Download the file from `url` and save it locally under `file_name`:
urllib.request.urlretrieve(url, file_name)


import urllib.request
...
# Download the file from `url`, save it in a temporary directory and get the
# path to it (e.g. '/tmp/tmpb48zma.txt') in the `file_name` variable:
file_name, headers = urllib.request.urlretrieve(url)

但是请记住,urllib.request.urlretrieve被认为是旧有的并且可能会被弃用(虽然不确定为什么)。这样做是使用urlretrieve函数返回表示HTTP响应的类似文件的对象,然后使用urllib.request.urlopen将其复制到真实文件中。更简单,将整个下载内容存储在一个shutil.copyfileobj对象中,然后将其写入文件中。但是,这仅适用于小文件。支持随机访问文件。
import urllib.request
import shutil
...
# Download the file from `url` and save it locally under `file_name`:
with urllib.request.urlopen(url) as response, open(file_name, 'wb') as out_file:
    shutil.copyfileobj(response, out_file)


评论


您可以使用response.info()。get_param('charset','utf-8')代替对utf-8进行硬编码,以从Content-Type标头中获取字符编码

– jfs
2014年3月19日在17:54

@OlehPrypin为什么outfile.write(data)仅适用于小文件?

– Startec
15年5月18日在21:56

“ urlretrieve被认为是遗留的,可能已被弃用”,您从何处得到这个想法?

– Corey Goldberg
15年6月16日在11:16

@Corey:直接从文档开始:“ 21.6.24。旧版接口以下函数和类是从Python 2模块urllib(与urllib2相对)中移植的。将来某些时候它们可能会过时。 ...而且我同意Oleh的“不确定原因”

–cfi
15年9月29日在13:20

@Oleh Prypin如果我使用urllib.request.urlopen(url)作为响应,使用open(file_name,'wb')作为out_file:shutil.copyfileobj(response,out_file)那么如何在catch语句中找到HTTP状态代码知道找不到文件?

– Robert Achmann
17年11月8日17:46



#2 楼

每当我想要与HTTP请求相关的内容时,我都会使用requests软件包,因为它的API很容易开头:
首先安装requests

$ pip install requests


然后输入代码:

from requests import get  # to make GET request


def download(url, file_name):
    # open in binary mode
    with open(file_name, "wb") as file:
        # get request
        response = get(url)
        # write to file
        file.write(response.content)


#3 楼

我希望我理解正确的问题,即:当URL以字符串类型存储时如何从服务器下载文件?

我使用以下代码下载文件并将其保存在本地:

import requests

url = 'https://www.python.org/static/img/python-logo.png'
fileName = 'D:\Python\dwnldPythonLogo.png'
req = requests.get(url)
file = open(fileName, 'wb')
for chunk in req.iter_content(100000):
    file.write(chunk)
file.close()


评论


嗨,我也使用相同类型的代码下载文件,但是有些时候我遇到了异常-例如'charmap'编解码器无法编码字符'\ u010c'.....

–乔伊森
18年2月24日在13:00

#4 楼

您可以使用wget,它是流行的下载shell工具。 https://pypi.python.org/pypi/wget
这是最简单的方法,因为它不需要打开目标文件。这是一个例子。

import wget
url = 'https://i1.wp.com/python3.codes/wp-content/uploads/2015/06/Python3-powered.png?fit=650%2C350'  
wget.download(url, '/Users/scott/Downloads/cat4.jpg') 


#5 楼

在这里,我们可以在Python3中使用urllib的Legacy接口:

以下函数和类是从Python 2模块urllib(与urllib2相对)移植的。它们可能会在将来的某个时刻被弃用。

示例(2行代码):

import urllib.request

url = 'https://www.python.org/static/img/python-logo.png'
urllib.request.urlretrieve(url, "logo.png")


#6 楼

是的,绝对请求是在与HTTP请求相关的东西中使用的好软件包。但是我们需要注意传入数据的编码类型,下面是一个说明差异的示例。


from requests import get

# case when the response is byte array
url = 'some_image_url'

response = get(url)
with open('output', 'wb') as file:
    file.write(response.content)


# case when the response is text
# Here unlikely if the reponse content is of type **iso-8859-1** we will have to override the response encoding
url = 'some_page_url'

response = get(url)
# override encoding by real educated guess as provided by chardet
r.encoding = r.apparent_encoding

with open('output', 'w', encoding='utf-8') as file:
    file.write(response.content)



#7 楼

动机

有时候,我们想要获取图片,而无需将其下载到真实文件中,

,即下载数据并将其保存在内存中。

例如,如果我使用机器学习方法,请训练一个可以识别带有数字(条形码)图像的模型。因此我可以使用模型来识别它,

,而且我不想将这些图片保存在磁盘驱动器上,

,那么您可以尝试以下方法来帮助您将下载的数据保留在内存中。示例

import requests
from io import BytesIO
response = requests.get(url)
with BytesIO as io_obj:
    for chunk in response.iter_content(chunk_size=4096):
        io_obj.write(chunk)


#8 楼

如果您使用的是Linux,则可以通过python shell使用Linux的wget模块。这是一个示例代码片段
import os
url = 'http://www.example.com/foo.zip'
os.system('wget %s'%url)


#9 楼

from urllib import request

def get(url):
    with request.urlopen(url) as r:
        return r.read()


def download(url, file=None):
    if not file:
        file = url.split('/')[-1]
    with open(file, 'wb') as f:
        f.write(get(url))