* 이 실습은 공부에만 사용하였습니다
< 도전 과제 >
1. 웹툰 최신화 이미지 다운로드 크롤러 만들기
2. 웹툰 최신 10화 이미지 다운로드 크롤러 만들기
1. 기본 개념
1) 크롤링(crawling)이란?
크롤링이란 웹 크롤러에서 출발한 말로 인터넷 상의 페이지를 수집해 분류하고 저장한 후 나중에 쉽게 찾아볼 수 있도로 도와주는 일종의 봇이다.
2) 크롤링에 필요한 모듈
(1) urllib
- URL 처리 모듈로 URL 작업을 위한 여러 모듈을 모아놓은 패키지다
- 파이썬에서 웹과 관련한 데이터들을 손쉽게 이용할 수 있도록 도와준다
- urllib는 내장된 라이브러리에 있어 따로 설치하지 않아도 사용이 가능하다
- urllib에는 총 4가지 종류의 모듈이 있다. 우리는 그중 requet만 사용할 예정이다
· URL을 열고 읽기를 도와주는 request
· request에 의해 발생한 예외를 다루는 error
· URL 구문 분석을 도와주는 parse
· robots.txt 파일을 분석하기 위한 robotparser
- urllib.request
import urllib.request
· URL을 가져오기 위한 파이썬 모듈
· 모듈은 기본 & 다이제스트 인증, 수정, 쿠키 등과 같은 복잡한 환경을 처리해 URL을 가져오는 것을 도와주는 기능을 함
· 웹툰 크롤러를 만들 때 사용할 함수는 urlopen과 build_opener이다
▶ urlopen : 웹 페이지에서 얻은 데이터에 대한 객체를 반환해준다
result = urllib.request.urlopen("http://www.naver.com")
print(result)
# 결과 => <http.client.HTTPResponse object at 0x000002753E729548>
▶ build_opener
opener = urllib.request.build_opener()
opener.addheaders=[('User-Agent','Mozilla/5.0')]
urllib.request.install_opener(opener)
≫ 단일 함수 호출로 오퍼너 객체를 만드는 것이다
≫ 사용자가 직접 처리기에 대해 만들 수 있다
≫ 같이 사용하는 install_opener를 통해 build_opener로 만든 오프너를 기본 오프너로 만들 수 있다
≫ opener가 현재 어떤 브라우저를 이용해 접근할지 정할 수 있는데 이는 addheaders를 통해 User-Agert 헤더에 값을 넣을 수 있다
User-Agent :
사용자를 대신해 일을 수행하는 소프트웨어 agent이다. 헤더 필드로 전달되어 소프트웨어 업체, 버전을 식별하기도 한다
브라우저 | User-Agent String |
Mac OS Chrome |
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36 |
Mac OS Firefox |
Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:64.0) Gecko/20100101 Firefox/64.0 |
Mac OS Safari |
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0.2 Safari/605.1.15 |
iOS Chrome |
Mozilla/5.0 (iPhone; CPU iPhone OS 12_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/71.0.3578.89 Mobile/15E148 Safari/605.1 |
Android Chrome |
Mozilla/5.0 (Linux; Android 8.0.0; SAMSUNG-SM-G950N/KSU3CRJ1 Build/R16NW) pleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/8.2 Chrome/63.0.3239.111 Mobile Safari/537.36 |
Windows IE11 |
Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; .NET4.0C; .NET4.0E; rv:11.0) like Gecko |
Windows Edge |
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.140 Safari/537.36 Edge/17.17134 |
Windows Chrome |
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36 |
Windows Firefox |
Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:63.0) Gecko/20100101 Firefox/63.0 |
(2) Beautifulsoup
- 파이썬 패키지 중 하나로 HTML이나 XML 문서를 파싱할 때 사용한다. 이를 통해 추출한 데이터들을 사용할 수 있게 도와줌
- python 2.7과 python 3에서 사용 가능
- HTML, XML 문서를 읽고 해석해 태그명, 속서영, 속성값, 앨리먼트 내용을 분리해주는 프로그램이다
- 주어진 정보를 내가 원하는 대로 가공해 서버에서 원하는 때 불러올 수 있도록 도와준다
- urllib 모듈과는 다르게 따로 설치가 필요하다 (python 디렉토리 cmd창에서 Scripts 폴더로 이동해 설치한다)
pip install beautifulsoup4
- 이 모듈을 이용해 원하는 페이지를 파싱할 수 있다
# html은 urllib.urlopen을 통해 요청한 페이지다
result = BeautifulSoup(html.read(), "html.parser")
* parsing
· 어떤 페이지에서 내가 원하는 데이터를 특정 패턴이나 순서로 추출해 정보로 가공하는 것
· 문법적으로 해부라는 뜻으로 기계어를 번역한다고 이해할 수 있음
· 일련의 문자열을 의미 있는 토큰으로 분해해 토큰들로 이루어진 Parse tree를 만드는 과정
(3) os
- Operating System의 약자로 운영체제에서 제공되는 여러 기능을 파이썬에서 수행할 수 있게 해준다
- urllib 모듈처럼 내장된 모듈이기 때문에 다로 설치가 필요없다
- 이번 과제에서 사용할 주요 함수
· getcwd() : 현재 경로를 알려줌
path = os.getcwd()
print(path)
# 결과 => C:\Users\jamie\Desktop\SWING\2학년 1학기\3. python\swing_python
· chdir() : 원하는 디렉토리로 이동
# 원하는 디렉토리로 이동
os.chdir("week 4")
path = os.getcwd()
print(path)
# 결과 => C:\Users\jamie\Desktop\SWING\2학년 1학기\3. python\swing_python\week 4
# 이전 디렉토리로 이동
os.chdir("..")
path = os.getcwd()
print(path)
# 결과 => C:\Users\jamie\Desktop\SWING\2학년 1학기\3. python\swing_python
· mkdir() : 현재 지정된 경로에 새로운 디렉토리 생성
os.mkdir("hello") # 현재 경로에 hello라는 이름의 디렉토리 생성
os.chdir("hello") # 새로 만든 hello 디렉토리로 이동
os.mkdir("world") # 현재 경로인 hello 디렉토리에 world라는 이름의 디렉토리 생성
2. 웹툰 최신 이미지 다운로드 크롤러 만들기
- 원하는 웹툰 페이지에서 가장 최신에 올라온 화의 웹툰 이미지들을 다운로드하는 크롤러이다.
1) 웹툰 제목 가져오기
- 원하는 웹툰 페이지 URL로 요청하고 파싱하여 웹툰 제목 추출하기
# 크롤링할 웹툰 선택해 주소로 웹 페이지 요청
html = urllib.request.urlopen("https://comic.naver.com/webtoon/list.nhn?titleId=694946&weekday=mon")
result = BeautifulSoup(html.read(), "html.parser") # 요청한 웹 페이지 파싱
# 웹툰 이름 불러오기 split()하면 리스트에 웹툰 이름과 QTT가 저장됨 그중 [0]이 웹툰 제목
name = result.find("div", {"class", "detail"}).find("h2").text.split()[0]
2) 웹툰 제목으로 디렉토리 생성
- 만약 웹툰 제목의 디렉토리가 이미 있다면 생성하지 않음
# 파일을 저장하고 싶은 경로로 이동하기
os.chdir("week 4")
path = os.getcwd()
if not os.path.isdir(name): # 만약 만들려는 폴더 (웹툰 제목인 폴더)가 없다면 폴더 생성
os.mkdir(name)
os.chdir(name) # 만든(혹은 만들어져 있던) 폴더로 경로 이동
3) 가장 최신화 URL 가져오기
- 가장 최신화의 URL은 a태그에 있는 'href'의 값이다
- 가져온 URL 앞에 "https://comic.naver.com"을 붙여
# 웹툰 에피소드 하나의 url찾기 (한 화만 가져오므로 findAll이 아닌 find로 하나만 찾기)
newEpi = result.find("td", {"class", "title"})
# 원하는 에피소드 주소로 요청하고 파싱하기
newEpi_html = urllib.request.urlopen("https://comic.naver.com" + newEpi.a['href'])
newEpi_result = BeautifulSoup(newEpi_html.read(), "html.parser")
4) 웹툰 이미지 URL 가져오기
# div의 class가 wt_viewer인 가장 첫번째가 웹툰 이미지 영역임
img = newEpi_result.find("div", {"class", "wt_viewer"})
imgUrl = img.findAll("img") # class가 wt_viewer인 영역에서 img만 모두 가져오기 -> 웹툰 이미지
5) 네이버에게 봇이 아님을 보여주기
- 네이버와 같은 대형 사이트는 urllib.request 모듈을 이용해 접근한 것을 봇이라고 판단하여 403 에러를 발생시킴
- 403 에러는 요청이 금지되엇다는 의미로 이미지에 접근하는 것을 막아 당연히 다운로드도 불가능하게 된다
opener = urllib.request.build_opener()
opener.addheaders=[('User-Agent','Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1941.0 Safari/537.36')]
urllib.request.install_opener(opener)
6) 파일에 이미지 저장하기
- urlretrieve()는 현재 경로에 url 주소에 대한 이미지를 지정한 이름으로 저장하는 기능을 수행한다
- 현재 이미지 이름은 1부터 시작해 +1씩 시켰다. 또한, 확장자명을 뒤에 붙여주어야 한다
num = 1 # 이미지 이름 변수
for url in imgUrl: # 찾은 imgUrl이 있을 때까지 반복
save = str(num) + ".jpg" # 이미지 이름 + 확장자명 하나로 저장
urllib.request.urlretrieve(url.get("src"), save) # 이미지 url을 통해 다운로드
print(str(num) + "번째 이미지 저장 성공") # 성공했다는 의미의 문자열 출력
num = num + 1 # 이미지 이름 + 1
print("이미지 저장 완료") # 이미지 다운로드가 모두 완료되면 완료했다는 문자열 출력
- 현재 지정된 경로에 웹툰 이미지들을 차례대로 .jpg 확장자로 저장한다
3. 웹툰 최신 10화 이미지 다운로드 크롤러 만들기
- 웹툰 이미지를 다운받는 방법은 위 방법과 같은 방식이다
- 다른 점은 한 화에 대한 폴더가 아닌 최신 10화에 대한 이미지를 다운 받을 때 각 페이지에 요청하고 파싱해 각 화별 폴더를 만들어야 하는 것이다
- 경로 지정과 봇이 아님을 보여주는 코드는 위와 같기에 생략하겠다
1) 각 화의 제목 가져오기
- 위 과제에서는 한 화에 대한 정보만 가져왔으면 됐지만 이번 과제에서는 최신 10화에 대한 정보를 모두 가져와야함
- find()가 아닌 findAll()로 첫 페이지에있는 10화에 대한 정보를 모두 가져온다
# 웹툰 에피소드 하나의 url찾기 (첫 페이지의 최신 10화를 가져오므로 모두 가져와야 함 -> findAll 사용)
newEpi = result.findAll("td", {"class", "title"})
2) 각화에 대한 이미지 다운로드
- 각 화에 대한 제목으로 폴더를 만들고 그 화에 대한 이미지를 각 폴더에 저장한다
- 전체적인 틀은 같기 때문에 주석을 통해 첫 과제와 다른 부분들만 설명하겠다
# 화마다 해당 화 제목으로 파일 생성후 경로 이동 (첫 페이지에 있는 화수가 끝날 때 까지 반복)
for epi in newEpi:
epi_title = epi.text.split("\n")[1] # 해당 화의 제목 가져오기
if not os.path.isdir(epi_title): # 제목으로 만들어진 폴더가 있는지 확인 후 없으면 폴더 생성
os.mkdir(epi_title)
os.chdir(epi_title) # 만든(혹은 만들어져 있던) 폴더로 경로 이동
epi_html = urllib.request.urlopen("https://comic.naver.com" + epi.a['href'])
epi_result = BeautifulSoup(epi_html.read(), "html.parser
img = epi_result.find("div", {"class", "wt_viewer"})
imgUrl = img.findAll("img")
num = 1
print(epi_title + " 이미지 저장 시작")
for url in imgUrl:
save = str(num) + ".jpg"
urllib.request.urlretrieve(url.get("src"), save)
print(str(num) + "번째 이미지 저장 성공")
num = num + 1
print(epi_title + " 이미지 저장 완료\n\n
os.chdir("..") # 다음 화의 폴더로 이동하기 위해 현재 경로에서 이전 디렉토리로 이동
print("모든 이미지 저장 완료")
* 다운로드한 웹툰 이미지는 실습이 끝난 뒤에 모두 삭제하였습니다.
< 출처 >
위키피디아 https://en.wikipedia.org/wiki/Parsing
Python.org https://docs.python.org/3/library/urllib.html=
Chrome.com https://developer.chrome.com/multidevice/user-agent
네이버 블로그 https://blog.naver.com/ued_123/221552494873
'Study > Python' 카테고리의 다른 글
Python으로 게임 매크로 만들기 (0) | 2020.06.06 |
---|---|
[Python] 문자열과 리스트 함수 문법 (0) | 2020.04.12 |
댓글