Initial commit — AllMusicGuide scraper and music metadata tagger
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml;
|
||||
using MusicMetaTagger.Client.AllMusicGuide.Properties;
|
||||
using MusicMetaTagger.Core.Model;
|
||||
using MusicMetaTagger.Core.Utility;
|
||||
|
||||
namespace MusicMetaTagger.Client.AllMusicGuide.RemoteDataAccess.Parser
|
||||
{
|
||||
public class AlbumParser : ParserBase<Album>
|
||||
{
|
||||
public override Album Parse(XmlDocument xml)
|
||||
{
|
||||
var album = new Album();
|
||||
var settings = AlbumScraper.Default;
|
||||
|
||||
if (XpathMatch(xml, settings.ArtistUrlXpath))
|
||||
{
|
||||
var artistUrl = XpathMatchString(xml, settings.ArtistUrlXpath);
|
||||
album.ArtistId = RegexCapture(artistUrl, settings.ArtistUrlIdRegex);
|
||||
album.ArtistName = XpathMatchString(xml, settings.ArtistXpath);
|
||||
}
|
||||
else
|
||||
{
|
||||
album.VariousArtists = true;
|
||||
album.ArtistName = "Various Artists";
|
||||
}
|
||||
|
||||
if (XpathMatch(xml, settings.SoundtrackXpath))
|
||||
{
|
||||
album.Soundtrack = true;
|
||||
}
|
||||
|
||||
var albumId = XpathMatchString(xml, settings.AlbumIdXpath);
|
||||
album.AlbumId = StringUtility.CleanId(albumId);
|
||||
|
||||
album.Title = XpathMatchString(xml, settings.TitleXpath);
|
||||
if (XpathMatch(xml, settings.ReleaseDateXpath))
|
||||
album.ReleaseDate = XpathMatchString(xml, settings.ReleaseDateXpath);
|
||||
|
||||
//rating
|
||||
if (XpathMatch(xml, settings.RatingXpath))
|
||||
{
|
||||
float rating;
|
||||
if (float.TryParse(XpathMatchString(xml, settings.RatingXpath), out rating))
|
||||
album.Rating = Convert.ToInt32(rating*2);
|
||||
}
|
||||
|
||||
if (XpathMatch(xml, settings.PickXpath))
|
||||
album.Pick = true;
|
||||
|
||||
if (XpathMatch(xml, settings.CoverUrlXpath))
|
||||
{
|
||||
var coverUrl = XpathMatchString(xml, settings.CoverUrlXpath);
|
||||
album.CoverUrl = RegexCapture(coverUrl, settings.CoverUrlRegex);
|
||||
}
|
||||
if (XpathMatch(xml, settings.ReviewXpath))
|
||||
album.Review = XpathMatchString(xml, settings.ReviewXpath);
|
||||
|
||||
if (XpathMatch(xml, settings.ReviewerXpath))
|
||||
{
|
||||
var reviewer = XpathMatchString(xml, settings.ReviewerXpath);
|
||||
album.Reviewer = RegexCapture(reviewer, settings.ReviewerRegex).Trim();
|
||||
}
|
||||
|
||||
if (XpathMatch(xml, settings.StylesXpath))
|
||||
album.Styles = XpathMatchStringList(xml, settings.StylesXpath);
|
||||
if (XpathMatch(xml, settings.MoodsXpath))
|
||||
album.Moods = XpathMatchStringList(xml, settings.MoodsXpath);
|
||||
if (XpathMatch(xml, settings.ThemesXpath))
|
||||
album.Themes = XpathMatchStringList(xml, settings.ThemesXpath);
|
||||
|
||||
album.Tracks = new List<Track>();
|
||||
|
||||
if (XpathMatch(xml, settings.TrackXpath))
|
||||
{
|
||||
var trackParser = new TrackParser();
|
||||
var tracks =
|
||||
from tXml in XpathMatchXmlList(xml, settings.TrackXpath)
|
||||
let t = trackParser.Parse(tXml)
|
||||
where t.PerformerIds.Any() && t.TrackLength > TimeSpan.MinValue
|
||||
select t;
|
||||
|
||||
foreach (var track in tracks)
|
||||
{
|
||||
track.AlbumId = album.AlbumId;
|
||||
album.Tracks.Add(track);
|
||||
}
|
||||
}
|
||||
return album;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml;
|
||||
using MusicMetaTagger.Client.AllMusicGuide.Properties;
|
||||
using MusicMetaTagger.Core.Model;
|
||||
|
||||
namespace MusicMetaTagger.Client.AllMusicGuide.RemoteDataAccess.Parser
|
||||
{
|
||||
public class AlbumResultPageParser : ParserBase<List<AlbumResult>>
|
||||
{
|
||||
public override List<AlbumResult> Parse(XmlDocument xml)
|
||||
{
|
||||
var albumResults = new List<AlbumResult>();
|
||||
var settings = AlbumResultPageScraper.Default;
|
||||
var albumResultScraper = new AlbumResultParser();
|
||||
|
||||
if (XpathMatch(xml, settings.AlbumXpath))
|
||||
{
|
||||
var albumResultInfoXmlList = XpathMatchXmlList(xml, settings.AlbumXpath);
|
||||
albumResults.AddRange(albumResultInfoXmlList.Select(albumResultScraper.Parse));
|
||||
var i = 1;
|
||||
albumResults.ForEach(ar => ar.ResultOrder = i++);
|
||||
}
|
||||
return albumResults;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
using System;
|
||||
using System.Xml;
|
||||
using MusicMetaTagger.Client.AllMusicGuide.Properties;
|
||||
using MusicMetaTagger.Core.Model;
|
||||
|
||||
namespace MusicMetaTagger.Client.AllMusicGuide.RemoteDataAccess.Parser
|
||||
{
|
||||
public class AlbumResultParser : ParserBase<AlbumResult>
|
||||
{
|
||||
public override AlbumResult Parse(XmlDocument xml)
|
||||
{
|
||||
var albumResult = new AlbumResult();
|
||||
var settings = AlbumResultScraper.Default;
|
||||
|
||||
var albumUrl = XpathMatchString(xml, settings.AlbumUrlXpath);
|
||||
albumResult.AlbumId = RegexCapture(albumUrl, settings.AlbumUrlIdRegex);
|
||||
|
||||
if (XpathMatch(xml, settings.InfoXpath))
|
||||
{
|
||||
var infoRaw = XpathMatchString(xml, settings.InfoXpath);
|
||||
if (RegexMatch(infoRaw, settings.YearRegex))
|
||||
{
|
||||
var year = RegexCapture(infoRaw, settings.YearRegex);
|
||||
int yearInt;
|
||||
if (Int32.TryParse(year, out yearInt))
|
||||
albumResult.Year = yearInt;
|
||||
}
|
||||
if (RegexMatch(infoRaw, settings.GenreRegex))
|
||||
{
|
||||
var genre = RegexCapture(infoRaw, settings.GenreRegex);
|
||||
albumResult.Genre = genre.Trim();
|
||||
}
|
||||
}
|
||||
|
||||
if (XpathMatch(xml, settings.ArtistUrlXpath))
|
||||
{
|
||||
var artistId = XpathMatchString(xml, settings.ArtistUrlXpath);
|
||||
albumResult.ArtistId = RegexCapture(artistId, settings.ArtistUrIdRegex);
|
||||
albumResult.ArtistName = XpathMatchString(xml, settings.ArtistXpath);
|
||||
}
|
||||
else if (XpathMatch(xml, settings.ArtistNoUrlXpath))
|
||||
{
|
||||
albumResult.ArtistName = XpathMatchString(xml, settings.ArtistNoUrlXpath);
|
||||
}
|
||||
|
||||
albumResult.AlbumTitle = XpathMatchString(xml, settings.TitleXpath);
|
||||
|
||||
return albumResult;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml;
|
||||
using MusicMetaTagger.Client.AllMusicGuide.Properties;
|
||||
using MusicMetaTagger.Core.Model;
|
||||
using MusicMetaTagger.Core.Utility;
|
||||
|
||||
namespace MusicMetaTagger.Client.AllMusicGuide.RemoteDataAccess.Parser
|
||||
{
|
||||
public class ArtistDiscographyPageParser : ParserBase<List<ArtistDiscography>>
|
||||
{
|
||||
public override List<ArtistDiscography> Parse(XmlDocument xml)
|
||||
{
|
||||
var artistDiscographies = new List<ArtistDiscography>();
|
||||
var settings = ArtistDiscographyPageScraper.Default;
|
||||
|
||||
if (XpathMatch(xml, settings.DiscographyXpath))
|
||||
{
|
||||
var releaseTypeStr = XpathMatchString(xml, settings.ReleaseTypeXpath);
|
||||
releaseTypeStr = RegexCapture(releaseTypeStr, settings.ReleaseTypeRegex);
|
||||
|
||||
ReleaseType releaseType;
|
||||
switch (releaseTypeStr)
|
||||
{
|
||||
case "main":
|
||||
releaseType = ReleaseType.Album;
|
||||
break;
|
||||
case "singles":
|
||||
releaseType = ReleaseType.Single;
|
||||
break;
|
||||
case "compilations":
|
||||
releaseType = ReleaseType.Compilation;
|
||||
break;
|
||||
default:
|
||||
throw new ApplicationException("Unknown release type");
|
||||
}
|
||||
|
||||
var discographyParser = new ArtistDiscographyParser(releaseType);
|
||||
artistDiscographies.AddRange(
|
||||
from albumXml in XpathMatchXmlList(xml, settings.DiscographyXpath)
|
||||
let album = discographyParser.Parse(albumXml)
|
||||
where album.Year > 0
|
||||
select album);
|
||||
|
||||
var artistId = StringUtility.CleanId(XpathMatchString(xml, settings.ArtistIdXpath));
|
||||
var artistName = XpathMatchString(xml, settings.ArtistXpath);
|
||||
|
||||
foreach (var artistDiscography in artistDiscographies)
|
||||
{
|
||||
artistDiscography.ArtistId = artistId;
|
||||
artistDiscography.ArtistName = artistName;
|
||||
}
|
||||
}
|
||||
return artistDiscographies;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
using System;
|
||||
using System.Xml;
|
||||
using MusicMetaTagger.Client.AllMusicGuide.Properties;
|
||||
using MusicMetaTagger.Core.Model;
|
||||
using MusicMetaTagger.Core.Utility;
|
||||
|
||||
namespace MusicMetaTagger.Client.AllMusicGuide.RemoteDataAccess.Parser
|
||||
{
|
||||
public class ArtistDiscographyParser : ParserBase<ArtistDiscography>
|
||||
{
|
||||
private readonly ReleaseType _releaseType;
|
||||
|
||||
public ArtistDiscographyParser(ReleaseType releaseType)
|
||||
{
|
||||
_releaseType = releaseType;
|
||||
}
|
||||
|
||||
public override ArtistDiscography Parse(XmlDocument xml)
|
||||
{
|
||||
var artistDiscography = new ArtistDiscography();
|
||||
var settings = ArtistDiscographyScraper.Default;
|
||||
|
||||
var albumUrl = XpathMatchString(xml, settings.AlbumUrlXpath);
|
||||
artistDiscography.AlbumId = RegexCapture(albumUrl, settings.AlbumUrlIdRegex);
|
||||
|
||||
var year = XpathMatchString(xml, settings.YearXpath);
|
||||
if (year.Length > 0 && StringUtility.IsNumeric(year))
|
||||
artistDiscography.Year = Convert.ToInt32(XpathMatchString(xml, settings.YearXpath));
|
||||
|
||||
//rating
|
||||
if (XpathMatch(xml, settings.RatingXpath))
|
||||
{
|
||||
var ratingString = XpathMatchString(xml, settings.RatingXpath);
|
||||
if (!string.IsNullOrEmpty(ratingString))
|
||||
{
|
||||
ratingString = RegexCapture(ratingString, settings.RatingRegex);
|
||||
int rating;
|
||||
if (int.TryParse(ratingString, out rating))
|
||||
artistDiscography.Rating = Convert.ToInt32(rating);
|
||||
}
|
||||
}
|
||||
|
||||
artistDiscography.Pick = XpathMatch(xml, settings.PickXpath);
|
||||
|
||||
if (XpathMatch(xml, settings.LabelXpath))
|
||||
artistDiscography.Label = XpathMatchString(xml, settings.LabelXpath);
|
||||
|
||||
artistDiscography.AlbumTitle = XpathMatchString(xml, settings.TitleXpath);
|
||||
|
||||
artistDiscography.ReleaseType = _releaseType;
|
||||
// EPs will have "[EP]" after the title
|
||||
if (RegexMatch(artistDiscography.AlbumTitle, settings.ReleaseTypeRegex))
|
||||
{
|
||||
var releaseType = RegexCapture(artistDiscography.AlbumTitle, settings.ReleaseTypeRegex);
|
||||
if (releaseType == "EP")
|
||||
artistDiscography.ReleaseType = ReleaseType.EP;
|
||||
}
|
||||
else if (artistDiscography.AlbumTitle.Contains("Box Set"))
|
||||
artistDiscography.ReleaseType = ReleaseType.BoxSet;
|
||||
|
||||
// TODO: add "has review"
|
||||
|
||||
return artistDiscography;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Xml;
|
||||
using MusicMetaTagger.Client.AllMusicGuide.Properties;
|
||||
using MusicMetaTagger.Core.Model;
|
||||
using MusicMetaTagger.Core.Utility;
|
||||
|
||||
namespace MusicMetaTagger.Client.AllMusicGuide.RemoteDataAccess.Parser
|
||||
{
|
||||
public class ArtistParser : ParserBase<Artist>
|
||||
{
|
||||
public override Artist Parse(XmlDocument artistXml)
|
||||
{
|
||||
var scraper = ArtistScaper.Default;
|
||||
var artist = new Artist();
|
||||
|
||||
artist.ArtistId = StringUtility.CleanId(XpathMatchString(artistXml, scraper.ArtistIdXpath));
|
||||
artist.ArtistName = XpathMatchString(artistXml, scraper.ArtistXpath);
|
||||
|
||||
if (XpathMatch(artistXml, scraper.GenreXpath))
|
||||
artist.Genre = XpathMatchString(artistXml, scraper.GenreXpath);
|
||||
|
||||
artist.Styles =
|
||||
XpathMatch(artistXml, scraper.StylesXpath)
|
||||
? XpathMatchStringList(artistXml, scraper.StylesXpath)
|
||||
: new List<string>();
|
||||
|
||||
return artist;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml;
|
||||
using MusicMetaTagger.Client.AllMusicGuide.Properties;
|
||||
using MusicMetaTagger.Core.Model;
|
||||
|
||||
namespace MusicMetaTagger.Client.AllMusicGuide.RemoteDataAccess.Parser
|
||||
{
|
||||
public class ArtistResultPageParser : ParserBase<List<ArtistResult>>
|
||||
{
|
||||
public override List<ArtistResult> Parse(XmlDocument xml)
|
||||
{
|
||||
var artistResults = new List<ArtistResult>();
|
||||
var settings = ArtistResultPageScraper.Default;
|
||||
var artistResultParser = new ArtistResultParser();
|
||||
|
||||
if (XpathMatch(xml, settings.ArtistXpath))
|
||||
{
|
||||
var artistResultsXmlList = XpathMatchXmlList(xml, settings.ArtistXpath);
|
||||
artistResults = artistResultsXmlList.Select(artistResultParser.Parse).ToList();
|
||||
var i = 1;
|
||||
artistResults.ForEach(ar => ar.ResultOrder = i++);
|
||||
}
|
||||
return artistResults;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
using System.Xml;
|
||||
using MusicMetaTagger.Client.AllMusicGuide.Properties;
|
||||
using MusicMetaTagger.Core.Model;
|
||||
|
||||
namespace MusicMetaTagger.Client.AllMusicGuide.RemoteDataAccess.Parser
|
||||
{
|
||||
public class ArtistResultParser : ParserBase<ArtistResult>
|
||||
{
|
||||
public override ArtistResult Parse(XmlDocument xml)
|
||||
{
|
||||
var artistResult = new ArtistResult();
|
||||
var settings = ArtistResultScraper.Default;
|
||||
|
||||
var artistId = XpathMatchString(xml, settings.ArtistUrlXpath);
|
||||
artistResult.ArtistId = RegexCapture(artistId, settings.ArtistUrIdRegex);
|
||||
|
||||
artistResult.ArtistName = XpathMatchString(xml, settings.ArtistXpath);
|
||||
if (XpathMatch(xml, settings.InfoXpath))
|
||||
{
|
||||
var infoRaw = XpathMatchString(xml, settings.InfoXpath);
|
||||
if (RegexMatch(infoRaw, settings.YearsActiveRegex))
|
||||
{
|
||||
var yearsActive = RegexCapture(infoRaw, settings.YearsActiveRegex);
|
||||
artistResult.YearsActive = yearsActive.Trim();
|
||||
}
|
||||
if (RegexMatch(infoRaw, settings.GenreRegex))
|
||||
{
|
||||
var genre = RegexCapture(infoRaw, settings.GenreRegex);
|
||||
artistResult.Genre = genre.Trim();
|
||||
}
|
||||
}
|
||||
return artistResult;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
using System.Xml;
|
||||
|
||||
namespace MusicMetaTagger.Client.AllMusicGuide.RemoteDataAccess.Parser
|
||||
{
|
||||
public interface IParser<out TEntity>
|
||||
{
|
||||
TEntity Parse(XmlDocument xml);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Xml;
|
||||
|
||||
namespace MusicMetaTagger.Client.AllMusicGuide.RemoteDataAccess.Parser
|
||||
{
|
||||
public abstract class ParserBase<TEntity> : IParser<TEntity>
|
||||
{
|
||||
public abstract TEntity Parse(XmlDocument xml);
|
||||
|
||||
protected static string RegexCapture(string str, string regexStr)
|
||||
{
|
||||
var regex = new Regex(regexStr);
|
||||
var match = regex.Match(str);
|
||||
if (match.Captures.Count == 0)
|
||||
throw new ApplicationException("Couldn't make regex match for "
|
||||
+ regexStr + " in " + str);
|
||||
return match.Captures[0].Value;
|
||||
}
|
||||
|
||||
protected static bool RegexMatch(string str, string regexStr)
|
||||
{
|
||||
var regex = new Regex(regexStr);
|
||||
var match = regex.Match(str);
|
||||
return match.Captures.Count > 0;
|
||||
}
|
||||
|
||||
protected static bool XpathMatch(XmlDocument xml, string xPath)
|
||||
{
|
||||
var nodes = xml.SelectNodes(xPath);
|
||||
return nodes != null && nodes.Count > 0;
|
||||
}
|
||||
|
||||
protected static string XpathMatchString(XmlDocument xml, string xPath)
|
||||
{
|
||||
var titleNodes = xml.SelectNodes(xPath);
|
||||
if (titleNodes == null || titleNodes.Count == 0)
|
||||
{
|
||||
//xml.Save(@"problem_" + DateTime.Now.Ticks + ".xml");
|
||||
throw new ApplicationException(string.Format("Couldn't find matching nodes for : \"{0}\" in {1}", xPath,
|
||||
xml.InnerXml));
|
||||
}
|
||||
var decodedValue = WebUtility.HtmlDecode(titleNodes[0].InnerText);
|
||||
return decodedValue.Trim();
|
||||
}
|
||||
|
||||
protected static List<string> XpathMatchStringList(XmlDocument xml, string xPath)
|
||||
{
|
||||
var titleNodes = xml.SelectNodes(xPath);
|
||||
if (titleNodes == null || titleNodes.Count == 0)
|
||||
throw new ApplicationException("Couldn't find matching nodes for : " + xPath);
|
||||
|
||||
return (
|
||||
from XmlNode node in titleNodes
|
||||
select WebUtility.HtmlDecode(node.InnerText)
|
||||
into decodedValue
|
||||
select decodedValue.Trim()
|
||||
).ToList();
|
||||
}
|
||||
|
||||
protected static IEnumerable<XmlDocument> XpathMatchXmlList(XmlDocument xml, string xPath)
|
||||
{
|
||||
var titleNodes = xml.SelectNodes(xPath);
|
||||
if (titleNodes == null || titleNodes.Count == 0)
|
||||
{
|
||||
xml.Save("problem.xml");
|
||||
throw new ApplicationException("Couldn't find matching nodes for : " + xPath);
|
||||
}
|
||||
|
||||
var xmlList = new List<XmlDocument>();
|
||||
foreach (XmlNode node in titleNodes)
|
||||
{
|
||||
var xmlDocument = new XmlDocument();
|
||||
xmlDocument.LoadXml(xml.FirstChild.InnerXml + "<root></root>");
|
||||
|
||||
var importNode = xmlDocument.ImportNode(node, true);
|
||||
if (xmlDocument.DocumentElement == null)
|
||||
throw new ApplicationException("xmlDocument.DocumentElement Null");
|
||||
xmlDocument.DocumentElement.AppendChild(importNode);
|
||||
|
||||
xmlList.Add(xmlDocument);
|
||||
}
|
||||
return xmlList;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml;
|
||||
using MusicMetaTagger.Client.AllMusicGuide.Properties;
|
||||
using MusicMetaTagger.Core.Model;
|
||||
|
||||
namespace MusicMetaTagger.Client.AllMusicGuide.RemoteDataAccess.Parser
|
||||
{
|
||||
public class SongAppearsOnAlbumParser : ParserBase<SongAppearsOnAlbum>
|
||||
{
|
||||
public override SongAppearsOnAlbum Parse(XmlDocument xml)
|
||||
{
|
||||
var albumResult = new SongAppearsOnAlbum();
|
||||
var settings = SongAppearsOnAlbumScraper.Default;
|
||||
|
||||
var albumUrl = XpathMatchString(xml, settings.AlbumUrlXpath);
|
||||
albumResult.AlbumId = RegexCapture(albumUrl, settings.AlbumUrlIdRegex);
|
||||
|
||||
if (XpathMatch(xml, settings.YearXpath))
|
||||
{
|
||||
var yearRaw = XpathMatchString(xml, settings.YearXpath);
|
||||
if (RegexMatch(yearRaw, settings.YearRegex))
|
||||
{
|
||||
var year = RegexCapture(yearRaw, settings.YearRegex);
|
||||
int yearInt;
|
||||
if (Int32.TryParse(year, out yearInt))
|
||||
albumResult.Year = yearInt;
|
||||
}
|
||||
}
|
||||
|
||||
if (XpathMatch(xml, settings.ArtistUrlXpath))
|
||||
{
|
||||
var artistId = XpathMatchString(xml, settings.ArtistUrlXpath);
|
||||
albumResult.ArtistId = RegexCapture(artistId, settings.ArtistUrIdRegex);
|
||||
albumResult.ArtistName = XpathMatchString(xml, settings.ArtistXpath);
|
||||
}
|
||||
else if (XpathMatch(xml, settings.ArtistNoUrlXpath))
|
||||
{
|
||||
albumResult.ArtistName = XpathMatchString(xml, settings.ArtistNoUrlXpath);
|
||||
}
|
||||
|
||||
albumResult.AlbumTitle = XpathMatchString(xml, settings.TitleXpath);
|
||||
|
||||
return albumResult;
|
||||
}
|
||||
}
|
||||
|
||||
public class SongParser : ParserBase<Song>
|
||||
{
|
||||
public override Song Parse(XmlDocument xml)
|
||||
{
|
||||
var song = new Song();
|
||||
var settings = SongScraper.Default;
|
||||
|
||||
song.SongTitle = XpathMatchString(xml, settings.SongTitleXpath);
|
||||
var songUrlId = XpathMatchString(xml, settings.SongUrlIdXpath);
|
||||
song.SongId = RegexCapture(songUrlId, settings.SongUrlIdRegex);
|
||||
|
||||
song.AppearsOnAlbum = new List<SongAppearsOnAlbum>();
|
||||
var songAppearsOnAlbumParser = new SongAppearsOnAlbumParser();
|
||||
|
||||
if (XpathMatch(xml, settings.AlbumXpath))
|
||||
{
|
||||
var albumResultInfoXmlList = XpathMatchXmlList(xml, settings.AlbumXpath);
|
||||
song.AppearsOnAlbum.AddRange(albumResultInfoXmlList.Select(songAppearsOnAlbumParser.Parse));
|
||||
var i = 1;
|
||||
song.AppearsOnAlbum.ForEach(ar => ar.ResultOrder = i++);
|
||||
}
|
||||
|
||||
return song;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml;
|
||||
using MusicMetaTagger.Client.AllMusicGuide.Properties;
|
||||
using MusicMetaTagger.Core.Model;
|
||||
|
||||
namespace MusicMetaTagger.Client.AllMusicGuide.RemoteDataAccess.Parser
|
||||
{
|
||||
public class SongResultPageParser : ParserBase<List<SongResult>>
|
||||
{
|
||||
public override List<SongResult> Parse(XmlDocument xml)
|
||||
{
|
||||
var songResults = new List<SongResult>();
|
||||
var settings = SongResultPageScraper.Default;
|
||||
var songResultScraper = new SongResultParser();
|
||||
|
||||
if (XpathMatch(xml, settings.SongXpath))
|
||||
{
|
||||
var songResultInfoXmlList = XpathMatchXmlList(xml, settings.SongXpath);
|
||||
songResults.AddRange(songResultInfoXmlList.Select(songResultScraper.Parse));
|
||||
var i = 1;
|
||||
songResults.ForEach(ar => ar.ResultOrder = i++);
|
||||
}
|
||||
return songResults;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
using System.Xml;
|
||||
using MusicMetaTagger.Client.AllMusicGuide.Properties;
|
||||
using MusicMetaTagger.Core.Model;
|
||||
|
||||
namespace MusicMetaTagger.Client.AllMusicGuide.RemoteDataAccess.Parser
|
||||
{
|
||||
public class SongResultParser : ParserBase<SongResult>
|
||||
{
|
||||
public override SongResult Parse(XmlDocument xml)
|
||||
{
|
||||
var songResult = new SongResult();
|
||||
var settings = SongResultScraper.Default;
|
||||
|
||||
songResult.SongTitle = XpathMatchString(xml, settings.SongTitleXpath);
|
||||
if (RegexMatch(songResult.SongTitle, settings.SongTitleRegex))
|
||||
songResult.SongTitle = RegexCapture(songResult.SongTitle, settings.SongTitleRegex);
|
||||
|
||||
var songUrl = XpathMatchString(xml, settings.SongUrlIdXpath);
|
||||
songResult.SongId = RegexCapture(songUrl, settings.SongUrlIdRegex);
|
||||
|
||||
if (XpathMatch(xml, settings.ArtistUrlXpath))
|
||||
{
|
||||
var artistId = XpathMatchString(xml, settings.ArtistUrlXpath);
|
||||
songResult.ArtistId = RegexCapture(artistId, settings.ArtistUrIdRegex);
|
||||
songResult.ArtistName = XpathMatchString(xml, settings.ArtistXpath);
|
||||
}
|
||||
|
||||
return songResult;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Xml;
|
||||
using MusicMetaTagger.Client.AllMusicGuide.Properties;
|
||||
using MusicMetaTagger.Core.Model;
|
||||
using MusicMetaTagger.Core.Utility;
|
||||
|
||||
namespace MusicMetaTagger.Client.AllMusicGuide.RemoteDataAccess.Parser
|
||||
{
|
||||
public class TrackParser : ParserBase<Track>
|
||||
{
|
||||
public override Track Parse(XmlDocument xml)
|
||||
{
|
||||
var track = new Track();
|
||||
var settings = TrackScraper.Default;
|
||||
|
||||
if (XpathMatch(xml, settings.TrackUrlXpath))
|
||||
{
|
||||
var trackUrl = XpathMatchString(xml, settings.TrackUrlXpath);
|
||||
track.TrackId = RegexCapture(trackUrl, settings.TrackUrlIdRegex);
|
||||
}
|
||||
|
||||
track.TrackNumber = Convert.ToInt32(XpathMatchString(xml, settings.TrackNumberXpath));
|
||||
|
||||
track.Pick = XpathMatch(xml, settings.PickXpath);
|
||||
|
||||
track.TrackTitle =
|
||||
XpathMatch(xml, settings.TitleXpath)
|
||||
? XpathMatchString(xml, settings.TitleXpath)
|
||||
: string.Empty;
|
||||
|
||||
if (XpathMatch(xml, settings.ComposerXpath))
|
||||
track.Composer =
|
||||
String.Join(", ",
|
||||
XpathMatchStringList(xml, settings.ComposerXpath).ToArray());
|
||||
|
||||
track.PerformerIds = new List<string>();
|
||||
var performerIdXpath = settings.PerformerIdXpath;
|
||||
if (!XpathMatch(xml, settings.PerformerIdXpath))
|
||||
performerIdXpath = settings.PerformerIdAlternateXpath;
|
||||
|
||||
if (XpathMatch(xml, performerIdXpath))
|
||||
{
|
||||
var performerIdsRaw = XpathMatchStringList(xml, performerIdXpath);
|
||||
foreach (var performerIdRaw in performerIdsRaw)
|
||||
{
|
||||
if (RegexMatch(performerIdRaw, settings.PerformerIdRegex))
|
||||
track.PerformerIds.Add(RegexCapture(performerIdRaw, settings.PerformerIdRegex));
|
||||
}
|
||||
}
|
||||
|
||||
var timeString = XpathMatchString(xml, settings.TimeXpath);
|
||||
track.TrackLength = StringUtility.ConvertTimeSpan(timeString);
|
||||
|
||||
return track;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user