파이썬 크롤링 - urllib.request로 크롤링

안녕하세요 jay입니다.
지난 시간에는 크롤링과 스크레이핑에 대해 간단하게 정의를 내려보았습니다.
링크 : https://classicismist.blogspot.com/2020/01/blog-post_19.html
이번 시간은 urllib으로 웹페이지를 직접 크롤링을 해보도록 하겠습니다.

1. urllib.request 함수들

from urllib.request import urlopen

f = urlopen('http://www.hanbit.co.kr/store/books/full_book_list.html') # 크롤링 하고 싶은 url 지정
# 해당 url의 http 응답본문(bytes type)을 추출
print(f.read()) # b'<!DOCTYPE html>\r\n<html lang="ko">\r\n<head>\r\n<!......
print(f.status) # 200(응답이 되었다는 의미)
# http의 헤더값을 추출
print(f.getheader('Content-Type')) # text/html; charset=UTF-8
encoding = f.info()
print(encoding)
"""
        Date: Sun, 19 Jan 2020 04:35:11 GMT
        Server: Apache
        X-Powered-By: PHP/5.3.3
        Set-Cookie: PHPSESSID=rtsnrufja0rpamesvs1b8c75g6; path=/
        Expires: Thu, 19 Nov 1981 08:52:00 GMT
        Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
        Pragma: no-cache
        Connection: close
        Transfer-Encoding: chunked
        Content-Type: text/html; charset=UTF-8
"""

urlopen() : urlopen에 크롤링 하고 싶은 웹사이트 주소를 적고, 변수 f에 저장을 합니다.
                f의 타입은 <class 'http.client.HTTPResponse'>입니다.

f.read() : read함수로 추출한 값은 해당 웹페이지의 bytes 자료형입니다. 필요한 자료를 얻기 위해선
str타입으로 디코딩을 해야합니다. HTML5의 기본 인코딩 방식이 대부분 UTF-8이므로
디코딩도 UTF-8 형식으로 하면 됩니다. 하지만 여러가지 인코딩 방식이 섞여 있을 수 있으니
HTTP 헤더의 정보를 참조해 인코딩 방식을 추출해 적절한 방식으로 디코딩하면 됩니다.

f.getheader('Content-Type') : HTTP 헤더의 정보 중 인코딩 정보를 추출해주는 명령어입니다.
이에 맞춰 디코딩을 해주면 됩니다.

encoding = f.info() : 우리가 원하는 사이트의 정보를 출력해주는 명령어 입니다.

2. 본격적으로 크롤링


from urllib.request import urlopen

# 크롤링 하고 싶은 url 지정
f = urlopen('http://www.hanbit.co.kr/store/books/full_book_list.html') 

# 헤더 내용 중 charset내용만 가져오게 함, failobj : 만약 헤더가 명시 안되어 있으면 utf-8이라고 가정
encoding=f.info().get_content_charset(failobj="utf-8")

print(encoding) # utf-8

# url의 HTTP 응답 본문을 추출하고, encoding 방식으로 decode하라
text=f.read().decode(encoding)

# decoding 된 결과물
print(text)
"""
    <!DOCTYPE html>
    <html lang="ko">
    <head>
    <!--[if lte IE 8]>
    <script>
      location.replace('/support/explorer_upgrade.html');
    </script>
    <![endif]-->
    <meta charset="utf-8"/>
    .........
    ...........
"""

1. 먼저 urlopen()를 이용하여 크롤링하기 원하는 url을 지정합니다.

2. encoding = f.info().get_content_charset(failobj="utf-8")
해당 url의 정보 중 charset내용만 읽어와서 encoding 변수에 저장합니다.(즉 해당 url 페이지의 인코딩 방식), 만약 헤더가 명시 안되어 있으면 utf-8로 가정합니다(대부분 utf-8 헤더이기 때문)

3.  text = f.read().decode(encoding)
해당 url의 HTTP응답 본문을 추출하고, encoding 방식으로 decode를 합니다.

3. 주의할 점

HTTP 헤더에서 추출한 인코딩 정보가 항상 맞는 것은 아닙니다.
따라서 HTML 내부의 meta tag를 확인해서 결정합니다.

meta tag란 : 문서 자체를 설명하는 태그, 어떤 내용을 담고 있고, 그 문서의 핵심 키워드는 무엇이며, 누가 만들어 있는지 등 정보를 담고 있는 태그

meta tage 예시 :

<meta charset="utf-8">
<meta http-equiv="Content-Type" content="text/html; charset=EUC_KR">

4. 정리

urllib.request로 크롤링을 하려면 
1. 크롤링하기 원하는 url을 가져온다.
2. 해당 url의 HTTP 헤더 내용 중 charset 내용만 가져온다
3. 해당 url의 HTTP 응답 본문을 가져오고, 가져온 encoding 내용으로 decode를 한다.

댓글