본문 바로가기

Python/YouTube Data API v3

[Youtube API] 페이지 토큰 값으로 동영상 제목과 설명 추출하기

이번에는YouTube Data  API의 리소스 중 토큰값을 이용하여 단일 최대 호출수인 50개 이상의 유튜브 동영상을 호출하고

동영상의 제목과 설명을 추출해 보도록 하겠습니다.

 

기존의 코드에서 추가되어야 할 부분이 몇가지 있습니다.

동영상 제목과 설명은 API 중 JSON중 video 리소스에서 추출할 수 있어 video에 관련된 API URL을 따로 호출하여 추출해야 합니다.

해당 리소스는 Snippet 이라는 JSON 구조 아래에 포함되어 있어 아래의 URL로 호출하면 됩니다.

https://www.googleapis.com/youtube/v3/videos?part=snippet 

또한, 유튜브 동영상 제목과 설명란에는 특수 문자가 있을 수 있으므로 DB의 CHARSET을 utf8mb3 형식으로 변경해 주어야 합니다.

 

다음은 참고하실 JSON 구조입니다.

{
  "kind": "youtube#video",
  "etag": etag,
  "id": string,
  "snippet": {
    "publishedAt": datetime,
    "channelId": string,
    "title": string,
    "description": string,
    "thumbnails": {
      (key): {
        "url": string,
        "width": unsigned integer,
        "height": unsigned integer
      }
    },
    "channelTitle": string,
    "tags": [
      string
    ],
    ...

그럼 수정된 코드를 통해 추가된 기능을 알아보도록 하겠습니다.

# import 생략

login = youtube_config.conn
key = login['key']
search_url = 'https://www.googleapis.com/youtube/v3/search?q=' #Search (id-videoId, order-rationg viewCount)
snippet_url = 'https://www.googleapis.com/youtube/v3/videos?part=snippet' #Snippet (snippet-title description)
conn = pymysql.connect(
    host=login['host'],
    port=login['port'],
    user=login['user'],
    password=login['password'],
    database=login['database'],
    charset=login['charset']
)

curs = conn.cursor()

#사용자에게 검색어를 입력받습니다.
searchText = input("검색어를 입력하세요 :")

i = 0

#토큰값으로 더이상 동영상을 불러올게 없을 때 까지 호출합니다.
while curs.rowcount != None:
    curl =""
    if i == 0 :
        curl = search_url + searchText + '&maxResults=50&key=' + key
    elif i > 0 : #다음 페이지 토큰값으로 다시 50개 호출
        curl = search_url + searchText + '&pageToken='+ NextPageData + '&maxResults=50&key=' + key


    response = requests.get(curl)
    jsonObject = json.loads(response.text)
    listData = jsonObject.get('items')
    NextPageData = jsonObject.get('nextPageToken') #다음 페이지 토큰값
    PrvPageData = jsonObject.get('prevPageToken') #이전 페이지 토큰값
  
  
    i = i + 1
    for list in listData:
        v_id = list.get('id').get('videoId')
        etag = list.get('etag')

		# 저장되어 있는 동영상과 중복 체크
        query_str = "SELECT COUNT(v_id) FROM TEST.video_list WHERE v_id = '" + str(v_id) + "';"
        curs.execute(query_str)
        data = curs.fetchone()
        data_int = int(data[0])

		#중복되지 않은 동영상이면 패스
        if data_int == 0 and str(v_id) != 'None':
            curl2 = snippet_url + '&id=' + v_id + '' + '&key=' + key
            response2 = requests.get(curl2)
            jsonObject2 = json.loads(response2.text)
            listData2 = jsonObject2.get('items')

			#중복되지 않은 동영상의 제목과 설명 추출
            for list2 in listData2: 
                v_id2 = list2.get('id')
                v_title = list2.get('snippet').get('title')
                v_desc = list2.get('snippet').get('description')
                
                #추출한 제목과 설명을 포함하여 DB에 추가
                sql = "INSERT INTO TEST.video_list (v_id, etag, search_txt, title, description) VALUES (%s, %s, %s, %s, %s);"
                val = (v_id, etag, searchText, v_title, v_desc)
                curs.execute(sql, val)
                # print(curs.rowcount)
        conn.commit()
    # conn.close() 계속 DB에 반영 해야하기 때문에 close 하면 안됨

여기서 참고할 사항은, 토큰값을 사용하던지 안하던지 한번의 동영상 목록 호출(50개)에 50개가 모두 검색되지 않는다는 것입니다.

구글 측에서 서비스 품질 유지를 위한 것인지, 50개를 호출해도 40개나 10개씩 무작위로 호출되며 특정 호출 횟수를 넘으면 호출해도 0개가 호출되는데 이때 다음 토큰이 없기 때문에 스크립트는 끝나게 됩니다.

 

이렇게 한번 호출에 50개 이상의 동영상을 불러올 수 있게 되었습니다.

다음에는 많은 데이터를 가독성 있게 검색하고 확인할 수 있도록 페이징을 구현해 보도록 하겠습니다.