Загрузить файл из Интернета в Python 3

Я создаю программу, которая будет загружать файл .jar(java) с веб-сервера, читая URL-адрес, указанный в файле .jad той же игры/приложения. Я использую Python 3.2.1

Мне удалось извлечь URL-адрес JAR файла из JAD файла (каждый JAD файл содержит URL-адрес в JAR файле), но, как вы можете себе представить, извлеченное значение является строкой типа().

Здесь соответствующая функция:

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-адрес хранится в строковом типе?

Ответ 1

Если вы хотите получить содержимое веб-страницы в переменной, просто read ответ urllib.request.urlopen:

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.urlretrieve:

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)

Но имейте в виду, что urlretrieve считается legacy и может стать устаревшим (не уверен, почему, хотя).

Таким образом, самый правильный способ сделать это - использовать функцию urllib.request.urlopen, чтобы вернуть файл -подобный объект, который представляет HTTP-ответ и копирует его в реальный файл, используя 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)

Если это кажется слишком сложным, вам может потребоваться упростить и сохранить всю загрузку в объекте bytes, а затем записать его в файл. Но это хорошо работает только для небольших файлов.

import urllib.request
...
# 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:
    data = response.read() # a `bytes` object
    out_file.write(data)

Можно извлекать .gz (и, возможно, другие форматы) сжатые данные "на лету", но такая операция, вероятно, требует, чтобы HTTP-сервер поддерживал произвольный доступ к файлу.

import urllib.request
import gzip
...
# Read the first 64 bytes of the file inside the .gz archive located at `url`
url = 'http://example.com/something.gz'
with urllib.request.urlopen(url) as response:
    with gzip.GzipFile(fileobj=response) as uncompressed:
        file_header = uncompressed.read(64) # a `bytes` object
        # Or do anything shown above using `uncompressed` instead of `response`.

Ответ 2

Я использую пакет requests всякий раз, когда хочу что-то связанное с HTTP-запросами, потому что его 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()

Ответ 4

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))