text: from googleapiclient.discovery import build
  
  def yt_search(query, API_KEY, publishedBefore, publishedAfter, maxResults=20):
      """
      Request YouTube video search results for a particular query and return parsed data
  
      Parameters
      ----------
      query : string
          The query to search for on YouTube
      API_KEY : string
          The API key to authenticate requests to YouTube Data API v3
      maxResults : int, optional
          The maximum number of videos to scrape
      Returns
      ----------
      videos : list of dict or None
          The list of collected video data, each dictionary with the video's url and title, or None if
          no YouTube search results exist
      Notes
      ----------
      For more info on YouTube v3 API, please visit https://developers.google.com/youtube/v3
      """
      
      if not API_KEY:
          return '"Please provide "YouTube API Key"'
      
      youtube = build('youtube', 'v3', developerKey=API_KEY)
      
      # Request search results
      try:
          search_response = youtube.search().list(
              q=query,
              maxResults=maxResults,
              part='id',
              type='video',
              order='viewCount',
              relevanceLanguage='en',
              publishedBefore=publishedBefore,
              publishedAfter=publishedAfter
          ).execute()
      except:
          raise
  
      search_items = search_response['items']
      
      videos = None
      
      if not search_items:
          return videos
      
      id_str = ""
      
      # Request video data
      for video in search_items:
          id_str = id_str + video["id"]["videoId"] + ","
      
      videos_response = youtube.videos().list(
          part="snippet,contentDetails,statistics",
          id=id_str
      ).execute()
      video_items = videos_response['items']
      
      videos = list(map(parse_videos, video_items))
      
      return videos
  
  def yt_comments(videoId, API_KEY):
      """
      Request YouTube comments for a particular video and return parsed data
  
      Parameters
      ----------
      videoId : string
          The ID of video to fetch comments
      API_KEY : string
          The API key to authenticate requests to YouTube Data API v3
      Returns
      ----------
      comments : list of dict or None
          The list of collected comments data, each dictionary with the comment's text, author, publish date, and number of likes, or None if
          no YouTube search results exist
      Notes
      ----------
      For more info on YouTube v3 API, please visit https://developers.google.com/youtube/v3
      """
      
      if not API_KEY:
          return '"Please provide "YouTube API Key"'
      
      youtube = build('youtube', 'v3', developerKey=API_KEY)
      
      try:
          # Grab comments for videoId
          comments_response = youtube.commentThreads().list(
              part='id,snippet',
              videoId=videoId,
              maxResults=100,
              order="relevance"
      
          ).execute()
      
      except:
          return
      
      items = comments_response['items']
      comments = None
      
      if not items:
          return comments
      
      comments = list(map(parse_comments, items))
      
      return comments
      
  def parse_videos(video):
      """
      Parse data from the video JSON structure
      
      Parameters
      ----------
      video : JSON object of strings
          The video search result requested from YouTube API v3
      Returns
      ----------
      video_dict : dictionary of strings
          The dictionary contianing video title, published date, id, views, likes, dislikes, and no. of comments
      """
      
      
      title = video['snippet']['title']
      date = video['snippet']['publishedAt']
      channel = video['snippet']['channelTitle']
      ID = video['id']
      stats = video['statistics']
      views = stats['viewCount']
      try:
          likes = stats['likeCount']
          dislikes = stats['dislikeCount']
      except:
          likes = 0
          dislikes = 0
      try:
          commentCount = stats['commentCount']
      except:
          commentCount = 0
      
      video_dict = {
          'title': title,
          'date': date,
          'channel': channel,
          'id': ID,
          'views': views,
          'likes': likes,
          'dislikes': dislikes,
          'comment_count': commentCount
      }
      
      return video_dict
      
  def parse_comments(commentThread):
      """
      Parse data from the comment JSON structure
      
      Parameters
      ----------
      comment : JSON object of strings
          The comment resource requested from YouTube API v3
      Returns
      ----------
      comment_dict : dictionary of strings
          The dictionary contianing comment text, author, date, no. of likes
      """
      comment = commentThread['snippet']['topLevelComment']
      
      snippet = comment['snippet']
      text = snippet['textOriginal'].replace("\n", " ").replace("\t", " ").replace("\r", " ")
      author = snippet['authorDisplayName']
      date = snippet['publishedAt']
      likes = snippet['likeCount']
      
      comment_dict = {
          'text' : text,
          'author' : author,
          'date' : date,
          'likes' : likes
      }
      
      return comment_dict