- Today
- Total
개발하는 고라니
[Spring] 크롤링된 이미지 다운로드 본문
* '코드로 배우는 스프링 웹 프로젝트' 교재를 1.5회(?) 완독 후, 스스로의 힘으로 게시판을 구현해보았다.
물론 미흡한 점이 심심찮게 발견되어 수정의 수정을 거듭했다. 그렇게 3~4주를 보내고 나니 다음엔 무엇을 만들어볼까 하던 차에, 문득 떠오른 것이 있다.
'무수히 많은 치킨 가게가 있고, 그 많은 메뉴들을 한 곳에서 모아보면 어떨까?'
그래서 프로젝트라고 하기엔 뭣하지만 원하는 작업을 구현해보며 모르는 부분이 있으면 배워가고, 알던 내용이 있으면 다시 되새기는 목적을 가지고 시도해보려 한다.
먼저 '푸라닭' 사이트에서 메뉴 정보들을 크롤링해 뿌려주는 식으로 시작해보고 결과가 괜찮으면 다른 브랜드들도 시도해보는 식으로 점차 넓혀가겠다.
* 저번 포스팅에서 푸라닭 사이트에서 제공하는 메뉴들의 이름 목록을 크롤링하고, Oracle DB에 INSERT하는 작업을 했다.
* 오늘은 푸라닭 사이트에서 제공하는 모든 메뉴들의 이름, 가격, 상품 사진, 상세 설명을 크롤링해서 DB에 INSERT하고 Image를 다운로드하는 내용을 포스팅 하겠다. (DB에 추가하는 내용은 이전 글과 상당히 유사하니 이미지 다운로드에 초점을 맞춘다.)
※ 변경사항
- 크롤링 할 URL 값이 변경되었다. (메뉴들의 목록을 리스트로 보여주는 페이지 --> 메뉴의 상세 페이지)
- 목록의 리스트만 보여주는 곳은 가격 및 설명을 크롤링 할 수 없기 때문에 상품의 상세 페이지에서 긁어오도록 한다
- https://puradakchicken.com/menu/view.asp?idx=i
- 위 URL의 쿼리인 idx의 값에 따라 보여주고자 하는 제품이 달라진다. (5~105까지 for문을 돌리며 크롤링 할 예정)
# 1 Controller
> localhost:8080/crawling/puradak 주소로 GET 요청이 오면 puradakInsert()가 실행된다.
> 푸라닭의 고유번호는 100으로 지정했다. (타 브랜드는 101, 102, 103...)
# 2 크롤링(Crawling) - Service단
> Controller 단에서 넘긴 Url 배열과 브랜드 고유번호 100을 insert() 메서드에 인자로 받아 실행한다.
> 해당 URL의 전체 HTML 코드 중 <div class="photo_view"> 태그의 모든 자식 태그들을 elements 변수에 넣는다.
> <div class="photo_view">의 자식 중 <p class="photo_txt">라는 태그를 content에 넣고 사이즈를 비교하여 0이면 비어있는 페이지이므로 continue로 하위 코드를 실행하지 않는다.
# 3 다운로드 할 IMAGE의 'src'값 가져오기
> 우리가 가져와야 하는 것은 <img src="/upload/menu/xxxx.jpg">태그 내부의 src 속성 값이다.
> 63행에서 위 값을 가져오게 된다. attr("abs:src")는 src라는 속성 값의 절대 경로를 달라는 뜻이므로 URL 뿐 아니라 도메인도 붙어서 오게 된다.
> HttpURLConnection 객체는 Request Header의 "Referer"의 값을 같은 도메인의 값인 푸라닭 홈페이지로 설정하려고 가져와보았다. 네이버에서 웹툰 같은 것을 크롤링하여 다운로드 할 경우, 이전 페이지의 값을 검사 하는데, 이 때 안전하지 않은 경로로부터 요청이 오면 거부하여 에러를 발생시킨다. 하지만 푸라닭 사이트 같은 경우 이전 페이지 검사를 하지 않는 것으로 보인다. 헤더의 Referer는 "이전 페이지"를 나타낸다.
> 위와 같이 코드를 작성 후 실행하면 아래와 같은 에러를 야기한다.
> FileNotFoundException은 파일을 찾지 못했다는 것인데 이게 무슨 말인가 해서 log기록을 보았는데 뭔가 이상하다.
메뉴_PC-750.png가 한글은 자음 모음이 분리가 되어있었다. 이 뿐만 아니라 모든 이미지 파일(한글로 된)에 동일한 에러가 발생했다.
> 찾아보았더니 Window의 NFC와 Mac의 NFD 차이였다. 정말 간단히 설명하자면 NFC는 한글 유니코드를 완성형인 '메뉴' 로 나타내지만 NFD는 'ㅁㅔㄴㅠ'로 나타낸다. 하지만 이것 때문에 에러가 발생하는 것이 아니었다.
> URL Encoding 문제였다. 궁금하면 여러분도 직접 해보는 것을 추천한다.
위 url을 클릭하여 주소창에 있는 글을 복사 후에 메모장에 붙여넣기 해보자.
> 이상하다? 주소창엔 분명 한글로 나오는데 ctrl c+v하면 왜 저렇게 나오는가? 역시 URL Encoding문제였다. 크롬의 주소창에선 아마 자동으로 Decoding 해주는 것으로 안다. 그래서 한글로 잘 나오는 것이다. 그럼 이제 해야할 일은 파일을 다운로드 받는 경로를 위와같이 Encoding해야한다.
# 4 IMAGE 경로 URLEncoding
> 변경하는 법은 매우 간단하다. 기존의 경로인 'https://puradakchicken.com/upload/menu/ㅁㅔㄴㅠ...'에서
'menu/' 뒤의 내용을 인코딩해서 대체해주면 된다.
> 93행의 Nomalizer.normalize()는 'ㅁㅔㄴㅠ'를 '메뉴'로 합쳐주는 역할을 한다
> 이제 실행하면 DB에도 잘 들어가고 이미지 파일도 잘 다운로드 됨을 알 수 있다.
> Log를 보면 인코딩된 Url과 원래의 Url이 다르다. 혹시 파일명이 한글인 이미지 또는 파일이 다운로드가 안될 땐 경로를 인코딩 해보자.
<혼자 공부하며 써놓느라 부족함이 많습니다. 부정확한 부분이나 고쳐야 할 곳이 있다면 댓글 남겨주세요>
'Framework > Spring' 카테고리의 다른 글
[Spring] 로컬 저장소의 이미지 파일 웹에서 보여주기 (0) | 2020.12.17 |
---|---|
[Spring] 'JSON'으로 반환하는 @RestController (0) | 2020.12.16 |
[Spring] 크롤링 해온 정보 DB에 저장 (0) | 2020.12.14 |
[Spring MVC] JSON 출력하기 (0) | 2020.12.08 |
[Spring MVC] @RestController String의 한글 처리 (0) | 2020.12.08 |