SMAPPNYU / youtube-data-api

A Python Client for collect and parse public data from the Youtube Data API
https://youtube-data-api.readthedocs.io/en/latest/index.html
MIT License
79 stars 31 forks source link

get_channel_metadata() fails when channel_id is a list instead of a string #32

Closed aleksnavratil closed 4 years ago

aleksnavratil commented 4 years ago

Describe the bug get_channel_metadata() fails when channel_id is a list instead of a string. Cardinality of the list doesn't matter, meaning it fails even on a list of length 1.

Expected behavior Instead of crashing, it should return an iterable (probably a dict) of metadata for each of the channel_id's.

Traceback

# Traceback (most recent call last):
#   File "<stdin>", line 1, in <module>
#   File "/Users/anavratil/.virtualenvs/influencer_fraud/lib/python3.7/site-packages/youtube_api/youtube_api.py", line 209, in get_channel_metadata
#     **kwargs):
#   File "/Users/anavratil/.virtualenvs/influencer_fraud/lib/python3.7/site-packages/youtube_api/youtube_api.py", line 165, in get_channel_metadata_gen
#     response_json = self._http_request(http_endpoint)
#   File "/Users/anavratil/.virtualenvs/influencer_fraud/lib/python3.7/site-packages/youtube_api/youtube_api.py", line 109, in _http_request
#     response_json = _load_response(response)
#   File "/Users/anavratil/.virtualenvs/influencer_fraud/lib/python3.7/site-packages/youtube_api/youtube_api_utils.py", line 48, in _load_response
#     response.raise_for_status()
#   File "/Users/anavratil/.virtualenvs/influencer_fraud/lib/python3.7/site-packages/requests/models.py", line 941, in raise_for_status
#     raise HTTPError(http_error_msg, response=self)
# requests.exceptions.HTTPError: 404 Client Error: Not Found for url: https://www.googleapis.com/youtube/3/channels?part=id,snippet,contentDetails,statistics,topicDetails,brandingSettings&id=UCwdVOry0oNF9WIe_3uCfz9Q&key={key_goes_here}&maxResults=50
# >>>

Desktop (please complete the following information):

Additional context

## Here's a minimal testbed for reproducing this bug:
import os
from youtube_api import YoutubeDataApi as yt_api

YT_KEY = os.environ.get('YT_KEY')
yt = yt_api(YT_KEY, verbose = True) 

## Here we try it with channel_id as a string. This test case works perfectly. I turned on verbose mode so we can see the endpoint URL fully composed with all vars subbed in.
yt.get_channel_metadata(channel_id = 'UCwdVOry0oNF9WIe_3uCfz9Q')

# https://www.googleapis.com/youtube/v3/channels?part=id,snippet,contentDetails,statistics,topicDetails,brandingSettings&id=UCwdVOry0oNF9WIe_3uCfz9Q&key={API_KEY_PLACEHOLDER}&maxResults=50
## It turns out that this URL is identical to the one printed by the failing case below

# {'channel_id': 'UCwdVOry0oNF9WIe_3uCfz9Q', 'title': "Matt's Off Road Recovery", 'account_creation_date': datetime.datetime(2019, 3, 28, 13, 50, 25), 'keywords': '"matt\'s off road recovery" "matt\'s towing" "matt\'s towing and recovery" "matts off road recovery" "winder towing" "off road recovery" "matts towing" "matt towing and recovery" "matts recovery" "matt off road recovery" "wheels on the bus" "matt recovery" "off road" "you took your hyundai where" "stuck in the mud" "stuck in the sand" "stuck truck" "stuck 4x4" "sand recovery" "4x4 recovery" "side by side" "jeep cherokee" "jeep xj"', 'description': 'Off road towing, recoveries and rescues. We cover beautiful southern Utah, near Zion National park. We have a unique way to do off road recovery with our Jeep XJ affectionately named, the yellow banana. We have the infamous Ed with his postive outlook on life.', 'view_count': '27534880', 'video_count': '137', 'subscription_count': '147000', 'playlist_id_likes': None, 'playlist_id_uploads': 'UUwdVOry0oNF9WIe_3uCfz9Q', 'topic_ids': None, 'country': 'US', 'collection_date': datetime.datetime(2020, 4, 7, 20, 35, 24, 687072)}
# >>>

## On the other hand, with the same channel_id as a list containing a single string, we get a failure. The same is true for longer lists also of course. As above, I turned on verbose mode so we can see the endpoint URL fully composed with all vars subbed in.

yt.get_channel_metadata(channel_id = ['UCwdVOry0oNF9WIe_3uCfz9Q'])

# https://www.googleapis.com/youtube/3/channels?part=id,snippet,contentDetails,statistics,topicDetails,brandingSettings&id=UCwdVOry0oNF9WIe_3uCfz9Q&key={API_KEY_PLACEHOLDER}&maxResults=50
## It turns out that this URL is identical to the one printed by the failing case above

# Traceback (most recent call last):
#   File "<stdin>", line 1, in <module>
#   File "/Users/anavratil/.virtualenvs/influencer_fraud/lib/python3.7/site-packages/youtube_api/youtube_api.py", line 209, in get_channel_metadata
#     **kwargs):
#   File "/Users/anavratil/.virtualenvs/influencer_fraud/lib/python3.7/site-packages/youtube_api/youtube_api.py", line 165, in get_channel_metadata_gen
#     response_json = self._http_request(http_endpoint)
#   File "/Users/anavratil/.virtualenvs/influencer_fraud/lib/python3.7/site-packages/youtube_api/youtube_api.py", line 109, in _http_request
#     response_json = _load_response(response)
#   File "/Users/anavratil/.virtualenvs/influencer_fraud/lib/python3.7/site-packages/youtube_api/youtube_api_utils.py", line 48, in _load_response
#     response.raise_for_status()
#   File "/Users/anavratil/.virtualenvs/influencer_fraud/lib/python3.7/site-packages/requests/models.py", line 941, in raise_for_status
#     raise HTTPError(http_error_msg, response=self)
# requests.exceptions.HTTPError: 404 Client Error: Not Found for url: https://www.googleapis.com/youtube/3/channels?part=id,snippet,contentDetails,statistics,topicDetails,brandingSettings&id=UCwdVOry0oNF9WIe_3uCfz9Q&key={key_goes_here}&maxResults=50
# >>>

Thanks for the great library by the way, it's quite handy :)

mabrownnyu commented 4 years ago

Hi @aleksnavratil, This has been resolved and will be fixed in the next package update.

aleksnavratil commented 4 years ago

Great, sounds like a plan :) Thanks!