파이썬을 사용하여 URL에서 파일을 다운로드 하는 방법

2023. 12. 6. 21:41python/basic

파이썬을 사용하여 URL에서 파일을 다운로드 하는 방법

ㅇ 표준 라이브러리오 파이썬의 탓 라이브러리를 사용하여 웹에서 파일 다운로드

ㅇ 데이터 스트리밍 대용량 파일을 관리 가능한 단위로 다운로드

ㅇ 스레드 풀을 사용하여 병렬 다운로드 구현

ㅇ 비동기 다운로드를 수행하여 여러 파일을 대량으로 다운로드 파이썬을 사용하여 파일을

다운로드시 이점 유연성 이식성 프로세스 자동화 urllib을 사용하면 URL 구분 분석, HTTP 요청 전송, 파일 다운로드, 네트워크 작업과 관련된 오류 처리 등 네트워크 통신을 다루는 다양한 작업을 수행

from urllib.request import urlretrieve

url = ("https://api.worldbank.org/v2/en/indicator/" "NY.GDP.MKTP.CD?downloadformat=csv")

filename = "gdp_by_country.zip"

인터프린터는 서로 다른 줄에 있는 별도의 문자열을 자동으로 단일 문자열로 결합합니다

urlretrieve(url, filename)
('gdp_by_country.zip', )

path, headers = urlretrieve(url, filename)
for name, value in headers.items():
print(name, value)

할당문을 사용하여 튜플을 개별 변수로 압축해제할 수 있습니다.

requests 라이브러리는 요청 헤더 지정, 쿠키 처리, 로그인 제한 웹페이지 뒤의 데이터 액세스, 데이터 청크 단위 스트리밍 등이 있습니다.

!python -m pip install requests

import requests

ㅇ HTTP GET : 서버 상태를 수정하지 않고 원격 리소스의 표현을 가져와서 데이터를 검색할 때에 사용합니다.
ㅇ HTTP POST : 기존 또는 새 리소스 생성, 업데이트, 제출 등 서버 데이터를 수정하는 작업에 사용합니다.

url = "https://api.worldbank.org/v2/en/indicator/NY.GDP.MKTP.CD"
query_parameters = {"downloadformat": "csv"}

response = requests.get(url, params=query_parameters)
response.url

response.ok

response.status_code

다운로드한 콘텐츠를 파일에 저장합니다.

with open("gdp_by_country.zip", mode="wb") as
file: file.write(response.content)

스트리밍 방식으로 대용량 파일 다운로드 데이터 스트리밍은 다음과 같은 시나리오에서도 이점을 제공합니다.

  1. 파일을 작은 단위로 다운로드 하고 처리
  2. 실시간으로 데이터 처리 및 소비
  3. 다운로드 프로세스 일시 중지 및 재개

url = "https://databank.worldbank.org/data/download/WDI_CSV.zip"
response = requests.get(url, stream=True)

response.headers

with open("WDI_CSV.zip", mode="wb") as file:
for chunk in response.iter_content(chunk_size=10 * 1024):
file.write(chunk)

병렬 파일 다운로드 수행

  1. 스레드 풀을 requests 라이브러리와 함께 사용
  2. 라이브러리와 함께 비동기 다운로드 사용

from concurrent.futures import ThreadPoolExecutor
import requests

def download_file(url):
response = requests.get(url)
if "content-disposition" in response.headers:
content_disposition = response.headers["content-disposition"]
filename = content_disposition.split("filename=")[1]
else:
filename = url.split("/")[-1]
with open(filename, mode="wb") as file:
file.write(response.content)
print(f"Downloaded file {filename}")

동일한 API에서 세 개의 개별 파일을 다운로드하게 되므로 URL 템플릿을 만들고 이를 파이썬 목록에 입력합니다.

template_url = (
"https://api.worldbank.org/v2/en/indicator/"
"{resource}?downloadformat=csv" )
urls = [

Total population by country

template_url.format(resource="SP.POP.TOTL"),

GDP by country

template_url.format(resource="NY.GDP.MKTP.CD"),

Population density by country

template_url.format(resource="EN.POP.DNST"),
]

여러 실행 스레드를 사용하여 이러한 파일을 동시에 다운로드 하려면 새 스레드 풀을 만들고 download_file() 함수를 목록의 각 항목에 매핑합니다.

with ThreadPoolExecutor() as executor:
executor.map(download_file, urls) Downloaded file API_NY.GDP.MKTP.CD_DS2_en_csv_

for 루프를 사용하는 경우

for url in urls:
download_file(url)

안타깝게도 스레드를 사용하는 것은 복잡성으로 인해 항상 바람직하지는 않습니다. 멀티스레팅이 성능을 전혀 향상시키지 못하는 몇가지 조건이 있습니다. 근본적인 문제가 본질적으로 순차적이라면 이를 병렬화할 방법이 없습니다. 게다가 작업에 CPU 바인딩 작업이 포함된 경우 파이썬은 이전 GIL로 인해 여러 CPU 코어를 활용할 수가 없습니다.

비동기식 aiothhp 라이브러리 사용

!python -m pip install aiohttp

import asyncio
import aiohttp

async def download_file(url):
async with aiohttp.ClientSession() as session:
async with session.get(url) as response:
if "content-disposition" in response.headers:
header = response.headers["content-disposition"]
filename = header.split("filename=")[1]
else:
filename = url.split("/")[-1]
with open(filename, mode="wb") as file:
while True:
chunk = await response.content.read()
if not chunk:
break
file.write(chunk)
print(f"Downloaded file {filename}")

template_url = (
"https://api.worldbank.org/v2/en/indicator/"
"{resource}?downloadformat=csv"
)

urls = [

Total population by country

template_url.format(resource="SP.POP.TOTL"),

GDP by country

template_url.format(resource="NY.GDP.MKTP.CD"),

Population density by country

template_url.format(resource="EN.POP.DNST"),
]

async def main(url):
tasks = [download_file(url) for url in urls]
await asyncio.gather(*tasks)

asyncio.run(main())