본문 바로가기

About 배우고 익히는법/Python

[Python] 웹에서 파일 다운로드 받기

이번 포스팅에서는 파이썬으로 외부의 웹 페이지에 저장된 파일을 다운로드 받는 방법에 대해 알아보자.

사실 파일을 다운받기 위한 별도의 라이브러리가 존재하는 것은 아니고 기존에 웹 프로그래밍을 위해 사용하던 라이브러리인 'requests' 패키지를 통해 간단하게 구현할 수 있다.

request 설치
서드파티 라이브러리이기 때문에 만약 설치되어 있지 않다면 다음과 같은 명령어로 requests 패키지를 설치하도록 하자.

$ pip install requests


GET 메소드
웹 페이지에서 URL을 통해 파일을 접근할 때는 보통 GET 메소드 방식을 통해 해당 경로의 파일에 직접 접근하는 방식이 대부분이다. 예를 들자면, 마루마루 만화 사이트에서 각 만화 페이지의 이미지는 다음과 같이 나타내고 있다.

http://wasabisyrup.com/storage/gallery/-quJruo2cWQ/m0071_6lMClr7aldA.jpg

그렇기 때문에 실제로 requests 라이브러리에서 사용할 메소드 이름도 get이다.

예제 코드
구체적인 사용 방법은 다음과 같다.

# code.py # Link:https://code.i-harness.com/ko/q/6e87e6 from requests import get # to make GET request def download(url, file_name): with open(file_name, "wb") as file: # open in binary mode response = get(url) # get request file.write(response.content) # write to file if __name__ == '__main__': url = "http://wasabisyrup.com/storage/gallery/-quJruo2cWQ/m0071_6lMClr7aldA.jpg" download(url,"iml.jpg")
// code.py와 같은 경로에 iml.jpg가 생성되었음.

requests.get(url) 메소드를 통해 해당 URL이 GET 메소드인 경우, 해당 데이터를 객체로 반환한다. 그 후, 새로운 파일을 바이트 단위로 쓰기로 열어서 객체의 콘텐츠 데이터를 그대로 써주는 것이다.

위의 경우, 파일 이름을 프로그래머가 원하는 대로 지어서 다시 쓰기를 한 경우이고, 만약 URL 링크에 있었던 파일 이름을 그대로 받고 싶다면 아래와 같이 해보자.

# code.py # Link:https://code.i-harness.com/ko/q/6e87e6 from requests import get def download(url, file_name = None): if not file_name: file_name = url.split('/')[-1] with open(file_name, "wb") as file: response = get(url) file.write(response.content) if __name__ == '__main__': url = "http://wasabisyrup.com/storage/gallery/-quJruo2cWQ/m0071_6lMClr7aldA.jpg" download(url)

file_name의 인자 값이 오지 않을 경우, None으로 설정해주고 해당 URL을 split() 메소드를 사용하여 /(슬래시)로 나누어 맨 마지막, 즉 파일의 원래 이름을 file_name에 대입하는 것이다.


주의사항

from urllib import request def get(url): with request.urlopen(url) as r: return r.read()

urllib 라이브러리는 파이썬에서 가장 유명한 웹 관련 라이브러리다. 그렇기 때문에 종종 여러 웹 사이트는 아예 이 라이브러리를 봇으로 감지하여 차단하고 있다.

urllib.error.HTTPError: HTTP Error 403: Forbidden

만약 이 라이브러리를 사용하다 다음과 같은 에러를 만났을 경우, 봇 감지에 걸렸다고 생각하면 될 것 같다.