示例#1
0
def get_youtube_handle(keys):
    """ Returns the YouTube Data API v3 handle.

    Parameter
    ---------
    api_key: (str, list(str))
        An index and a list of authorized API keys.

    Returns
    -------
        An object for interacting with the YouTube API v3 service.
    """
    try:
        index = keys[0]
        key = keys[1][index]
        keys[0] += 1
    except IndexError:
        echow("No API Keys left!")
        if click.confirm("Do you want to enter another API key?"):
            key = click.prompt("Enter your API key", type=str)
        else:
            echoe("No API key provided. Exiting.")
    try:
        return build("youtube", "v3", developerKey=key)
    except HttpError as e:
        echoe(f""" There was an error while connecting to the YouTube API.
        Please check your API key: {e}""")
示例#2
0
def get(context, option):
    """ Shows a default option."""
    config = context.obj["config"]
    update_config(config)
    if option in config:
        echov(f"The value of '{option}' is set to '{config[option]}'.")
    else:
        echow(f"The value of '{option}' is not set!")
示例#3
0
def _search(handle, number, **api_options):
    api_options["type"] = "video"
    api_options["part"] = "id,snippet"
    response = _get_response(handle.search(), **api_options)
    video_data = [_extract_data(video) for video in response["items"]]
    if len(video_data) < number:
        echow(
            f"API gave less videos than requested: {len(video_data)} instead of {number}!"
        )
    return video_data[:number]
示例#4
0
def update_config(config, options={}):
    """ Updates a configuration dictionary and inserts default values.

        Parameters
        ----------
        config: dict
            A dictionary that should be updated.
        options: dict
            Values that should be put into `config`.
    """
    for key, value in options.items():
        if value or value == 0:
            if key in DEFAULT_OPTIONS:
                config[key] = value
            else:
                echow(f"Invalid option given: {key}")
    for key in DEFAULT_OPTIONS:
        if key not in config:
            config[key] = DEFAULT_OPTIONS[key]
示例#5
0
def load_config(config_path=None):
    r"""Processes and returns the user configuration.

    This function reads a TOML configuration file from either a provided
    path or the standard configuration directory and returns it.

    Parameters
    ----------
    config_path: str, optional
        The file path to the configuration file. If not specified,
        the method tries to read the default system-specific
        configuration directory.

    Returns
    -------
    dict
        Configuration dictionary.

    Notes
    -----
        The standard configuration directory is system specific:
        - Mac OS X: "~/Library/Application Support/YouTube Scraper"
        - Unix: "~/.config/youtube-scraper"
        - Windows: C:\Users\<user>\AppData\Roaming\YouTube Scraper
    """
    if config_path:
        config = toml.load(config_path)
    else:
        try:
            config_path = _get_default_config_path()
            config = toml.load(config_path)
        except FileNotFoundError:
            echow("Configuration file not found:")
            echow(str(config_path))
            if click.confirm("Do you want to create a default configuration?"):
                config_path = _get_default_config_path(create=True)
                config = toml.load(config_path)
            else:
                config = {}

    config["config_path"] = config_path
    return config
示例#6
0
def build_nodes(config, handle, api_options, starter_videos):
    for rank, video in enumerate(starter_videos):
        video.update({"rank": rank, "depth": 0})
    queue = deque(starter_videos)
    processed = []
    processed_ids = set()
    while len(queue) > 0:
        video = queue.popleft()
        echov(
            f"Processing video {video['videoId']} (Depth: {video['depth']}).",
            verbose,
        )
        processed.append(video)
        processed_ids.add(video["videoId"])
        if video["depth"] >= config["max_depth"]:
            video["relatedVideos"] = list()
            continue
        # Add children
        num_children = _get_branching(config["number"], video["depth"])
        while True:
            try:
                children = related_search(handle, num_children,
                                          video["videoId"], **api_options)
                video["relatedVideos"] = list(
                    map(lambda c: c["videoId"], children))
                for rank, child in enumerate(children):
                    child.update({"rank": rank, "depth": video["depth"] + 1})
                if config["unique"]:
                    queue.extend(child for child in children
                                 if child["videoId"] not in processed_ids)
                else:
                    queue.extend(children)
                break
            except HttpError as e:
                sys.tracebacklimit = 0
                echow("Http error received:")
                echow(e)
                handle = get_youtube_handle(api_options["keys"])

    return processed