이 가이드에서는 다음을 확인할 수 있습니다:
wget이무엇인지.- 왜 requests 라이브러리보다 나을 수 있는지.
- Python에서
wget사용이 얼마나 쉬운지. - Python 스크립트에서 wget을 채택할 때의 장단점.
자, 시작해 보겠습니다!
wget이란 무엇인가?
wget은HTTP, HTTPS, FTP, FTPS 및 기타 인터넷 프로토콜을 사용하여 웹에서 파일을 다운로드하기 위한 명령줄 유틸리티입니다. 대부분의 유닉스 계열 운영체제에 기본적으로 설치되어 있지만, Windows에서도 사용할 수 있습니다.
왜 Python 패키지인 requests가 아닌 Wget인가?
물론 wget은 멋진 명령줄 도구이지만,requests와 같은 인기 있는 라이브러리 대신 파이썬에서 파일을 다운로드하는 데 왜 wget을 사용해야 할까요?
wget을 requests보다 사용해야 하는 설득력 있는 이유가 몇 가지 있습니다:
- requests보다 훨씬 더 많은 프로토콜을 지원합니다.
- 중단되거나 중단된 다운로드를 재개할 수 있습니다.
- 제한된 다운로드 속도를 지정하여 네트워크 대역폭을 모두 소모하지 않도록 지원합니다.
- 와일드카드가 포함된 파일명 및 네트워크 위치를 지원합니다.
- 다양한 언어를 위한 NLS 기반 메시지 파일을 제공합니다.
- 다운로드된 문서 내 절대 링크를 상대 링크로 변환할 수 있습니다.
- HTTP/S 프록시를 지원합니다.
- 지속적인 HTTP 연결을 지원합니다.
- 무인/백그라운드 다운로드 작업을 수행할 수 있습니다.
- 미러링 시 문서 재다운로드 필요 여부를 판단하기 위해 로컬 파일 타임스탬프를 사용합니다.
- 특정 웹 페이지에 링크된 파일을 재귀적으로 다운로드하거나 사용자가 지정한 재귀 깊이에 도달할 때까지 다운로드할 수 있습니다.
- robots.txt에 정의된 로봇 배제 규칙을 자동으로 준수합니다.웹 스크래핑을 위한 robots.txt 가이드에서 자세한 내용을 확인하세요.
이는 wget이 다른 Python HTTP 클라이언트 라이브러리에 비해 강력하고 특별한 이유 중 일부에 불과합니다. 자세한 내용은공식 매뉴얼에서 확인하세요.
특히 wget이 HTML 페이지 내 링크를 추적하여 해당 페이지에서 참조된 파일을 다운로드하는 방식을 주목하세요. 이 기능 덕분에 웹사이트 전체를 가져올 수 있어 wget은웹 크롤링에 이상적입니다.
요약하자면, 웹에서 파일과 웹 페이지를 다운로드해야 하는 스크립트를 작성할 때 wget은 훌륭한 선택입니다. Python과 함께 wget을 사용하는 방법을 배워봅시다!
Python에서 CLI 명령 실행하기
아래 단계를 따라 wget 명령을 실행할 수 있는 Python 스크립트를 작성해 보세요.
필수 조건
시작하기 전에 컴퓨터에 wget이 설치되어 있는지 확인하세요. 설치 과정은 운영 체제에 따라 다릅니다:
- 리눅스의 경우 기본적으로 설치되어 있을 것입니다. 그렇지 않다면 배포판의 패키지 관리자를 사용하여 설치하세요.
- Mac에서는Homebrew로
wget을설치하세요. - Windows에서는Windows용
Wget바이너리를다운로드하여 폴더에 저장하세요. 그런 다음wget바이너리 경로(예: C:Program Files (x86)Wget)를PATH 환경 변수에 추가하세요.
또한 컴퓨터에 Python 3 이상이 설치되어 있어야 합니다. 설치하려면설치 프로그램을 다운로드한 후 더블클릭하고 안내에 따라 진행하세요.
PyCharm Community Edition이나Python 확장 기능이 설치된 Visual Studio Code와같은 Python IDE도 유용할것입니다.
Python 프로젝트 설정
아래 명령어를 사용하여가상 환경을포함한 wget Python 프로젝트를 생성하세요:
mkdir wget-python-demo
cd wget-python-demo
python -m venv env
위에서 생성한 wget-python-demo 디렉터리는 프로젝트 폴더를 나타냅니다.
Python IDE에서 이 디렉터리를 로드하고, script.py 파일을 생성한 후 다음과 같이 초기화하세요:
print('Hello, World!')
현재 이 스크립트는 터미널에 “Hello, World!”를 출력하는 샘플입니다. 곧 wget 통합 로직이 포함될 예정입니다.
IDE의 실행 버튼을 누르거나 아래 명령어로 스크립트 작동 여부를 확인하세요:
python script.py
터미널에 다음과 같은 결과가 표시되어야 합니다:
Hello, World!
완벽합니다! 이제 Python 프로젝트가 준비되었습니다.
다음 섹션에서 wget 사용법을 확인하세요!
subprocess 모듈을 통해 CLI 명령을 실행하는 함수 작성하기
파이썬 스크립트에서 CLI 명령을 실행하는 가장 쉬운 방법은subprocess모듈을 사용하는 것입니다.
Python 표준 라이브러리의 이 라이브러리를 사용하면 새 프로세스를 생성하고, 해당 프로세스의 입력/출력/오류 파이프에 연결하고, 반환 코드를 얻을 수 있습니다. 즉, Python에서 터미널 명령을 실행하는 데 필요한 모든 기능을 제공합니다.
Python에서 wget과 같은 CLI 명령어를 실행하기 위해 subprocess의Popen()메서드를 사용하는 방법은 다음과 같습니다:
import subprocess
def execute_command(command):
"""
CLI 명령어를 실행하고 출력 및 오류 메시지를 반환합니다.
매개변수:
- command (str): 실행할 CLI 명령어.
반환값:
- output (str): 명령어에 의해 생성된 출력.
- error (str): 명령어가 생성한 오류 메시지(있는 경우).
"""
try:
# 명령어 실행 및 출력/오류 메시지 캡처
process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
output, error = process.communicate()
output = output.decode("utf-8")
error = error.decode("utf-8")
# 출력 및 오류 메시지 반환
return output, error
except Exception as e:
# 예외 발생 시, 예외 메시지를 오류로 반환
return None, str(e)
Popen()은 문자열로 전달된 명령어를 운영체제의 새 프로세스에서 실행합니다. shell=True 옵션은 해당 메서드가 OS에 설정된 기본 셸을 사용하도록 보장합니다.
위의 코드 조각을 script.py 파일에 붙여넣으세요. 이제 다음과 같은 예시처럼 Python에서 CLI 명령어를 호출할 수 있습니다:
output, error = execute_command("<CLI 명령어 문자열>")
if error:
print("CLI 명령어 실행 중 오류 발생:", error)
else:
print("CLI 명령어 출력:", output)
Python에서 Wget 사용: 사용 사례
wget 명령어 구문은 다음과 같습니다:
wget [옵션] [URL]
여기서:
- [options]는 CLI 도구가 지원하는 옵션 및 플래그 목록으로, 동작을 사용자 정의하는 데 사용됩니다.
- url은 다운로드하려는 파일의 URL입니다. 이는 파일의 직접 링크이거나 여러 파일 링크를 포함하는 웹페이지의 URL일 수 있습니다.
참고: Windows에서는 wget 대신 wget.exe를 입력하십시오.
이제 인기 있는 사용 사례를 다루는 Python 스니펫에서 wget이 작동하는 모습을 살펴볼 시간입니다!
파일 다운로드
wget으로 http://lumtest.com/myip.json를 다운로드한다고 가정해 보겠습니다. 이를 위한 명령어는 다음과 같습니다:
wget http://lumtest.com/myip.json
파이썬에서는 다음과 같은 코드 한 줄로 구현됩니다:
output, error = execute_command("wget http://lumtest.com/myip.json")
output을 출력하면 다음과 같은 결과가 표시됩니다:
--2024-04-18 15:20:59-- http://lumtest.com/myip.json
Resolving lumtest.com (lumtest.com)... 3.94.72.89, 3.94.40.55
lumtest.com (lumtest.com)|3.94.72.89|:80에 연결 중... 연결됨.
HTTP 요청 전송, 응답 대기 중... 200 OK
길이: 266 [application/json]
저장 중: 'myip.json.1'
myip.json.1 100%[=================================================>] 266 --.-KB/s in 0s
2024-04-18 15:20:59 (5.41 MB/s) - 'myip.json.1' 저장됨 [266/266]
명령어 출력 결과에서 확인할 수 있는 내용은 다음과 같습니다:
- URL이 서버의 IP 주소로 해결됩니다.
wget이지정된 리소스에 대한 HTTP 요청을 통해 서버에 연결합니다.- 서버가 수신한 HTTP 응답 상태 코드는 200입니다.
wget이파일을 다운로드하여 현재 디렉터리에 저장합니다.
이제 Python 프로젝트 디렉터리에 myip.json 파일이 생성됩니다.
다운로드할 파일을 저장할 대상 폴더를 변경하려면 아래와 같이 –directory-prefix 또는 -P 플래그를 사용하십시오:
output, error = execute_command("wget --directory-prefix=./download http://lumtest.com/myip.json")
이제 myip.json 파일이 프로젝트 디렉토리 내 download 폴더에 저장됩니다. 대상 폴더가 존재하지 않으면 wget이 자동으로 생성합니다.
다운로드 리소스의 파일 이름을 변경하려면 –output-document 또는 -O 플래그를 사용하세요:
output, error = execute_command("wget --output-document=custom-name.json http://lumtest.com/myip.json")
이번에는 wget Python 스크립트가 myip.json 대신 custom-name.json이라는 파일을 생성합니다.
웹 페이지 다운로드
wget 명령어는 이전과 동일하며, 주요 차이점은 이번에는 url이 웹 페이지를 가리킨다는 점입니다:
output, error = execute_command("wget https://brightdata.com/")
이제 프로젝트 디렉토리에 https://brightdata.com/ 웹 페이지의 HTML 콘텐츠가 담긴 index.html 파일이 생성됩니다.
마지막 다운로드 이후 변경된 경우에만 파일 다운로드
디스크 공간과 네트워크 자원을 절약하기 위해, 이전 다운로드 이후 변경되지 않은 파일은 다운로드하지 않을 수 있습니다. wget이파일 타임스탬핑 기능을 제공하는 이유가 바로 여기에 있습니다.
자세히 설명하면, –timestamping 옵션은 wget이 로컬 파일의 타임스탬프를 서버의 타임스탬프와 비교하도록 지시합니다. 로컬 파일의 타임스탬프가 서버의 타임스탬프와 같거나 더 최신인 경우, wget은 해당 파일을 다시 다운로드하지 않습니다. 그렇지 않으면 파일을 다운로드합니다.
타임스탬핑 메커니즘의 작동 방식은 다음과 같습니다:
- –timestamping 또는 -N 옵션으로 파일을 다운로드할 때
wget은원격 파일의 타임스탬프를 가져옵니다. - 로컬 파일의 타임스탬프(존재하는 경우)를 확인하고 원격 파일의 타임스탬프와 비교합니다.
- 로컬 파일이 존재하지 않거나 타임스탬프가 서버의 것보다 오래된 경우,
wget은파일을 다운로드합니다. 로컬 파일이 존재하고 타임스탬프가 서버의 것과 같거나 더 새로운 경우,wget은파일을 다운로드하지 않습니다.
HTTP에서 타임스탬핑은 HEAD 요청 후 서버가 반환하는Last-Modified헤더를 확인하여 구현됩니다. wget은 또한 파일 크기를 비교하기 위해Content-Length헤더도 확인합니다. 두 헤더가 동일하지 않으면 Last-Modified 헤더의 내용과 상관없이 원격 파일을 다운로드합니다. Last-Modified는 선택적 응답 헤더임을 유의하십시오. 해당 헤더가 없더라도 wget은 파일을 다운로드합니다.
Python에서 –timestamping 옵션을 사용하려면 다음 코드 줄을 실행하세요:
output, error = execute_command("wget --timestamping https://brightdata.com")
index.html을 이미 다운로드한 경우, 아래와 같은 메시지가 표시되어 파일이 다시 다운로드되지 않음을 알립니다:
--2024-04-18 15:55:06-- https://brightdata.com
Resolving brightdata.com (brightdata.com)... 104.18.25.60, 104.18.24.60
brightdata.com (brightdata.com)|104.18.25.60|:443에 연결 중... 연결됨.
HTTP 요청 전송, 응답 대기 중... 304 Not Modified
서버에서 'index.html' 파일이 수정되지 않았습니다. 다운로드를 생략합니다.
동일한 메커니즘은FTP를 통한 파일 다운로드 시에도 작동합니다.
중단된 다운로드 완료
기본적으로 wget은 다운로드 중 연결이 끊어지면 최대 20회까지 자동으로 재시도합니다. 부분적으로 다운로드된 파일을 수동으로 계속하려면 다음과 같이 –continue 또는 -c 옵션을 사용하세요:
출력, 오류 = execute_command("wget --continue http://lumtest.com/myip.json")
전체 사이트 다운로드
재귀적 다운로드는 단일 명령으로 전체 사이트를 다운로드하는 wget의 기능입니다.
지정된 URL에서 시작하여 wget은 HTML 페이지를 파싱하고 src 및 href HTML 속성 또는 url() CSS 속성에서 발견된 다른 문서들을 추적합니다. 다음 파일도 text/HTML 파일인 경우, 이를 파싱하고 원하는 깊이에 도달할 때까지 해당 문서들도 추적합니다. 재귀적 다운로드는너비 우선 탐색 알고리즘을 따르며, 깊이 1의 파일, 그다음 깊이 2의 파일 등을 순차적으로 가져옵니다.
이 다운로드 모드를 사용할 때 유의해야 할 wget 옵션은 다음과 같습니다:
- –recursive 또는 -r:
wget이파일을 재귀적으로 다운로드하도록 지시합니다. 즉, 웹 페이지의 링크를 따라갑니다. 이를 통해 이미지, 스타일시트, 스크립트 등 모든 연결된 리소스를 포함한 전체 웹사이트의 로컬 복사본을 생성할 수 있습니다. 이 옵션이 지정되면wget은다운로드된 모든 파일을 대상 사이트의 도메인 이름과 동일한 이름의 폴더에 저장합니다. - –level=<깊이> 또는 -l=<깊이>: 링크된 페이지를 다운로드할 때 따라갈 재귀의 최대 깊이를 지정합니다. 예를 들어 –level=1을 설정하면
wget은시작 URL에서 직접 링크된 페이지만 다운로드합니다. 해당 페이지의 링크를 따라 추가 페이지를 다운로드하지 않습니다. 대규모 사이트 크롤링을 방지하기 위해 기본 깊이 값은 5입니다. 무한 깊이를 원하면 이 옵션을 0 또는 ‘inf’로 설정하세요. 지정된 깊이와 무관하게 페이지 정상 표시를 위한 모든 리소스가 다운로드되도록 하려면 -p 또는 –page-requisites 옵션을 추가하세요. - –convert-links 또는 -k: 다운로드된 HTML 파일 내 링크를 원본 URL 대신 로컬에 다운로드된 파일로 가리키도록 수정합니다. 사이트의 로컬 미러를 생성하고 다운로드된 페이지 내 모든 링크가 오프라인에서도 정상 작동하도록 보장할 때 유용합니다.
Bright Data 사이트를 최대 깊이 1로 재귀적으로 다운로드하면서 모든 링크를 로컬 파일로 변환하려면 다음과 같은 Python wget 명령어를 작성해야 합니다:
output, error = execute_command("wget --recursive --level=1 --convert-links https://brightdata.com")
참고: 인터넷 연결 속도에 따라 이 명령어 실행에 시간이 다소 소요될 수 있으니 기다려 주십시오.
이제 brightdata.com 폴더에는 1단계 재귀 깊이로 Bright Data 사이트 파일의 로컬 사본이 포함됩니다.
Python에서 Wget 사용의 장단점
Python에서 wget을 사용할 때의 장단점을 살펴보겠습니다.
장점
- subprocess 모듈 덕분에 Python과 쉽게 통합됩니다.
- 재귀적 다운로드, 자동 재시도, 파일 스탬핑 등 다양한 기능과 옵션을 제공합니다.
- 단일 명령어로 사이트 전체의 로컬 복사본 생성 가능.
- FTP 지원.
- 프록시 통합 지원.
- 중단된 다운로드 복구 기능.
단점
- 출력은 Python 스크립트에서 직접 사용할 수 있는 문자열 변수가 아닌 다운로드된 파일입니다.
- 다운로드된 HTML 파일에서 특정 DOM 요소에 접근하려면Beautiful Soup과같은 파서가 필요합니다.
[추가] 프록시와 함께 Wget 사용하기
wget으로 파일이나 전체 사이트를 다운로드할 때 주요 문제는 요청이 차단될 수 있다는 점입니다. wget 요청은 대상 서버에 봇에서 온 것으로 인식되기 때문입니다. 일부 웹사이트는 페이지 및 리소스에 대한제한을 적용하여이를 방지합니다. 이러한 제한에는 지역 제한, 속도 제한 정책, 스크래핑 방지 조치가 포함될 수 있습니다.
이러한 제한을 우회하기 위한 실용적인 해결책은 wget에프록시 서버를통합하는 것입니다. 프록시는 컴퓨터와 인터넷 사이의 중간 서버 역할을 합니다. wget 트래픽을 프록시 서버를 통해 전달함으로써 IP 노출을 피하고 사이트가 부과하는 대부분의 제한을 우회할 수 있습니다.
더 자세한 사용법은 Wget에서 프록시 사용 방법 가이드를 참조하십시오.
결론
이 글에서는 wget이 무엇인지, requests 라이브러리보다 우수한 점, Python에서 사용하는 방법을 이해하셨습니다. 이제 wget이 HTTP, HTTPS, FTP를 통해 파일과 웹 페이지를 다운로드하는 강력한 도구임을 알게 되셨을 것입니다. 여기서 배운 내용을 바탕으로 Python과 함께 wget을 사용하는 방법을 숙지하셨습니다.
이 가이드에서 보셨듯이, 프록시는 wget과 같은 유틸리티가 콘텐츠를 다운로드하는 것을 막기 위해 사이트가 취하는 모든 반봇(anti-bot) 조치를 피하는 데 훌륭한 도우미가 될 수 있습니다. 문제는 온라인에 수십 개의 공급자가 존재하며 최적의 공급자를 선택하는 것이 쉽지 않다는 점입니다. 시간을 절약하고 시장 최고의공급자인 Bright Data로 바로 가세요!
Bright Data는 포춘 500대 기업 및 20,000명 이상의 고객에게 서비스를 제공하는 세계 최고의 프록시 서버를 운영합니다. 다양한 프록시 유형을 제공합니다:
- 데이터센터 프록시– 77만 개 이상의 데이터센터 IP.
- 주거용 프록시– 195개국 이상에 걸쳐 7,200만 개 이상의 주거용 IP.
- ISP프록시– 70만 개 이상의 ISP IP 주소.
무료 체험으로 시작하거나 당사 데이터 전문가에게 프록시 및 스크래핑 솔루션에 대해 문의하십시오.