Ejemplo n.º 1
0
        /// <summary>
        /// 有的MP3文件标题有错, 解析artists会出错
        /// 手动修改MP3Info.Title属性, 和已经下载好的MP3文件名
        ///
        /// 如
        /// "09. 四郎探母9(坐宫) 管绍华 王玉蓉 百代"
        /// 修改为
        /// "09.四郎探母9(坐宫) 管绍华 王玉蓉 百代"
        /// 否则原标题分组是 "09." "四郎探母9(坐宫)" "管绍华" "王玉蓉" "百代",
        /// 会把"四郎探母9(坐宫)"也当作artist
        /// </summary>
        private static void NormalizeMp3FileName(List <ExcelSheetModel> sheetModels, string oldFileName, string newFileName)
        {
            string  categoryName = null, albumName = null;
            Mp3Info wrongMp3 = null;

            // 大分类: 如 2018年出品-京剧
            foreach (var categoryInfo in sheetModels)
            {
                // 该分类下面的专辑: 1.京剧正宗谭派《王又宸专辑》
                foreach (MediaItem mediaItem in categoryInfo.MediaItems)
                {
                    wrongMp3 = mediaItem.Mp3Items?.FirstOrDefault(x => x.Title == oldFileName);
                    if (wrongMp3 != null)
                    {
                        categoryName = categoryInfo.Name;
                        albumName    = mediaItem.Title;
                        break;
                    }
                }

                if (wrongMp3 != null)
                {
                    break;
                }
            }

            if (wrongMp3 != null &&
                !string.IsNullOrEmpty(categoryName) &&
                !string.IsNullOrEmpty(albumName))
            {
                var mp3FilePath = System.IO.Path.Combine(StaticVariables.GetDownloadDir(),
                                                         categoryName, // "2018年出品-京剧",
                                                         albumName,    // "11 京剧红生大王《林树森专辑》",
                                                         oldFileName + ".mp3");

                var newMp3FilePath = System.IO.Path.Combine(
                    System.IO.Path.GetDirectoryName(mp3FilePath),
                    newFileName + ".mp3"
                    );
                if (System.IO.File.Exists(mp3FilePath))
                {
                    if (System.IO.File.Exists(newMp3FilePath))
                    {
                        System.IO.File.Delete(newMp3FilePath);
                    }

                    System.IO.File.Move(mp3FilePath, newMp3FilePath);
                }

                // 更新MP3标题
                wrongMp3.Title = newFileName;
            }
        }
Ejemplo n.º 2
0
        // 下载某个具体专辑信息
        // 如:1.《评剧皇后白玉霜 》第一集 http://www.bavc.com.cn/c44169.htm
        static MediaItem ParseMediaItem(string title, string url)
        {
            MediaItem item = new MediaItem();

            item.Title = title;
            item.Url   = url;

            DebugInfo($"读取专辑: {item.Title}");
            var homePageNode = HtmlCacheParser.LoadHtmlNode(url);

            // 主要内容的node
            var mainNode = homePageNode.SelectSingleNode("/html/body/table[7]");

            //发布时间: /html/body/table[7]/tbody/tr[1]/td/p[2]/font/span
            item.PublishTime = mainNode.SelectSingleNode(".//font/span")?.InnerText;

            //简介 /html/body/table[7]/tbody/tr[3]/td/div/p[1]
            item.Description = mainNode.SelectSingleNode(".//div[@class='article']")?.InnerText;

            // 封面图片 /html/body/table[7]/tbody/tr[3]/td/div/p[2]/img
            var imageAttr = mainNode.SelectSingleNode(".//div[@class='article']//img")?.Attributes["src"]?.Value;

            if (!string.IsNullOrEmpty(imageAttr))
            {
                item.ImageUrl = StaticVariables.HOST_NAME.TrimEnd('/') + imageAttr;
            }

            // MP3列表 /html/body/table[7]/tbody/tr[7]/td/p/table/tbody/tr[1]/td[2]/a
            foreach (var link in mainNode.SelectNodes(".//a"))
            {
                var href     = link.Attributes["href"].Value;
                var mp3Title = link.InnerText;
                // http://www.bavc.com.cn/xxxx.htm
                var address = StaticVariables.HOST_NAME.TrimEnd('/') + href;

                var mp3Info = new Mp3Info
                {
                    Title = mp3Title,
                    Url   = address
                };

                // DebugInfo($"\t读取专辑下曲目: {mp3Title}");
                LoadMp3Info(mp3Info);

                item.Mp3Items.Add(mp3Info);
            }

            return(item);
        }
        /// <summary>
        /// 生成标签
        /// </summary>
        /// <param name="tags">MP3标签</param>
        /// <param name="mp3FileDir">MP3文件夹</param>
        /// <param name="mp3Info">MP3信息</param>
        /// <param name="mediaItem">MP3所在专辑信息</param>
        private static void SetTags(TagLib.Tag tag, string mp3FileDir, Mp3Info mp3Info, MediaItem mediaItem)
        {
            tag.Title = mp3Info.Title;
            tag.Album = mediaItem.Title;
            var artists = mp3Info.GuessArtists(mediaItem.Title, out string companyName);

            if (artists != null && artists.Length > 0)
            {
                tag.AlbumArtists = new string[1] {
                    artists[0]
                };
                tag.Artists = artists;
            }

            // 唱片公司写到Grouping属性中?
            if (string.IsNullOrEmpty(companyName))
            {
                tag.Grouping = companyName;
            }

            var trackIndex = mediaItem.Mp3Items?.FindIndex(x => x.Title == mp3Info.Title);

            if (trackIndex > -1)
            {
                tag.Track      = (uint)trackIndex + 1;
                tag.TrackCount = (uint)mediaItem.Mp3Items.Count;
            }

            // 播放器不支持内嵌歌词, 目前还是放到备注里了
            //tag.Lyrics = mp3Info.Lyric;
            tag.Comment = mp3Info.Lyric; //tag.Comment = "强森强森整理";

            tag.Copyright = "北京典籍与经典老唱片数字化出版项目";

            // 封面图片(默认名称为_avatar.jpg)
            var mp3CoverFilePath = Path.Combine(mp3FileDir, StaticVariables.ALBUM_MP3_COVER_NAME);

            if (System.IO.File.Exists(mp3CoverFilePath))
            {
                var fileBytes = System.IO.File.ReadAllBytes(mp3CoverFilePath);
                var corverPic = new TagLib.Picture(new TagLib.ByteVector(fileBytes));
                // apply corver
                tag.Pictures = new TagLib.IPicture[] { corverPic };
            }
        }
Ejemplo n.º 4
0
        /// url为某个具体MP3播放页面
        /// 从url中读取MP3相关信息
        static void LoadMp3Info(Mp3Info mp3Info)
        {
            if (mp3Info == null || string.IsNullOrEmpty(mp3Info.Url))
            {
                throw new ArgumentException(nameof(mp3Info));
            }

            // 播放页面左侧有导航栏的情况(少数是这样)
            // 无导航: http://www.bavc.com.cn/w10276740.htm?page=1
            // 有导航: http://www.bavc.com.cn/w10276738.htm?page=1
            var homePageNode = HtmlCacheParser.LoadHtmlNode(mp3Info.Url);
            var tdNodes      = homePageNode.SelectNodes("/html/body/table[4]/tbody/tr/td");

            if (tdNodes == null || tdNodes.Count == 0)
            {
                HtmlParseLogger.Error($"{mp3Info.Title}({mp3Info.Url})页面信息不存在");
            }

            // 音频页面有导航栏xpath不同
            bool hasSidebar = tdNodes.Count > 1;

            HtmlNode mainNode = null;

            if (!hasSidebar)
            {
                mainNode = homePageNode.SelectSingleNode("/html/body/table[4]/tbody/tr/td/table[4]");
            }
            else
            {
                mainNode = homePageNode.SelectSingleNode("/html/body/table[4]/tbody/tr/td[3]/center/table[last()]");
            }

            if (mainNode == null)
            {
                HtmlParseLogger.Error($"{mp3Info.Title}({mp3Info.Url})页面信息不存在");
            }

            // 标题(列表页已经获取了) /html/body/table[4]/tbody/tr/td/table[4]/tbody/tr[2]/td/table/tbody/tr[1]/td/p[1]/span

            // 当前读取方式会显示‘Your browser does not support’,<a>写出了地址
            mp3Info.Mp3DownloadUrl = mainNode.SelectSingleNode(".//table[1]//table[1]//a")?.Attributes["href"]?.Value;

            // 如果没有MP3, 检测MP4
            if (string.IsNullOrEmpty(mp3Info.Mp3DownloadUrl))
            {
                mp3Info.Mp4DownloadUrl = GuessMp4DownloadUrl(mp3Info.Title, mp3Info.Url);
            }

            // 歌词标题和歌词在一个td里, 标题带有<strong>
            // /html/body/table[4]/tbody/tr/td/table[4]/tbody/tr[2]/td/table/tbody/tr[5]/td/strong
            // /html/body/table[4]/tbody/tr/td/table[4]/tbody/tr[2]/td/table/tbody/tr[4]/td
            // 歌词部分有两种可能
            HtmlNode lyricNode = mainNode.SelectSingleNode("./tbody/tr[last()-1]/td/table/tbody/tr[last()]");

            if (lyricNode == null)
            {
                lyricNode = mainNode.SelectSingleNode("./tbody/tr[last()-2]/td/table/tbody/tr[last()]");
            }

            if (lyricNode == null)
            {
                HtmlParseLogger.Error($"{mp3Info.Title}({mp3Info.Url})歌词信息不存在, 跳过");
            }

            // 大部分标题在<p><strong>{Title}</strong></p>中
            // 目前只发现13. 《梨园名票唱腔选》第三集 "06.武家坡-2 夏山楼主 高亭"没有<strong>, 标题<p>{Title}</p>中
            var lyricTitle = (lyricNode?.SelectSingleNode(".//strong") ??
                              lyricNode?.SelectSingleNode(".//p"))?.InnerText;
            var lyric = lyricNode?.InnerText;

            // .Replace("&nbsp;", "")
            lyric = lyric?.Replace("\r\n", "");

            // 歌词去掉标题部分
            if (!string.IsNullOrEmpty(lyricTitle) &&
                !string.IsNullOrEmpty(lyric))
            {
                var titleIndex = lyric.IndexOf(lyricTitle);
                // 标题出现在开头
                if (titleIndex == 0 && lyric.Length > lyricTitle.Length)
                {
                    lyric = lyric.Substring(lyricTitle.Length);
                }
            }

            mp3Info.Lyric      = lyric;
            mp3Info.LyricTitle = lyricTitle;
        }