programing tip

Python을 사용하여 HTTP를 통해 파일을 다운로드하려면 어떻게해야합니까?

itbloger 2020. 9. 29. 07:23
반응형

Python을 사용하여 HTTP를 통해 파일을 다운로드하려면 어떻게해야합니까?


일정에 따라 웹 사이트에서 MP3를 다운로드 한 다음 iTunes에 추가 한 팟 캐스트 XML 파일을 빌드 / 업데이트하는 데 사용하는 작은 유틸리티가 있습니다.

XML 파일을 생성 / 업데이트하는 텍스트 처리는 Python으로 작성됩니다. .bat그러나 Windows 파일 내에서 wget을 사용 하여 실제 MP3를 다운로드합니다. 그래도 전체 유틸리티를 Python으로 작성하고 싶습니다.

나는 실제로 파이썬에서 파일을 다운로드하는 방법을 찾기 위해 고심했고, 그래서 wget.

그렇다면 Python을 사용하여 파일을 어떻게 다운로드합니까?


Python 2에서는 표준 라이브러리와 함께 제공되는 urllib2를 사용합니다.

import urllib2
response = urllib2.urlopen('http://www.example.com/')
html = response.read()

이것은 오류 처리를 제외한 라이브러리를 사용하는 가장 기본적인 방법입니다. 헤더 변경과 같은 더 복잡한 작업을 수행 할 수도 있습니다. 문서는 여기 에서 찾을 수 있습니다.


하나 더, 사용 urlretrieve:

import urllib
urllib.urlretrieve ("http://www.example.com/songs/mp3.mp3", "mp3.mp3")

(Python 3 이상 사용 import urllib.requesturllib.request.urlretrieve)

"진행률 표시 줄"이있는 또 다른

import urllib2

url = "http://download.thinkbroadband.com/10MB.zip"

file_name = url.split('/')[-1]
u = urllib2.urlopen(url)
f = open(file_name, 'wb')
meta = u.info()
file_size = int(meta.getheaders("Content-Length")[0])
print "Downloading: %s Bytes: %s" % (file_name, file_size)

file_size_dl = 0
block_sz = 8192
while True:
    buffer = u.read(block_sz)
    if not buffer:
        break

    file_size_dl += len(buffer)
    f.write(buffer)
    status = r"%10d  [%3.2f%%]" % (file_size_dl, file_size_dl * 100. / file_size)
    status = status + chr(8)*(len(status)+1)
    print status,

f.close()

2012 년에는 python 요청 라이브러리 사용

>>> import requests
>>> 
>>> url = "http://download.thinkbroadband.com/10MB.zip"
>>> r = requests.get(url)
>>> print len(r.content)
10485760

당신은 pip install requests그것을 얻기 위해 달릴 수 있습니다 .

API가 훨씬 간단하기 때문에 요청은 대안에 비해 많은 이점이 있습니다. 인증을해야하는 경우 특히 그렇습니다. urllib와 urllib2는이 경우 매우 직관적이지 않고 고통 스럽습니다.


2015-12-30

사람들은 진행률 표시 줄에 감탄을 표했습니다. 멋지네요. 현재 다음과 같은 여러 가지 기성 솔루션이 있습니다 tqdm.

from tqdm import tqdm
import requests

url = "http://download.thinkbroadband.com/10MB.zip"
response = requests.get(url, stream=True)

with open("10MB", "wb") as handle:
    for data in tqdm(response.iter_content()):
        handle.write(data)

이것은 본질적으로 30 개월 전에 설명한 @kvance 구현입니다.


import urllib2
mp3file = urllib2.urlopen("http://www.example.com/songs/mp3.mp3")
with open('test.mp3','wb') as output:
  output.write(mp3file.read())

wb에서이 open('test.mp3','wb')파일을 열고 (기존의 모든 파일을 삭제합니다) 당신은 단지 텍스트 대신 그것으로 데이터를 저장할 수 있도록 바이너리 모드로.


파이썬 3

  • urllib.request.urlopen

    import urllib.request
    response = urllib.request.urlopen('http://www.example.com/')
    html = response.read()
    
  • urllib.request.urlretrieve

    import urllib.request
    urllib.request.urlretrieve('http://www.example.com/songs/mp3.mp3', 'mp3.mp3')
    

파이썬 2


wget 모듈 사용 :

import wget
wget.download('url')

Python 2/3 용 PabloG 코드의 개선 된 버전 :

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import ( division, absolute_import, print_function, unicode_literals )

import sys, os, tempfile, logging

if sys.version_info >= (3,):
    import urllib.request as urllib2
    import urllib.parse as urlparse
else:
    import urllib2
    import urlparse

def download_file(url, dest=None):
    """ 
    Download and save a file specified by url to dest directory,
    """
    u = urllib2.urlopen(url)

    scheme, netloc, path, query, fragment = urlparse.urlsplit(url)
    filename = os.path.basename(path)
    if not filename:
        filename = 'downloaded.file'
    if dest:
        filename = os.path.join(dest, filename)

    with open(filename, 'wb') as f:
        meta = u.info()
        meta_func = meta.getheaders if hasattr(meta, 'getheaders') else meta.get_all
        meta_length = meta_func("Content-Length")
        file_size = None
        if meta_length:
            file_size = int(meta_length[0])
        print("Downloading: {0} Bytes: {1}".format(url, file_size))

        file_size_dl = 0
        block_sz = 8192
        while True:
            buffer = u.read(block_sz)
            if not buffer:
                break

            file_size_dl += len(buffer)
            f.write(buffer)

            status = "{0:16}".format(file_size_dl)
            if file_size:
                status += "   [{0:6.2f}%]".format(file_size_dl * 100 / file_size)
            status += chr(13)
            print(status, end="")
        print()

    return filename

if __name__ == "__main__":  # Only run if this file is called directly
    print("Testing with 10MB download")
    url = "http://download.thinkbroadband.com/10MB.zip"
    filename = download_file(url)
    print(filename)

간단하지만 Python 2 & Python 3호환되는 방법은 six라이브러리 와 함께 제공됩니다 .

from six.moves import urllib
urllib.request.urlretrieve("http://www.example.com/songs/mp3.mp3", "mp3.mp3")

import os,requests
def download(url):
    get_response = requests.get(url,stream=True)
    file_name  = url.split("/")[-1]
    with open(file_name, 'wb') as f:
        for chunk in get_response.iter_content(chunk_size=1024):
            if chunk: # filter out keep-alive new chunks
                f.write(chunk)


download("https://example.com/example.jpg")

wget을 바로이 목적을 위해 순수한 파이썬 라이브러리를. 그것은 최대 펌핑 urlretrieve으로 이러한 기능을 버전 2.0으로.


Corey에 동의합니다. urllib2는 urllib 보다 완벽하며 더 복잡한 작업을 수행하려는 경우 사용되는 모듈 일 가능성이 높지만 답변을 더 완벽하게 만들기 위해 urllib는 기본 만 원하는 경우 더 간단한 모듈입니다.

import urllib
response = urllib.urlopen('http://www.example.com/sound.mp3')
mp3 = response.read()

잘 작동합니다. 또는 "response"객체를 처리하지 않으려면 read ()를 직접 호출 할 수 있습니다.

import urllib
mp3 = urllib.urlopen('http://www.example.com/sound.mp3').read()

다음은 Python에서 파일을 다운로드하는 데 가장 일반적으로 사용되는 호출입니다.

  1. urllib.urlretrieve ('url_to_file', file_name)

  2. urllib2.urlopen('url_to_file')

  3. requests.get(url)

  4. wget.download('url', file_name)

참고 : urlopenurlretrieve대용량 파일 (크기> 500MB의) 다운로드 상대적으로 나쁜 수행 발견된다. requests.get다운로드가 완료 될 때까지 파일을 메모리에 저장합니다.


urlretrieve를 사용하여 진행 상황에 대한 피드백을받을 수도 있습니다.

def report(blocknr, blocksize, size):
    current = blocknr*blocksize
    sys.stdout.write("\r{0:.2f}%".format(100.0*current/size))

def downloadFile(url):
    print "\n",url
    fname = url.split('/')[-1]
    print fname
    urllib.urlretrieve(url, fname, report)

wget이 설치되어 있으면 parallel_sync를 사용할 수 있습니다.

pip install parallel_sync

from parallel_sync import wget
urls = ['http://something.png', 'http://somthing.tar.gz', 'http://somthing.zip']
wget.download('/tmp', urls)
# or a single file:
wget.download('/tmp', urls[0], filenames='x.zip', extract=True)

문서 : https://pythonhosted.org/parallel_sync/pages/examples.html

이것은 매우 강력합니다. 병렬로 파일을 다운로드하고 실패시 재 시도 할 수 있으며 원격 시스템에 파일을 다운로드 할 수도 있습니다.


python3에서는 urllib3 및 shutil libraires를 사용할 수 있습니다. pip 또는 pip3을 사용하여 다운로드 (python3이 기본값인지 여부에 따라 다름)

pip3 install urllib3 shutil

그런 다음이 코드를 실행하십시오.

import urllib.request
import shutil

url = "http://www.somewebsite.com/something.pdf"
output_file = "save_this_name.pdf"
with urllib.request.urlopen(url) as response, open(output_file, 'wb') as out_file:
    shutil.copyfileobj(response, out_file)

다운로드 urllib3하지만 urllib코드에서 사용하십시오 .


완전성을 위해 subprocess패키지를 사용하여 파일을 검색하기 위해 모든 프로그램을 호출 할 수도 있습니다 . 파일 검색 전용 프로그램은 urlretrieve. 예를 들어, wget디렉토리를 재귀 적으로 다운로드 할 수 있고 ( -R), FTP, 리디렉션, HTTP 프록시를 처리 할 수 ​​있고, 기존 파일을 다시 다운로드 하지 않을 수 있으며 ( -nc), aria2잠재적으로 다운로드 속도를 높일 수있는 다중 연결 다운로드를 수행 할 수 있습니다.

import subprocess
subprocess.check_output(['wget', '-O', 'example_output_file.html', 'https://example.com'])

Jupyter Notebook에서는 다음 !구문을 사용하여 프로그램을 직접 호출 할 수도 있습니다 .

!wget -O example_output_file.html https://example.com

당신에게 속도 문제는, 내가 모듈을위한 작은 성능 테스트 한 경우 urllibwget,와 관련하여 wget나는 상태 표시 줄에 및없이 일단 한 번 시도했다. 테스트를 위해 500MB 파일 3 개를 사용했습니다 (다른 파일-내부에서 캐싱이 진행될 가능성을 없애기 위해). python2를 사용하여 데비안 컴퓨터에서 테스트되었습니다.

첫째, 결과는 다음과 같습니다 (다른 실행에서 유사 함).

$ python wget_test.py 
urlretrive_test : starting
urlretrive_test : 6.56
==============
wget_no_bar_test : starting
wget_no_bar_test : 7.20
==============
wget_with_bar_test : starting
100% [......................................................................] 541335552 / 541335552
wget_with_bar_test : 50.49
==============

테스트를 수행 한 방법은 "프로필"데코레이터를 사용하는 것입니다. 다음은 전체 코드입니다.

import wget
import urllib
import time
from functools import wraps

def profile(func):
    @wraps(func)
    def inner(*args):
        print func.__name__, ": starting"
        start = time.time()
        ret = func(*args)
        end = time.time()
        print func.__name__, ": {:.2f}".format(end - start)
        return ret
    return inner

url1 = 'http://host.com/500a.iso'
url2 = 'http://host.com/500b.iso'
url3 = 'http://host.com/500c.iso'

def do_nothing(*args):
    pass

@profile
def urlretrive_test(url):
    return urllib.urlretrieve(url)

@profile
def wget_no_bar_test(url):
    return wget.download(url, out='/tmp/', bar=do_nothing)

@profile
def wget_with_bar_test(url):
    return wget.download(url, out='/tmp/')

urlretrive_test(url1)
print '=============='
time.sleep(1)

wget_no_bar_test(url2)
print '=============='
time.sleep(1)

wget_with_bar_test(url3)
print '=============='
time.sleep(1)

urllib 가장 빠른 것 같습니다


소스 코드는 다음과 같습니다.

import urllib
sock = urllib.urlopen("http://diveintopython.org/")
htmlSource = sock.read()                            
sock.close()                                        
print htmlSource  

Python 2 및 3에서 PycURL사용할 수 있습니다 .

import pycurl

FILE_DEST = 'pycurl.html'
FILE_SRC = 'http://pycurl.io/'

with open(FILE_DEST, 'wb') as f:
    c = pycurl.Curl()
    c.setopt(c.URL, FILE_SRC)
    c.setopt(c.WRITEDATA, f)
    c.perform()
    c.close()

나는 바닐라 파이썬 2 또는 파이썬 3에서 작동하는 다음을 작성했습니다.


import sys
try:
    import urllib.request
    python3 = True
except ImportError:
    import urllib2
    python3 = False


def progress_callback_simple(downloaded,total):
    sys.stdout.write(
        "\r" +
        (len(str(total))-len(str(downloaded)))*" " + str(downloaded) + "/%d"%total +
        " [%3.2f%%]"%(100.0*float(downloaded)/float(total))
    )
    sys.stdout.flush()

def download(srcurl, dstfilepath, progress_callback=None, block_size=8192):
    def _download_helper(response, out_file, file_size):
        if progress_callback!=None: progress_callback(0,file_size)
        if block_size == None:
            buffer = response.read()
            out_file.write(buffer)

            if progress_callback!=None: progress_callback(file_size,file_size)
        else:
            file_size_dl = 0
            while True:
                buffer = response.read(block_size)
                if not buffer: break

                file_size_dl += len(buffer)
                out_file.write(buffer)

                if progress_callback!=None: progress_callback(file_size_dl,file_size)
    with open(dstfilepath,"wb") as out_file:
        if python3:
            with urllib.request.urlopen(srcurl) as response:
                file_size = int(response.getheader("Content-Length"))
                _download_helper(response,out_file,file_size)
        else:
            response = urllib2.urlopen(srcurl)
            meta = response.info()
            file_size = int(meta.getheaders("Content-Length")[0])
            _download_helper(response,out_file,file_size)

import traceback
try:
    download(
        "https://geometrian.com/data/programming/projects/glLib/glLib%20Reloaded%200.5.9/0.5.9.zip",
        "output.zip",
        progress_callback_simple
    )
except:
    traceback.print_exc()
    input()

메모:

  • "진행률 표시 줄"콜백을 지원합니다.
  • 내 웹 사이트에서 다운로드 한 4MB 테스트 .zip입니다.

This may be a little late, But I saw pabloG's code and couldn't help adding a os.system('cls') to make it look AWESOME! Check it out :

    import urllib2,os

    url = "http://download.thinkbroadband.com/10MB.zip"

    file_name = url.split('/')[-1]
    u = urllib2.urlopen(url)
    f = open(file_name, 'wb')
    meta = u.info()
    file_size = int(meta.getheaders("Content-Length")[0])
    print "Downloading: %s Bytes: %s" % (file_name, file_size)
    os.system('cls')
    file_size_dl = 0
    block_sz = 8192
    while True:
        buffer = u.read(block_sz)
        if not buffer:
            break

        file_size_dl += len(buffer)
        f.write(buffer)
        status = r"%10d  [%3.2f%%]" % (file_size_dl, file_size_dl * 100. / file_size)
        status = status + chr(8)*(len(status)+1)
        print status,

    f.close()

If running in an environment other than Windows, you will have to use something other then 'cls'. In MAC OS X and Linux it should be 'clear'.


urlretrieve and requests.get are simple, however the reality not. I have fetched data for couple sites, including text and images, the above two probably solve most of the tasks. but for a more universal solution I suggest the use of urlopen. As it is included in Python 3 standard library, your code could run on any machine that run Python 3 without pre-installing site-package

import urllib.request
url_request = urllib.request.Request(url, headers=headers)
url_connect = urllib.request.urlopen(url_request)

#remember to open file in bytes mode
with open(filename, 'wb') as f:
    while True:
        buffer = url_connect.read(buffer_size)
        if not buffer: break

        #an integer value of size of written data
        data_wrote = f.write(buffer)

#you could probably use with-open-as manner
url_connect.close()

This answer provides a solution to HTTP 403 Forbidden when downloading file over http using Python. I have tried only requests and urllib modules, the other module may provide something better, but this is the one I used to solve most of the problems.

참고URL : https://stackoverflow.com/questions/22676/how-do-i-download-a-file-over-http-using-python

반응형