[Python 모듈] urllib : URL을 다루기 위한 모듈

1. urllib 모듈이란?

 

urllib 모듈은 파이썬에서 URL을 다루기 위한 모듈입니다. 이 모듈은 HTTP, FTP, SMTP 등과 같은 프로토콜을 사용하여 URL을 열고 읽고 쓰는 기능을 제공합니다. 

 

  • HTTP(HyperText Transfer Protocol) : 웹 상에서 문서, 이미지, 동영상 등 다양한 리소스를 전송하기 위한 프로토콜입니다.
  • FTP (File Transfer Protocol) : 컴퓨터 간에 파일을 송수신하기 위해 사용되며, 로컬과 원격 시스템 간의 파일 전송을 쉽게 할 수 있습니다.
  • SMTP (Simple Mail Transfer Protocol)  : 이메일 클라이언트와 메일 서버 간의 통신에 사용되며, 메일 서버에서 메일 서버로 메시지를 전달합니다. 

 

urllib 모듈은 별도의 설치 과정이 필요없습니다. 모듈을 사용하려면 아래와 같이 import를 하면 됩니다.

import urllib

 


2. urllib.request

 

urllib.request는 다양한 방식으로 URL을 열고 데이터를 가져오는 기능을 제공합니다.

 


2.1 urlopen()

 

urlopen() 함수는 URL을 열어서 HTTPResponse 객체를 반환하는 함수입니다. 이 함수는 HTTP, HTTPS, FTP 등의 프로토콜을 지원합니다. urlopen() 함수는 하나의 인자를 받습니다. 이 인자는 열고자 하는 URL을 나타내는 문자열입니다. urlopen() 함수를 호출하면 URL을 열어서 HTTPResponse 객체를 반환합니다. 이 객체는 read() 메서드를 사용하여 응답 본문을 가져올 수 있습니다.

 

코드에서는 urlopen() 함수를 사용하여 'https://www.example.com' URL을 열고, 반환된 HTTPResponse 객체에서 read() 메서드를 사용하여 웹 페이지의 HTML 코드를 읽어들입니다. 

import urllib.request

response = urllib.request.urlopen('https://www.example.com')
html = response.read()

print(html)

 


2.2 urlretrieve()

 

urlretrieve() 함수는 URL에서 파일을 다운로드하는 함수입니다. 이 함수는 URL에서 데이터를 읽어서 로컬 파일로 저장합니다. urlretrieve() 함수는 두 개의 인자를 받습니다. 첫 번째 인자는 다운로드하려는 파일의 URL을 나타내는 문자열입니다. 두 번째 인자는 로컬에 저장할 파일 경로를 나타내는 문자열입니다.

 

코드에서는 urlretrieve() 함수를 사용하여 'https://www.example.com/image.jpg' URL에서 이미지 파일을 다운로드하고, 로컬 파일 'image.jpg'로 저장합니다. 

import urllib.request

url = 'https://www.example.com/image.jpg'
filename = 'image.jpg'

urllib.request.urlretrieve(url, filename)

 


2.3 Request

 

Request는 urllib.request 모듈에 포함된 클래스 중 하나입니다. 이 클래스는 HTTP 요청을 만들기 위한 클래스로, 헤더 정보, 쿠키 정보 등을 설정할 수 있습니다. HTTP 요청을 보낼 때 사용되는 GET, POST, PUT, DELETE 등의 메서드를 설정할 수 있습니다. Request는 두 개의 인자를 받습니다. 첫 번째 인자는 URL을 나타내는 문자열입니다. 두 번째 인자는 옵션을 나타내는 딕셔너리입니다. 딕셔너리의 키는 헤더 정보를 나타내는 문자열이며, 값은 해당 헤더 정보의 값입니다.

 

아래 코드는 Python언어로 작성된 웹 스크레이핑 코드입니다. (웹스크레핑이란 웹 사이트에서 원하는 정보를 추출하는 과정을 말합니다.) 코드에서는 urllib.parse 모듈의 urlencode를 사용하여 URL에 데이터를 추가합니다. HTTP 요청을 만들고, 헤더 정보를 설정합니다. 코드의 urlencode는 아래 4.2에서 설명합니다.

 

  • 3 : 검색어인 'python'을 'data' 딕셔너리에 할당합니다. 여기서 'q' : 'python'은 검색어 파라미터를 나타냅니다.
  • 4 : urlencode를 사용하여 data 딕셔너리를 URL 인코딩된 문자열로 변환합니다. 이 경우, 변환된 문자열은 'q=python'이 됩니다.
  • 5: 변환된 문자열을 URL 끝에 붙여 완성된 URL을 생성합니다.
  • 6: 여기서 User-Agent는 웹 브라우저의 종류를 나타내고 Referer는 요청이 시작된 웹페이지의 URL을 나타냅니다.
import urllib.request
import urllib.parse

url = 'https://www.example.com/search'
data = {'q': 'python'}

data = urllib.parse.urlencode(data)
url = url + '?' + data

headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)',
    'Referer': 'https://www.example.com'
}

req = urllib.request.Request(url, headers=headers)
response = urllib.request.urlopen(req)

html = response.read()
print(html)

 


2.4 build_opener()

 

build_opener() 함수는 OpenerDirector 객체를 만드는 함수입니다. OpenerDirector 객체는 URL을 열 때 다양한 기능(쿠키 처리, 인증 처리 등)을 수행할 수 있습니다. build_opener() 함수는 urllib.request 모듈의 기본 오프너를 사용하여 OpenerDirector 객체를 만듭니다. OpenerDirector 객체는 다음과 같은 기능을 제공합니다.

 

  • HTTPBasicAuthHandler : HTTP 인증 처리를 수행합니다.
  • HTTPCookieProcessor : 쿠키 처리를 수행합니다.
  • ProxyHandler : 프록시 서버를 사용하여 URL을 엽니다.
  • HTTPSHandler : HTTPS 프로토콜을 사용하여 URL을 엽니다.

 

아래 코드에서는 기본 오프너 대신 커스텀 오프너를 사용하여 쿠키 처리와 HTTPS 처리를 추가했습니다. urllib.request 모듈의 HTTPCookieProcessor() 함수와 HTTPSHandler() 함수를 사용하여 쿠키 처리기와 HTTPS 처리기를 만듭니다. build_opener() 함수를 사용하여 이들을 결합하여 OpenerDirector 객체를 만들고, 이 객체를 사용하여 'https://www.example.com' URL을 엽니다.

import urllib.request

# 쿠키 처리기
cookie_handler = urllib.request.HTTPCookieProcessor()

# HTTPS 처리기
https_handler = urllib.request.HTTPSHandler()

# OpenerDirector 객체 생성
opener = urllib.request.build_opener(cookie_handler, https_handler)

# OpenerDirector 객체를 사용하여 URL 열기
response = opener.open('https://www.example.com')

html = response.read()
print(html)

 


2.5 HTTPPasswordMgrWithDefaultRealm

 

HTTPPasswordMgrWithDefaultRealm() 클래스는 urllib.request 모듈에 포함된 클래스 중 하나입니다. 이 클래스는 HTTP 인증 정보를 저장하기 위한 클래스로, HTTPPasswordMgrWithDefaultRealm 객체를 만들고 add_password() 메서드를 사용하여 인증 정보를 등록합니다. 이 클래스는 웹 사이트별로 인증 정보를 저장합니다. 여러 웹 사이트에서 같은 사용자 이름과 비밀번호를 사용하는 경우, HTTPPasswordMgrWithDefaultRealm() 클래스를 사용하여 인증 정보를 저장할 수 있습니다.

 

코드에서는 HTTPPasswordMgrWithDefaultRealm 클래스를 사용하여 HTTP 인증 정보를 등록합니다. HTTPBasicAuthHandler() 함수를 사용하여 인증 처리기를 만들고, 이를 OpenerDirector 객체에 등록합니다. 이 객체를 사용하여 'https://www.example.com' URL을 엽니다. 

 

코드에서 add_password()는 인증 정보를 비밀번호 관리자 객체에 등록하는 메서드입니다. 여기서 None은 기본 영역(모든 영역에 대한 인증 정보를 저장, 모든 요청에 대해 등록된 인증 정보를 사용)을 의미하며, url, username, password는 각각 웹페이지의 URL, 사용자 이름, 비밀번호를 나타냅니다.

import urllib.request

username = 'alice'
password = 'password'

url = 'https://www.example.com'

# HTTPPasswordMgrWithDefaultRealm 객체 생성
password_mgr = urllib.request.HTTPPasswordMgrWithDefaultRealm()

# 인증 정보 등록
password_mgr.add_password(None, url, username, password)

# 인증 처리기 등록
handler = urllib.request.HTTPBasicAuthHandler(password_mgr)

# OpenerDirector 객체 생성
opener = urllib.request.build_opener(handler)

# OpenerDirector 객체를 사용하여 URL 열기
response = opener.open(url)

html = response.read()
print(html)

 


3. urllib.error

 

urllib.error 모듈은 urllib.request 모듈에서 발생하는 예외를 처리하기 위한 예외 클래스를 제공합니다.

 


3.1 URLError

 

URLError 클래스는 urllib.request 모듈에서 발생하는 예외 중 하나로, URL 열기 작업에서 발생하는 예외를 처리하기 위한 클래스입니다. 이 예외는 다양한 이유로 발생할 수 있습니다. 예를 들어 DNS 오류, 연결 오류, 리디렉션 오류 등이 있습니다.

 

코드에서는 'https://www.example.com/notexist' URL을 열려고 시도합니다. URL이 잘못되었기 때문에 URLError 예외가 발생합니다. 이 예외를 처리하기 위해 try-except 블록을 사용합니다. 

import urllib.request
import urllib.error

url = 'https://www.example.com/notexist'

try:
    response = urllib.request.urlopen(url)
except urllib.error.URLError as e:
    print(e)

 


3.2 HTTPError

 

HTTPError 클래스는 urllib.request 모듈에서 발생하는 예외 중 하나로, HTTP 요청에서 발생하는 예외를 처리하기 위한 클래스입니다. 이 예외는 서버에서 '404 Not Found'와 같은 오류 응답을 반환하는 경우 발생합니다. HTTPError 예외는 code 속성과 read() 메서드를 제공합니다. code 속성은 서버에서 반환된 HTTP 상태 코드를 나타내며, read() 메서드는 오류 응답의 내용을 반환합니다.

 

코드에서는 'https://www.example.com/notexist' URL을 열려고 시도합니다. URL이 잘못되었기 때문에 HTTPError 예외가 발생합니다. 이 예외를 처리하기 위해 try-except 블록을 사용합니다. 

import urllib.request
import urllib.error

url = 'https://www.example.com/notexist'

try:
    response = urllib.request.urlopen(url)
except urllib.error.HTTPError as e:
    print(e.code, e.reason, e.read())

 


3.3 ContentTooShortError

 

ContentTooShortError 클래스는 urllib.request 모듈에서 발생하는 예외 중 하나로, 응답 내용의 크기가 지정된 크기보다 작은 경우 발생하는 예외를 처리하기 위한 클래스입니다. 이 예외는 일반적으로 웹 페이지의 응답 내용이 기대한 내용보다 작은 경우 발생합니다. ContentTooShortError 예외는 그룹화된 응답 객체를 반환합니다. 이 객체는 content 속성과 expected_content_length 속성을 제공합니다. content 속성은 서버에서 반환된 응답 내용을 나타내며, expected_content_length 속성은 서버에서 반환되어야 하는 응답 내용의 크기를 나타냅니다.

 

코드에서는 'https://www.example.com' URL을 열고 응답 내용을 읽은 후, 응답 내용이 1000 바이트보다 작은 경우 ContentTooShortError 예외가 발생합니다. 이 예외를 처리하기 위해 try-except 블록을 사용하고, ContentTooShortError 예외에서 제공하는 그룹화된 응답 객체를 사용하여 예외를 처리합니다.

import urllib.request
import urllib.error

url = 'https://www.example.com'

try:
    response = urllib.request.urlopen(url)
    content = response.read()
    if len(content) < 1000:
        raise urllib.error.ContentTooShortError('Content too short', content)
except urllib.error.ContentTooShortError as e:
    print('Error:', e)
    print('Expected content length:', e.expected_content_length)
    print('Actual content length:', len(e.content))

 


4. urllib.parse

 

urllib.parse 모듈은 URL을 구성 요소로 분리하고, URL을 인코딩하고 디코딩하며, URL 쿼리 문자열을 구문 분석하는 등의 기능을 제공합니다.


4.1 urlparse()

 

urlparse() 함수는 URL을 구성 요소로 분리하는 데 사용됩니다. 이 함수는 파싱된 URL의 구성 요소를 나타내는 NamedTuple 객체를 반환합니다. NamedTuple은 불변한 객체로, 각 구성 요소에 이름을 지정하여 해당 요소에 쉽게 접근할 수 있습니다. 일반적으로 URL을 파싱하여 호스트, 경로, 쿼리 문자열, 프래그먼트 등의 구성 요소를 추출하는 데 사용됩니다.

 

코드에서는 ' https://www.example.com/path/to/page.html?id=123#section1' URL을 파싱하여 NamedTuple 객체를 반환합니다. 반환된 NamedTuple 객체는 각 구성 요소에 이름이 지정되어 있으므로, 이를 통해 쉽게 각 구성 요소에 접근할 수 있습니다. 

from urllib.parse import urlparse

url = 'https://www.example.com/path/to/page.html?id=123#section1'

parsed_url = urlparse(url)

print(parsed_url.scheme)
print(parsed_url.netloc)
print(parsed_url.path)
print(parsed_url.params)
print(parsed_url.query)
print(parsed_url.fragment)

 


4.2 urlencode()

 

urlencode() 함수는 딕셔너리를 URL 쿼리 문자열로 인코딩하기 위해 사용됩니다. 이 함수는 딕셔너리의 키-값 쌍을 인코딩하여 URL 쿼리 문자열을 생성합니다. urlencode() 함수는 주로 웹 애플리케이션에서 GET 요청의 쿼리 문자열을 생성하는 데 사용됩니다.

 

코드에서는 딕셔너리를 생성하고, 이를 urlencode() 함수에 전달하여 URL 쿼리 문자열을 생성합니다. 이를 통해 생성된 URL 쿼리 문자열을 기존 URL과 조합하여 새로운 URL을 만듭니다. 

from urllib.parse import urlencode

params = {'name': 'Alice', 'age': 25, 'city': 'New York'}

query_string = urlencode(params)

url = 'https://www.example.com/search?' + query_string

print(url)

 


4.3 parse_qs()

 

parse_qs() 함수는 URL 쿼리 문자열을 파싱하여 딕셔너리로 반환하는 데 사용됩니다. 이 함수는 URL 쿼리 문자열의 각 키-값 쌍을 딕셔너리에 저장하고 반환합니다. parse_qs() 함수는 주로 웹 애플리케이션에서 GET 요청의 쿼리 문자열을 파싱하는 데 사용됩니다.

 

코드에서는 URL 쿼리 문자열을 생성하고, 이를 parse_qs() 함수에 전달하여 파싱된 딕셔너리를 반환합니다. 반환된 딕셔너리는 각 키-값 쌍을 저장하고 있으므로, 이를 통해 쉽게 각 키의 값을 추출할 수 있습니다. 

from urllib.parse import parse_qs

query_string = 'name=Alice&age=25&city=New+York'

params = parse_qs(query_string)

print(params['name'])
print(params['age'])
print(params['city'])

 


4.4 quote()

 

quote() 함수는 URL 안전 문자열로 인코딩하기 위해 사용됩니다. 이 함수는 문자열의 특정 문자를 URL 안전 문자열로 인코딩하여 반환합니다. 인코딩된 문자열은 URL의 일부로 사용될 수 있습니다. quote() 함수는 대부분의 ASCII 문자를 인코딩하지 않고, 일부 특수 문자만 인코딩합니다. 이 함수는 주로 URL에 포함될 수 없는 문자를 처리하는 데 사용됩니다.

 

코드에서는 문자열을 생성하고, 이를 quote() 함수에 전달하여 URL 안전 문자열로 인코딩합니다. 이를 통해 생성된 인코딩된 문자열을 기존 URL과 조합하여 새로운 URL을 만듭니다. 

from urllib.parse import quote

url = 'https://www.example.com/search?q=' + quote('Alice & Bob')

print(url)

4.5 unquote()

 

unquote() 함수는 URL 안전 문자열을 디코딩하기 위해 사용됩니다. 이 함수는 URL 안전 문자열로 인코딩된 문자열을 디코딩하여 반환합니다. unquote() 함수는 quote() 함수와 반대로 동작합니다. 

 

코드에서는 URL을 생성하고, 이를 파싱하여 딕셔너리로 변환합니다. 이를 통해 URL 안전 문자열로 인코딩된 문자열을 디코딩하고, 디코딩된 값을 딕셔너리에 저장합니다. 

from urllib.parse import unquote

url = 'https://www.example.com/search?q=Alice%20%26%20Bob'

query_string = url.split('?')[1]

params = {}

for param in query_string.split('&'):
    key, value = param.split('=')
    params[key] = unquote(value)

print(params['q'])

 


5. urllib.robotparser

 

urllib.robotparser 모듈은 robots.txt 파일의 구문을 분석하고 해당 URL이 로봇에 의해 접근 가능한지 확인하는 데 사용됩니다. (robots.txt 파일은 웹 서버에서 제공되는 텍스트 파일로, 로봇이 해당 서버의 페이지에 접근할 때 참고하는 지침서입니다. 이 파일은 웹 서버의 루트 디렉터리에 저장되며, 로봇이 이를 통해 접근 가능한 페이지와 배제되어야 할 페이지를 알 수 있습니다.) urllib.robotparser 모듈은 robots.txt 파일을 다운로드하고 해당 URL이 로봇에 의해 접근 가능한지 여부를 결정합니다. 이를 통해 웹 크롤러가 로봇 배제 표준을 준수하도록 도와주며, 웹 서버의 부하를 줄이는 데에도 도움이 됩니다.

 

코드에서는 웹 사이트의 URL을 생성하고, RobotFileParser 객체를 생성하여 해당 URL의 robots.txt 파일을 다운로드합니다. 이를 통해 can_fetch() 메서드를 사용하여 해당 URL이 로봇에 의해 접근 가능한지 여부를 확인합니다. 

from urllib.robotparser import RobotFileParser

url = 'https://www.example.com'
rp = RobotFileParser()
rp.set_url(url + '/robots.txt')
rp.read()

if rp.can_fetch('*', url):
    print('Allowed to access:', url)
else:
    print('Not allowed to access:', url)