Python을 사용하여 URL에서 파일을 다운로드하는 5가지 방법
Python을 활용하여 웹 주소(URL)에서 파일을 내려받는 다양한 방법을 알아보고 싶으신가요? 여러 가지 기법들을 함께 살펴보겠습니다.
Python 프로젝트를 진행하다 보면, 웹상의 특정 URL에서 파일을 가져와야 할 때가 종종 있습니다.
물론, 파일을 수동으로 다운로드하는 방법도 있지만, Python 스크립트 안에서 프로그래밍 방식으로 URL에서 직접 파일을 다운로드하는 것이 훨씬 더 편리할 수 있습니다.
이 글에서는 Python 내장 패키지뿐만 아니라 외부 Python 패키지를 활용하여 웹에서 파일을 내려받는 여러 가지 접근법을 자세히 알아보겠습니다.
Python으로 URL에서 파일 다운로드하는 방법
만약 Python을 사용해 본 경험이 있다면, 아래와 같은 XKCD Python 관련 유명 만화를 보신 적이 있을 겁니다.
Python 만화 | 출처: XKCD
이 예시에서는 다양한 방법을 사용하여 위 XKCD 만화 이미지(확장자 .png)를 작업 디렉토리에 내려받아 보겠습니다.
이 글 전반에 걸쳐 여러 외부 Python 패키지를 사용할 예정이니, 프로젝트 전용 가상 환경에 해당 패키지들을 모두 설치해 주시길 바랍니다.
urllib.request 모듈 활용
Python에 내장된 urllib.request 모듈을 사용하면 URL에서 파일을 쉽게 다운로드할 수 있습니다. 이 모듈은 HTTP 요청 및 URL 처리 기능을 제공하여 웹 리소스와 상호작용하는 간단한 방식을 제공하므로, 웹사이트에서 데이터를 가져오는 등의 작업을 수행할 수 있습니다.
urllib.request를 활용하여 XKCD Python 만화를 내려받아 봅시다.
import urllib.request url="https://imgs.xkcd.com/comics/python.png" urllib.request.urlretrieve(url, 'xkcd_comic.png')
위 코드에서 다음을 수행합니다.
- urllib.request 모듈을 가져옵니다.
- XKCD Python 만화 이미지의 URL을 설정합니다.
- urllib.request.urlretrieve 함수를 사용하여 이미지를 다운로드하고 현재 디렉토리에 'xkcd_comic.png'라는 이름으로 저장합니다.
이제 터미널에서 `ls` 명령을 실행하여 현재 디렉토리의 내용을 확인하면, 'xkcd_comic.png' 파일이 생성된 것을 확인할 수 있습니다.

requests 라이브러리 활용
가장 많이 사용되는 Python 패키지 중 하나인 requests 라이브러리는 웹을 통해 HTTP 요청을 보내고 콘텐츠를 가져올 수 있도록 지원합니다.
먼저, requests 라이브러리를 설치해야 합니다.
pip install requests
만약 동일한 디렉토리에 새로운 Python 스크립트를 생성했다면, 현재 스크립트를 실행하기 전에 'xkcd_comic.png' 파일을 삭제해 주세요.
import requests
url="https://imgs.xkcd.com/comics/python.png"
response = requests.get(url)
with open('xkcd_comic.png', 'wb') as file:
file.write(response.content)
이 코드에서 수행하는 작업을 분석해 보겠습니다.
- requests 라이브러리를 가져옵니다.
- XKCD Python 만화 이미지의 URL을 설정합니다.
- requests.get 함수를 사용하여 해당 URL에 GET 요청을 보냅니다.
- 바이너리 쓰기 모드('wb')로 파일을 열고, HTTP 응답으로 받은 이미지 데이터를 'xkcd_comic.png'라는 이름으로 저장합니다.
이제 디렉토리 내용을 확인하면 다운로드된 이미지 파일이 나타날 것입니다.

urllib3 라이브러리 활용
내장된 urllib.request 모듈을 사용하는 방법을 알아보았습니다. 이번에는 외부 Python 패키지인 urllib3를 사용하는 방법을 살펴보겠습니다.
Urllib3는 내장 urllib 모듈보다 더 안정적이고 효율적으로 HTTP 요청을 생성하고 연결을 관리하기 위한 Python 라이브러리입니다. 연결 풀링, 요청 재시도, 스레드 안전 등의 기능을 제공하므로, Python 애플리케이션에서 HTTP 통신을 처리하는 데 강력한 선택지입니다.
먼저 pip를 사용하여 urllib3를 설치합니다.
pip install urllib3
이제 urllib3 라이브러리를 사용하여 XKCD Python 만화를 다운로드해 보겠습니다.
import urllib3
# XKCD 만화 이미지의 URL
url="https://imgs.xkcd.com/comics/python.png"
# PoolManager 인스턴스 생성
http = urllib3.PoolManager()
# URL에 HTTP GET 요청 전송
response = http.request('GET', url)
# 콘텐츠(이미지 데이터) 가져오기
image_data = response.data
# 만화 이미지 파일 이름을 지정
file_name="xkcd_comic.png"
# 이미지 데이터 저장
with open(file_name, 'wb') as file:
file.write(image_data)
이 방법은 urllib.request 및 requests 라이브러리를 사용한 이전 방법보다 다소 복잡해 보입니다. 이제 각 단계를 자세히 분석해 보겠습니다.
- HTTP 요청 기능을 제공하는 urllib3 모듈을 가져오는 것으로 시작합니다.
- 다음으로 XKCD 만화 이미지의 URL을 지정합니다.
- urllib3.PoolManager()의 인스턴스를 만듭니다. 이 객체는 연결 풀을 관리하고 HTTP 요청을 수행할 수 있게 합니다.
- http.request('GET', url) 메서드를 사용하여 지정된 URL로 HTTP GET 요청을 전송합니다. 이 요청은 XKCD 만화 콘텐츠를 가져옵니다.
- 요청이 성공하면 response.data를 사용하여 HTTP 응답에서 콘텐츠(이미지 데이터)를 가져옵니다.
- 마지막으로, 응답에서 얻은 이미지 데이터를 파일에 저장합니다.
Python 스크립트를 실행하면 다음과 같은 결과가 표시됩니다.

wget 라이브러리 활용
wget Python 라이브러리는 URL에서 파일을 다운로드하는 작업을 단순화합니다. 이 라이브러리를 사용하면 웹 리소스를 쉽게 가져올 수 있으며, 특히 다운로드 작업을 자동화하는 데 유용합니다.
pip를 사용하여 wget 라이브러리를 설치한 다음, 해당 기능을 사용하여 URL에서 파일을 다운로드할 수 있습니다.
pip install wget
다음 코드는 wget 모듈을 사용하여 XKCD Python 만화를 다운로드하고 작업 디렉토리에 'xkcd_comic.png'라는 이름으로 저장합니다.
import wget url="https://imgs.xkcd.com/comics/python.png" wget.download(url, 'xkcd_comic.png')
여기서:
- wget 모듈을 가져옵니다.
- XKCD Python 만화 이미지의 URL을 설정합니다.
- wget.download 함수를 사용하여 이미지를 다운로드하고 현재 디렉토리에 'xkcd_comic.png'로 저장합니다.
wget을 사용하여 XKCD 만화를 다운로드하면 비슷한 결과를 얻을 수 있습니다.

PyCURL 라이브러리 활용
Linux나 Mac 시스템을 사용해 본 적이 있다면, 웹에서 파일을 다운로드하는 데 사용되는 cURL 명령줄 도구에 익숙할 것입니다.
PyCURL은 libcurl의 Python 인터페이스이며, HTTP 요청을 생성하는 데 강력한 도구입니다. 요청에 대한 세밀한 제어를 제공하며 웹 리소스를 다룰 때 고급 사용 사례에 활용할 수 있습니다.
작업 환경에 pycurl을 설치하는 과정이 다소 복잡할 수 있습니다. pip를 사용하여 설치를 시도해 봅시다.
pip install pycurl
⚠️ 설치 과정에서 오류가 발생한다면, PyCURL 설치 가이드에서 문제 해결 팁을 확인해 보시기 바랍니다.
또는 cURL이 이미 설치되어 있는 경우, 다음과 같이 libcurl에 대한 Python 바인딩을 설치할 수 있습니다.
sudo apt install python3-pycurl
참고: Python 바인딩을 설치하기 전에 cURL이 설치되어 있어야 합니다. 컴퓨터에 cURL이 설치되어 있지 않다면, `apt install curl` 명령어를 사용하여 설치할 수 있습니다.
PyCURL을 사용하여 파일 다운로드하기
PyCURL을 사용하여 XKCD 만화를 다운로드하는 코드는 다음과 같습니다.
import pycurl
from io import BytesIO
# XKCD Python 만화의 URL
url="https://imgs.xkcd.com/comics/python.png"
# Curl 객체 생성
c = pycurl.Curl()
# URL 설정
c.setopt(pycurl.URL, url)
# 다운로드한 데이터를 저장할 BytesIO 객체 생성
buffer = BytesIO()
c.setopt(pycurl.WRITEDATA, buffer)
# 요청 수행
c.perform()
# 요청이 성공했는지 확인 (HTTP 상태 코드 200)
http_code = c.getinfo(pycurl.HTTP_CODE)
if http_code == 200:
# 다운로드한 데이터를 파일에 저장
with open('xkcd_comic.png', 'wb') as f:
f.write(buffer.getvalue())
# Curl 객체 닫기
c.close()
위 코드를 각 단계별로 나누어 자세히 살펴보겠습니다.
1단계: 필요한 모듈 가져오기
가장 먼저 pycurl을 가져와 HTTP 요청을 사용할 수 있도록 합니다. 그런 다음 IO 모듈에서 BytesIO를 가져와 다운로드한 데이터를 저장할 버퍼를 생성합니다.
import pycurl from io import BytesIO
2단계: Curl 객체 생성 및 URL 설정
다운로드하려는 XKCD Python 만화의 URL을 지정합니다. 그리고 HTTP 요청을 나타내는 Curl 객체를 생성합니다. 다음으로 `c.setopt(pycurl.URL, url)`을 사용하여 Curl 객체의 URL을 설정합니다.
# XKCD Python 만화의 URL url="https://imgs.xkcd.com/comics/python.png" # Curl 객체 생성 c = pycurl.Curl() # URL 설정 c.setopt(pycurl.URL, url)
3단계: BytesIO 객체 생성 및 WRITEDATA 옵션 설정
다운로드한 데이터를 저장하기 위해 BytesIO 객체를 생성하고, `c.setopt(pycurl.WRITEDATA, buffer)`를 사용하여 버퍼에 응답 데이터를 쓰도록 Curl 객체를 설정합니다.
# 다운로드한 데이터를 저장할 BytesIO 객체 생성 buffer = BytesIO() c.setopt(pycurl.WRITEDATA, buffer)
4단계: 요청 수행
`c.perform()`을 사용하여 HTTP 요청을 실행하고, 만화 이미지 데이터를 가져옵니다.
# 요청 수행 c.perform()
5단계: HTTP 상태 코드 확인 및 다운로드한 데이터 저장
요청이 성공했는지 확인하기 위해 `c.getinfo(pycurl.HTTP_CODE)`를 사용하여 HTTP 상태 코드를 가져옵니다(HTTP 코드 200). HTTP 상태 코드가 200이면 버퍼의 데이터를 이미지 파일에 저장합니다.
# 요청이 성공했는지 확인 (HTTP 상태 코드 200)
http_code = c.getinfo(pycurl.HTTP_CODE)
if http_code == 200:
# 다운로드한 데이터를 파일에 저장
with open('xkcd_comic.png', 'wb') as f:
f.write(buffer.getvalue())
6단계: Curl 객체 닫기
마지막으로 리소스를 정리하기 위해 `c.close()`를 사용하여 Curl 객체를 닫습니다.
# Curl 객체 닫기 c.close()
큰 파일을 작은 조각으로 나누어 다운로드하는 방법
지금까지 작은 이미지 파일인 XKCD Python 만화를 현재 디렉토리에 다운로드하는 다양한 방법을 살펴보았습니다.
그러나 IDE 설치 프로그램과 같이 훨씬 더 큰 파일을 다운로드해야 할 수도 있습니다. 이렇게 큰 파일을 다운로드할 때는 파일을 작은 단위로 나누어 다운로드하고, 다운로드 진행 상황을 추적하는 것이 도움이 될 수 있습니다. 요청 라이브러리의 기능을 활용하면 이러한 작업을 쉽게 수행할 수 있습니다.
요청 라이브러리를 사용하여 VS Code 설치 프로그램을 1MB 크기의 조각으로 나누어 다운로드해 보겠습니다.
import requests
# Visual Studio Code 설치 프로그램 EXE 파일의 URL
url="https://code.visualstudio.com/sha/download?build=stable&os=win32-x64-user"
# 다운로드 청크 크기
chunk_size = 1024 * 1024 # 1MB 청크
response = requests.get(url, stream=True)
# Content-Length 헤더에서 전체 파일 크기 확인
total_size = int(response.headers.get('content-length', 0))
with open('vs_code_installer.exe', 'wb') as file:
for chunk in response.iter_content(chunk_size):
if chunk:
file.write(chunk)
file_size = file.tell() # 현재 파일 크기 가져오기
print(f'다운로드 중... {file_size}/{total_size} 바이트', end='\r')
print('다운로드 완료.')
여기서:
- 각 청크의 크기를 결정하기 위해 `chunk_size` 변수를 설정했습니다(이 예시에서는 1MB).
- `stream=True` 옵션과 함께 `requests.get` 함수를 사용하여 전체 파일을 한 번에 메모리에 로드하지 않고 응답 콘텐츠를 스트리밍합니다.
- 각 청크를 다운로드할 때마다 순차적으로 파일에 저장합니다.
다운로드가 진행됨에 따라 현재 다운로드된 바이트 수와 전체 바이트 수를 확인할 수 있습니다.

다운로드가 완료되면 '다운로드 완료' 메시지가 표시됩니다.

이제 디렉토리에 VS Code 설치 프로그램이 나타날 것입니다.

마무리
Python을 사용하여 URL에서 파일을 다운로드하는 여러 가지 방법을 배우셨기를 바랍니다. 내장된 `urllib.request` 모듈 외에도 `requests`, `urllib3`, `wget`, 그리고 `PyCURL`과 같은 유명한 외부 Python 패키지들을 살펴보았습니다.
개발자로서 개인적으로는 파일 다운로드 및 웹 API와 관련된 작업에 `requests` 라이브러리를 다른 라이브러리보다 더 많이 사용해 왔습니다. 그러나 다운로드 작업의 복잡성과 HTTP 요청에 필요한 세분화 수준에 따라 다른 방법들도 매우 유용할 수 있습니다. 즐거운 다운로드 경험 되시길 바랍니다!