public ICollection<AnimeStreamInfo> GetAnimeStreamInfo()
        {
            string responseBody;
            using (CompressionWebClient client = new CompressionWebClient())
            {
                responseBody = client.DownloadString(Url);
            }

            // HTML Agility Pack does not convert "&Auml;" to an A with an umlaut
            // but it doesn't really matter as long as it's readable by the human editing the csv and consistent across program runs.
            HtmlDocument htmlDoc = new HtmlDocument();
            htmlDoc.LoadHtml(responseBody);
            HtmlNodeCollection matchingNodes = htmlDoc.DocumentNode.SelectNodes(XPath);

            List<AnimeStreamInfo> streams = new List<AnimeStreamInfo>();
            foreach (HtmlNode matchingNode in matchingNodes)
            {
                AnimeStreamInfo stream = GetStreamInfoFromMatch(matchingNode);

                // Convert possibly relative url to an absolute url
                stream = new AnimeStreamInfo(stream.AnimeName, Utils.PossiblyRelativeUrlToAbsoluteUrl(stream.Url, Url), stream.Service);

                streams.Add(stream);
            }

            return streams;
        }
        private void EnsureOauthToken()
        {
            if(_oauthToken != null)
                return;

            using (CompressionWebClient webClient = new CompressionWebClient())
            {
                string huluPageHtml = webClient.DownloadString("http://www.hulu.com/tv/genres/anime");
                Regex oathTokenRegex = new Regex("w.API_DONUT = '(?<Token>[^']*)'");
                Match m = oathTokenRegex.Match(huluPageHtml);
                if (!m.Success)
                {
                    throw new Exception("w.API_DONUT not found in Hulu HTML. The page probably changed and the code for getting Hulu anime needs to be updaed.");
                }

                _oauthToken = m.Groups["Token"].ToString();
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="type">movies or shows</param>
        /// <param name="genre"></param>
        /// <returns></returns>
        private ICollection<AnimeStreamInfo> GetAnimeStreamInfo(string type, string genre)
        {
            // http://www.hulu.com/mozart/v1.h2o/shows?exclude_hulu_content=1&genre={genre}&sort=release_with_popularity&_language=en&_region=us&items_per_page=100&position=0&region=us&locale=en&language=en&access_token={oathtoken}
            // count is in total_count
            // process results:
            //   data[x].show.name, data[x].show.canonical_name
            // current position += num results processed
            // if current position < count, repeat
            //
            // data[x].show.name is the show's name.
            // data[x].show.canonical_name is how you get the url for the show - http://www.hulu.com/{canonical_name}

            EnsureOauthToken();

            List<AnimeStreamInfo> streams = new List<AnimeStreamInfo>();

            using (CompressionWebClient webClient = new CompressionWebClient())
            {
                int position = 0;
                int numAnimes = int.MaxValue;

                while (position < numAnimes)
                {
                    string url = string.Format(
                        CultureInfo.InvariantCulture,
                        "http://www.hulu.com/mozart/v1.h2o/{0}?exclude_hulu_content=1&genre={1}&sort=release_with_popularity&_language=en&_region=us&items_per_page=100&position={2}&region=us&locale=en&language=en&access_token={3}",
                        type, Uri.EscapeDataString(genre), position, Uri.EscapeDataString(_oauthToken));

                    string jsonString = webClient.DownloadString(url);
                    HuluAnimeResultsJsonRoot json = JsonConvert.DeserializeObject<HuluAnimeResultsJsonRoot>(jsonString);

                    if (json.data.Count == 0)
                    {
                        throw new Exception(string.Format("Did not get any hulu anime from url {0}", url));
                    }

                    numAnimes = json.total_count;

                    foreach (var data in json.data)
                    {
                        string animeName = data.show.name;
                        string animeUrl = string.Format("http://www.hulu.com/{0}", data.show.canonical_name);
                        streams.Add(new AnimeStreamInfo(animeName: animeName, url: animeUrl, service: StreamingService.Hulu));
                        position++;
                    }
                }
            }

            return streams;
        }