[Python_mini_projects_3] 카카오 Open Api 이미지 크롤링
카카오 Open API로 사진 크롤링 하기
1. 카카오 developers 가입 후 APP KEY 받기
Open API를 이용하기 위해서는 해당 제공처에서 개인적으로 제공해주는 APP KEY를 받아야 한다.
-
카카오 개발자 사이트(https://dvelopers.kakao.com)에 접속하여 회원가입을 해준다.
-
로그인 후 상단[내 애플리케이션] 버튼 클릭
-
앱 이름과 회사 이름 작성 후 [저장]
(앱 이름과 회사 이름은 자유롭게 작성해도 된다. 무직이라해도 슬퍼하지 말자.)
-
내 애플리케이션에 생성된 애플리케이션 목록이 보인다. 클릭
-
발급받은 앱 키를 확인한다. 여기서 이용할 키는 ‘REST API’키 이다.
2. Python - 파일 읽고 쓰기
#파일 쓰기
data = "hello"
with open("test.txt", "w") as fp:
fp.write(data)
data 변수에 입력하고 싶은 내용을 적고 write(쓰기모드)로 open 해주면 작업하는 디렉터리에 test.txt 파일이 생성된 것을 확인할 수 있다.
test.txt 파일에 hello가 적혀있는 것을 볼 수 있다.
# 파일 읽기
with open("test.txt", "r") as fp:
print("========= [파일 읽기 결과] =========")
print(fp.read())
쓰기모드로 쓴 test.txt 파일을 read(읽기모드)로 읽어보겠다.
요청한대로 print된 것을 볼 수 있다.
3. 웹에 있는 이미지 파일 저장하기
https://search1.kakaocdn.net/argon/600x0_65_wr/ImZk3b2X1w8
해당 링크에 들어가보면
귀엽게 보이는 펭수 이미지가 보인다.
브라우저는 URL을 서버에게 요청(request)하고, 전달받은 정보(html 형태)를 해석하여 사용자에게 보여준다. 이렇게 전달 받은 이미지 정보를 저장하면 된다.
import requests
#이미지가 있는 url 주소
url = "https://search1.kakaocdn.net/argon/600x0_65_wr/ImZk3b2X1w8"
#해당 url로 서버에게 요청
img_response = requests.get(url)
#요청에 성공했다면,
if img_response.status_code == 200:
#print(img_response.content)
print("========= [이미지 저장] =========")
with open("test.jpg", "wb") as fp:
fp.write(img_response.content)
requests 모듈이 설치되어 있지 않다면 import할 수 없다.
cmd에 pip install requests 를 통해 requests 모듈을 설치해주자.
위 코드에서 requests.get(url)을 통해 GET 요청을 보냈고 서버에서는 그 요청을 받아 나에게 응답(response)를 준다.
그 응답 상태가 200이라면 요청이 서버에서 잘 처리되어서 정상적인 응답을 보내줬다는 것을 의미한다.
성공했다면 test.jpg라는 파일을 ‘wb’모드, 바이너리 형식을 쓰는 모드로 열고 fp 변수에 담아주고
이미지에 해당하는 img_response.content를 write함수를 호출하여 저장한다.
작업한 디렉터리에 test.jpg 파일이 생겼다.
print(img_response.content)
주석처리 되어있던 이미지에 해당하는 img_response.content를 호출해보자.
이미지(jpeg)를 바이너리 형태로 읽어들이면 이런 식으로 정보 값이 입력되고 jpeg binary 데이터를 파일로 저장하면 이미지가 보이게 된다.
4. 카카오 이미지 검색 Open API 호출하기
https://developers.kakao.com/docs/latest/ko/daum-search/dev-guide
카카오 Open API에서는 이미지 뿐만 아니라 웹문서, 동영상, 블로그, 책, 카페 등 다양한 API를 제공해준다.
이미지 검색을 할 시 Request와 Response 가이드이다.
-
REST API 키를 헤더에 담아 GET으로 요청한다.
-
원하는 검색어와 함께 결과 형식 파라미터를 선택적으로 추가할 수 있다.
-
응답(Response) 바디는 meta, documents로 구성된 JSON 객체이다.
import requests
import json
# 이미지 검색
url = "https://dapi.kakao.com/v2/search/image"
headers = {
"Authorization" : "KakaoAK <REST_API 앱키를 입력하세요>"
}
data = {
"query" : "펭수"
}
# 이미지 검색 요청
response = requests.post(url, headers=headers, data=data)
# 요청에 실패했다면,
if response.status_code != 200:
print("error! because ", response.json())
else: # 성공했다면,
count = 0
for image_info in response.json()['documents']:
print(f"[{count}th] image_url =", image_info['image_url'])
# 저장될 이미지 파일명 설정
count = count + 1
-
호스트와 이미지 검색에 해당하는 url을 url변수에 담는다
-
헤더에는 Request 양식에 맞게 {“Authorization” : “KakaoAK 발급받은 REST_API 앱키”}를 작성한다.
*KakaoAK 한칸 띄고 <>괄호 없이 rest api키를 입력하면 된다
-
원하는 검색어를 query로 요청한다.(Request 양식에 query는 Required이기 때문에 반드시 입력해야한다.)
-
response = requests.post(url, headers=headers, data=data)
get(), post() 둘 다 API 통신을 할 때 호출하는 함수로 둘의 차이는 함수 내 파라미터 명이 다르다는 것(get 은 param / post 는 data)이다. 자세한 내용은 [Requests 모듈]을 참고하자.
카카오 이미지 검색 Open API의 Request 양식에 헤더에 REST API 앱 키를 담아 요청한다고 하였으니 headers 변수를 headers 파라미터로 세팅해 호출을 해주어야 한다.
-
response.json()[‘documents’]
print(response.json())
위 코드를 호출하게 되면
{'documents': [{'collection': 'blog', 'datetime': '2020-03-09T19:26:00.000+09:00', 'display_sitename': '네이버블로그', 'doc_url': 'http://blog.naver.com/2012kiss/221845372207', 'height': 773, 'image_url': 'http://postfiles1.naver.net/MjAyMDAzMDlfMTM4/MDAxNTgzNzQ5NTk0Njkw.gvrYNHHvHfwrRUVu2xSCqE2kp_OLzg1Y2EFoafU3lEMg.spMelefH5nVyAsuH1SLbLarM4L1KHzR8oHHtdS0v1wUg.PNG.2012kiss/%ED%8E%AD%EC%88%98.png?type=w773', 'thumbnail_url': 'https://search4.kakaocdn.net/argon/130x130_85_c/1uTVnFKcose', 'width': 773}, {'collection': 'etc', 'datetime': '2020-04-11T10:36:40.000+09:00', 'display_sitename': '', 'doc_url': 'http://isplus.live.joins.com/news/article/article.asp?total_id=23749688', ... #너무 길어서 생략 'http://postfiles15.naver.net/MjAyMDAxMThfMTIz/MDAxNTc5MzUwMzk3MTI0.9duHjG3eFwjdw0AK13yqqpyMhH18fHkzTtyNlkEiv0sg.I8DPf2Pe-Dd_k6olTYwXmgtFTe09-OCcfvsS62vmhyMg.JPEG.juhye0401/%ED%8E%AD%EC%88%981.jpg?type=w773', 'thumbnail_url': 'https://search2.kakaocdn.net/argon/130x130_85_c/FfJhkHTDp8d', 'width': 600}], 'meta': {'is_end': False, 'pageable_count': 3896, 'total_count': 818140}}
응답(Response) 바디는 meta, documents로 구성된 JSON 객체이다.
Response 양식에 쓰여진 것처럼 json 파일은 key 값으로 documents와 meta를 갖고 있는 큰 하나의 딕셔너리이고, documents는 리스트를 value로 가지고 그 리스트 안에는 또 여러 개의 딕셔너리가 저장되어있다. 리스트 안의 딕셔너리에는 위의 표에 나와있는 것처럼 collection, thumbnail_url, image_url, width, height, display_sitename 등의 key값을 가지고 있다.
딕셔너리의 value 값에 접근하는 방식을 통해 response.json()[‘documents’], 즉 documents라는 key에 접근하여 그 value를 뽑아내어 for문을 돌게 된다.
- image_info[‘image_url’]
for문을 돌면서 image_info[‘image_url’]가 출력되는데 이 또한 딕셔너리 안의 해당하는 key값의 value값을 가져오는 것으로 우리는 documents라는 key값의 value 중 image_url만을 가져오게 된다.
5. 이미지 파일 저장하기
# 이미지가 있는 image_url을 통해 file_name 파일로 저장하는 함수
def save_image(image_url, file_name):
img_response = requests.get(image_url)
# 요청에 성공했다면,
if img_response.status_code == 200:
# 파일 저장
with open(file_name, "wb") as fp:
fp.write(img_response.content)
save_image 함수는 image_url, file_name 두 가지 파라미터를 가지는데
image_url은 이미지가 담긴 url 주소, file_name은 이미지를 저장할 파일명이다.
get()함수를 사용하여 image_url을 요청하고, 요청에 성공했다면(200) 바이너리 쓰기 모드로 열어 파일로서 저장하게 된다.
6. 전체 코드
import requests
import json
# 이미지가 있는 image_url을 통해 file_name 파일로 저장하는 함수
def save_image(image_url, file_name):
img_response = requests.get(image_url)
# 요청에 성공했다면,
if img_response.status_code == 200:
# 파일 저장
with open(file_name, "wb") as fp:
fp.write(img_response.content)
# 이미지 검색
url = "https://dapi.kakao.com/v2/search/image"
headers = {
"Authorization" : "KakaoAK <REST_API 앱키를 입력하세요>"
}
data = {
"query" : "펭수"
}
# 이미지 검색 요청
response = requests.post(url, headers=headers, data=data)
# 요청에 실패했다면,
if response.status_code != 200:
print("error! because ", response.json())
else: # 성공했다면,
count = 0
for image_info in response.json()['documents']:
print(f"[{count}th] image_url =", image_info['image_url'])
# 저장될 이미지 파일명 설정
count = count + 1
file_name = "test_%d.jpg" %(count)
# 이미지 저장
save_image(image_info['image_url'], file_name)
file_name = "test_%d.jpg" %(count)
# 이미지 저장
save_image(image_info['image_url'], file_name)
위 코드를 통해 save_image 함수의 첫번째 파라미터인 image_url에는 image_info[‘image_url’] 인자가, 두 번째 파라미터인 file_name에는 “test_%d.jpg” %(count)이 들어가게 된다.
7. 결과
총 80장의 펭수 사진이 저장되었다.(1번부터 11번은 캡쳐가 잘렸다ㅠㅠ)
80장인 이유는 request를 할 때 필수인 query만 요청했고 size는 요청해주지 않았기 때문이다. size를 요청해주지 않는다면 디폴트 값인 80이 자동으로 요청되기 때문에 필요한만큼만 받아오고 싶다면 size를 지정해주도록 하자.