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

StackOverflow https://stackoverflow.com/questions/22676

  •  09-06-2019
  •  | 
  •  

문제

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

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

실제로 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.request 그리고 urllib.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

  • urllib2.urlopen (감사해요 코리)

    import urllib2
    response = urllib2.urlopen('http://www.example.com/')
    html = response.read()
    
  • urllib.urlretrieve (감사해요 파블로G)

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

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)

썼다 wget 이 목적을 위해 순수 Python으로 작성된 라이브러리입니다.펌핑되어 있어요 urlretrieve ~와 함께 이러한 기능 버전 2.0부터.

단순하면서도 Python 2 & Python 3 호환 가능한 방식으로 제공됩니다. six 도서관:

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

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

import urllib
response = urllib.urlopen('http://www.example.com/sound.mp3')
mp3 = 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)

메모: urlopen 그리고 urlretrieve 대용량 파일(크기 > 500MB)을 다운로드할 때 성능이 상대적으로 좋지 않은 것으로 나타났습니다. requests.get 다운로드가 완료될 때까지 파일을 메모리에 저장합니다.

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

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 설치 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 코드에서

속도가 중요하다면 모듈에 대한 간단한 성능 테스트를 수행했습니다. urllib 그리고 wget, 그리고 wget 상태 표시줄을 사용하여 한 번, 상태 표시줄 없이 한 번 시도했습니다.테스트를 위해 3개의 서로 다른 500MB 파일을 사용했습니다(다른 파일 - 내부적으로 캐싱이 발생할 가능성을 없애기 위해).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
==============

제가 테스트를 수행한 방식은 "profile" 데코레이터를 사용하는 것입니다.전체 코드는 다음과 같습니다.

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 가장 빠른 것 같아요

완전성을 기하기 위해 다음을 사용하여 파일을 검색하기 위한 모든 프로그램을 호출하는 것도 가능합니다. subprocess 패키지.파일 검색 전용 프로그램은 다음과 같은 Python 기능보다 강력합니다. 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

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

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

나는 바닐라 Python 2 또는 Python 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입니다.

당신이 사용할 수있는 PycURL Python 2와 3에서.

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

조금 늦었을 수도 있지만 pabloG의 코드를 보고 os.system('cls')을 추가하여 멋지게 보이게 만들 수 밖에 없었습니다!확인 해봐 :

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

Windows 이외의 환경에서 실행하는 경우 'cls' 이외의 다른 것을 사용해야 합니다.MAC OS X 및 Linux에서는 'clear'해야 합니다.

urlretrieve와 request.get은 간단하지만 현실은 그렇지 않습니다.텍스트와 이미지를 포함한 몇 개의 사이트에 대한 데이터를 가져왔는데, 위의 두 가지가 아마도 대부분의 작업을 해결할 것입니다.그러나 보다 보편적인 솔루션을 위해서는 urlopen을 사용하는 것이 좋습니다.Python 3 표준 라이브러리에 포함되어 있으므로 사이트 패키지를 사전 설치하지 않고도 Python 3을 실행하는 모든 시스템에서 코드를 실행할 수 있습니다.

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

이 답변은 Python을 사용하여 http를 통해 파일을 다운로드할 때 HTTP 403 Forbidden에 대한 솔루션을 제공합니다.나는 요청과 urllib 모듈만 시도했고 다른 모듈이 더 나은 것을 제공할 수도 있지만 이것이 대부분의 문제를 해결하는 데 사용한 모듈입니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top