/// <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; } }
// 下载某个具体专辑信息 // 如: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 }; } }
/// 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(" ", "") 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; }