예제 #1
0
        public void TryGrabAndParsePage_Song()
        {
            OneSongHeader expected_song_header = new OneSongHeader(
                1,
                "Graeme Revell - Vaako Conspiracy",
                "Vaako Conspiracy",
                "Graeme Revell",
                "The Chronicles Of Riddick - OST / Хроники Риддика - Саундтрек [Score]",
                "OST",
                "03:19",
                "5,31 Мб",
                "223 Кб/с",
                "mp3",
                "Fluffy",
                new Uri("http://fp42.myzuka.ru/Download.aspx?lid=727400&mid=5258695&date=20140130224847&sum=0afff71bffd5ff030dad549c1973575f&name=&ic=False&cr=False&ex=.jpg&il=False"),
                new Uri("http://myzuka.ru/Song/164181/Graeme-Revell-Vaako-Conspiracy"),
                true
            );

            ACommonData result1 = Core.TryGrabAndParsePage(
                new Uri("http://myzuka.ru/Song/164181/Graeme-Revell-Vaako-Conspiracy"),
                "Mozilla/5.0 (Windows; I; Windows NT 5.1; ru; rv:1.9.2.13) Gecko/20100101 Firefox/4.0",
                true,
                false,
                CancellationToken.None);

            Assert.NotNull(result1);
            Assert.IsInstanceOf(typeof(ParsedSong), result1);

            ParsedSong conv_result1 = (ParsedSong)result1;
            Assert.IsTrue(conv_result1.Header.Equals(expected_song_header));
            Assert.IsTrue(conv_result1.AlbumLink == new Uri("http://myzuka.ru/Album/12059/Graeme-Revell-The-Chronicles-Of-Riddick-Ost-Хроники-Риддика-Саундтрек-Score-2004"));
        }
예제 #2
0
        /// <summary>
        /// Извлекает и возвращает всю информацию по одной песне из страницы песни
        /// </summary>
        /// <param name="HTMLPage"></param>
        /// <returns></returns>
        internal static OneSongHeader ParseOneSongHeader(HtmlDocument HTMLPage)
        {
            String caption = CoreInternal.TryGrabCaption(HTMLPage);

            HtmlNode body_node = HTMLPage.DocumentNode.SelectSingleNode(
                "//div[@class='centerblock gr']/div[starts-with(@class, 'in2')]/div/table[@style and @class]/tr/td[2][@class='infoSong']");
            if (body_node == null) {throw new InvalidOperationException("Невозможно извлечь блок HTML-кода с метаинформацией по песне");}
            String body = body_node.InnerHtml;

            Int32 pos_input;

            String genre = StringTools.SubstringHelpers.GetInnerStringBetweenTokens
                (body, "Жанр:", "Исполнитель", 0, StringComparison.OrdinalIgnoreCase, out pos_input);
            if (genre.Contains("Нет данных", StringComparison.OrdinalIgnoreCase) == true)
            {
                genre = "Нет данных";
            }
            else
            {
                genre = StringTools.SubstringHelpers.GetInnerStringBetweenTokens
                    (genre, ">", "</a>", 0, StringComparison.OrdinalIgnoreCase, out pos_input);
                genre = HttpUtility.HtmlDecode(genre);
            }

            String artist = StringTools.SubstringHelpers.GetInnerStringBetweenTokens
                (body, "Исполнитель:", "<br>", pos_input, StringComparison.OrdinalIgnoreCase, out pos_input).Trim();
            artist = CoreInternal.ExtractFromHTML(artist);
            
            String album = StringTools.SubstringHelpers.GetInnerStringBetweenTokens
                (body, "Альбом:", "<br>", pos_input, StringComparison.OrdinalIgnoreCase, out pos_input).Trim();
            album = CoreInternal.ExtractFromHTML(album);

            String duration = StringTools.SubstringHelpers.GetInnerStringBetweenTokens
                (body, "Длительность:", "<br>", pos_input, StringComparison.OrdinalIgnoreCase, out pos_input).Trim();
            duration = CoreInternal.ExtractFromHTML(duration);

            String size = StringTools.SubstringHelpers.GetInnerStringBetweenTokens
                (body, "Размер:", "<br>", pos_input, StringComparison.OrdinalIgnoreCase, out pos_input).Trim();
            size = CoreInternal.ExtractFromHTML(size);

            String format = StringTools.SubstringHelpers.GetInnerStringBetweenTokens
                (body, "<i class=\"format\">", "</i>", pos_input, StringComparison.OrdinalIgnoreCase, out pos_input).Trim();

            String bitrate = StringTools.SubstringHelpers.GetInnerStringBetweenTokens
                (body, "<i class=\"bitrate\">", "</i>", pos_input, StringComparison.OrdinalIgnoreCase, out pos_input).Trim();

            HtmlNode uploader_node = body_node.ChildNodes.FindFirst("div");
            String uploader = uploader_node.InnerText.TrimStart("Загрузил:", StringComparison.OrdinalIgnoreCase, false).Trim();

            HtmlNode name_node = HTMLPage.DocumentNode.SelectSingleNode("//div[@id]/table[@width='100%']/tr[starts-with(@id,'trSong_')]/td[2]/div");
            if(name_node==null) {throw new InvalidOperationException("Невозможно извлечь из страницы песни блок HTML-кода с названием песни");}
            Boolean is_available = !name_node.InnerText.Contains("Файл утерян", StringComparison.InvariantCultureIgnoreCase);
            String name = HttpUtility.HtmlDecode(name_node.ChildNodes.Single(
                nd => nd.Name == "span" && nd.Attributes.Count > 0 && nd.Attributes.Contains("itemprop") && nd.Attributes["itemprop"].Value == "name"
            ).InnerText.CleanString().Trim());
            
            HtmlNode link_node = body_node.SelectSingleNode
                ("//div[@class='centerblock gr']/div[starts-with(@class, 'in2')]/div/table[@style and @class]/tr/td[2][@class='infoSong']/meta[@itemprop='url' and @content]");
            if(link_node==null) {throw new InvalidOperationException("Невозможно извлечь из страницы песни блок HTML-кода с URL на данную страницу");}

            String raw_link_URI = link_node.GetAttributeValue("content", "");
            String err_mes;
            Uri link_URI = CoreInternal.TryFixReturnURI(raw_link_URI, out err_mes);
            if (link_URI == null)
            {
                throw new InvalidOperationException("Невозможно извлечь URI текущей страницы песни: " + err_mes);
            }

            OneSongHeader song = new OneSongHeader(
                1, caption, name, artist, album, genre, duration, size, bitrate, format, uploader,
                CoreInternal.TryGrabImageUri(HTMLPage), link_URI, is_available);
            return song;
        }
예제 #3
0
        internal static KeyValuePair<OneSongHeader, Exception> DownloadAndSaveOneSong
            (OneSongHeader Song, String UserAgent, Boolean GenerateNewFilenames, String FilenameTemplate, String FolderPath, 
            Int32 IterationNumber)
        {
            // 1. запрос по УРЛ и перевести результат в ХТМЛдокумент
            String err_mess;
            HtmlAgilityPack.HtmlDocument HTML_doc =
                CoreInternal.TryGrabPage(Song.SongPageURI, UserAgent, out err_mess);
            if (HTML_doc == null)
            {
                return new KeyValuePair<OneSongHeader, Exception>(Song, new InvalidOperationException(
                        String.Format("Невозможно скачать HTML-документ по ссылке '{0}' на итерации {1}: {2}",
                            Song.SongPageURI.ToString(), IterationNumber, err_mess)));
            }
            // 2. извлечь УРЛ на скачивание самой песни
            Uri download_link;
            try
            {
                download_link = CoreInternal.ExtractDownloadSongURI(HTML_doc);
            }
            catch (Exception ex)
            {
                return new KeyValuePair<OneSongHeader, Exception>(Song,  new InvalidOperationException(
                        "Невозможно извлечь ссылку на скачивание песни из HTML-документа на итерации " + IterationNumber, ex));
            }
            // 3. скачать саму песню и всунуть её в контейнер DownloadedFile
            DownloadedFile song_file = CoreInternal.TryDownloadFile
                (download_link, Song.SongPageURI, UserAgent, out err_mess);
            if (song_file == null)
            {
                return new KeyValuePair<OneSongHeader, Exception>(Song, new InvalidOperationException(String.Format(
                    "Невозможно скачать файл песни '{0}.{1}' (альбом {2}) из страницы '{3}' по ссылке '{4}' на итерации {5}: {6}",
                    Song.Number, Song.Name, Song.Album, Song.SongPageURI.ToString(), download_link.ToString(), IterationNumber, err_mess)));
            }

            //4. определиться с названием сохраняемого файла
            String new_filename = null;
            if (GenerateNewFilenames == true)
            {
                new_filename = Song.GenerateSongFilename(song_file.Filename, FilenameTemplate);
                FilePathTools.TryCleanFilename(new_filename, out new_filename);
            }
            if (new_filename == null)
            {
                new_filename = song_file.Filename;
            }
            new_filename = Path.Combine(FolderPath, new_filename);
            //5. начать сохранение
            try
            {
                using (FileStream fs = new FileStream(new_filename, FileMode.Create, FileAccess.Write, FileShare.None))
                {
                    song_file.FileBody.Position = 0;
                    song_file.FileBody.CopyTo(fs, 1024*8);
                }
                return new KeyValuePair<OneSongHeader, Exception>(Song, null);
            }
            catch (Exception ex)
            {
                return new KeyValuePair<OneSongHeader, Exception>(Song, new InvalidOperationException(String.Format(
                    "Невозможно сохранить файл песни '{0}.{1}' (альбом {2}) на диск с полным именем файла '{3}' на итерации {4}",
                    Song.Number, Song.Name, Song.Album, new_filename, IterationNumber), ex));
            }
            finally
            {
                song_file.Dispose();
                song_file = null;
            }
        }