extract description, image and favicon
This commit is contained in:
@@ -0,0 +1,137 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace ReadSharp.Ports.NReadability
|
||||
{
|
||||
public class MetaExtractor
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether [has value].
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <c>true</c> if [has value]; otherwise, <c>false</c>.
|
||||
/// </value>
|
||||
public bool HasValue { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the tags.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The tags.
|
||||
/// </value>
|
||||
public IEnumerable<XElement> Tags { get; private set; }
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="MetaExtractor"/> class.
|
||||
/// </summary>
|
||||
/// <param name="document">The document.</param>
|
||||
public MetaExtractor(XDocument document)
|
||||
{
|
||||
var documentRoot = document.Root;
|
||||
|
||||
if (documentRoot == null || documentRoot.Name == null || !"html".Equals(documentRoot.Name.LocalName, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
HasValue = false;
|
||||
return;
|
||||
}
|
||||
|
||||
var headElement = documentRoot.GetChildrenByTagName("head").FirstOrDefault();
|
||||
|
||||
if (headElement == null)
|
||||
{
|
||||
HasValue = false;
|
||||
return;
|
||||
}
|
||||
|
||||
IEnumerable<XElement> meta = headElement.GetChildrenByTagName("meta");
|
||||
IEnumerable<XElement> link = headElement.GetChildrenByTagName("link");
|
||||
|
||||
Tags = meta != null ? meta.Concat(link) : link;
|
||||
HasValue = Tags != null && Tags.Count() > 0;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets the meta description.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public string GetMetaDescription()
|
||||
{
|
||||
return SearchCandidates(new Dictionary<string, string>()
|
||||
{
|
||||
{ "property|og:description", "content" },
|
||||
{ "name|description", "content" }
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets the meta image.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public string GetMetaImage()
|
||||
{
|
||||
return SearchCandidates(new Dictionary<string, string>()
|
||||
{
|
||||
{ "property|og:image", "content" },
|
||||
{ "rel|apple-touch-icon", "href" },
|
||||
{ "rel|apple-touch-icon-precomposed", "href"},
|
||||
{ "name|msapplication-square310x310logo", "content" },
|
||||
{ "name|msapplication-square150x150logo", "content" },
|
||||
{ "name|msapplication-square70x70logo", "content" },
|
||||
{ "name|msapplication-TileImage", "content" },
|
||||
{ "rel|image_src", "href" }
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets the meta favicon.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public string GetMetaFavicon()
|
||||
{
|
||||
return SearchCandidates(new Dictionary<string, string>()
|
||||
{
|
||||
{ "rel|icon", "href" },
|
||||
{ "rel|shortcut icon", "href" }
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Searches the candidates.
|
||||
/// </summary>
|
||||
/// <param name="candidates">The candidates.</param>
|
||||
/// <returns></returns>
|
||||
private string SearchCandidates(Dictionary<string, string> candidates)
|
||||
{
|
||||
string result = null;
|
||||
|
||||
foreach (var candidate in candidates)
|
||||
{
|
||||
string[] type = candidate.Key.Split('|');
|
||||
|
||||
XElement element = Tags
|
||||
.Where(item => String.Equals(item.GetAttributeValue(type[0], null), type[1], StringComparison.OrdinalIgnoreCase))
|
||||
.FirstOrDefault();
|
||||
|
||||
if (element != null)
|
||||
{
|
||||
result = element.GetAttributeValue(candidate.Value, "");
|
||||
}
|
||||
|
||||
if (result != null && result.Length > 1)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -49,6 +49,7 @@
|
||||
<Compile Include="Enums.cs" />
|
||||
<Compile Include="HtmlUtils.cs" />
|
||||
<Compile Include="InternalErrorException.cs" />
|
||||
<Compile Include="MetaExtractor.cs" />
|
||||
<Compile Include="NReadabilityTranscoder.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="SgmlDomBuilder.cs" />
|
||||
|
||||
@@ -159,6 +159,7 @@ namespace ReadSharp.Ports.NReadability
|
||||
|
||||
private Func<AttributeTransformationInput, AttributeTransformationResult> _imageSourceTranformer;
|
||||
private Func<AttributeTransformationInput, AttributeTransformationResult> _anchorHrefTransformer;
|
||||
private Func<AttributeTransformationInput, AttributeTransformationResult> _metaTransformer;
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -249,11 +250,38 @@ namespace ReadSharp.Ports.NReadability
|
||||
|
||||
bool titleExtracted = !string.IsNullOrEmpty(extractedTitle);
|
||||
|
||||
MetaExtractor metaExtractor = new MetaExtractor(transcodedXmlDocument);
|
||||
|
||||
string description = null;
|
||||
Uri image = null;
|
||||
Uri favicon = null;
|
||||
|
||||
if (metaExtractor.HasValue)
|
||||
{
|
||||
description = metaExtractor.GetMetaDescription();
|
||||
string imageString = metaExtractor.GetMetaImage();
|
||||
string faviconString = metaExtractor.GetMetaFavicon();
|
||||
|
||||
if (imageString != null)
|
||||
{
|
||||
imageString = ResolveElementUrl(imageString, transcodingInput.Url);
|
||||
Uri.TryCreate(imageString, UriKind.Absolute, out image);
|
||||
}
|
||||
if (faviconString != null)
|
||||
{
|
||||
faviconString = ResolveElementUrl(faviconString, transcodingInput.Url);
|
||||
Uri.TryCreate(faviconString, UriKind.Absolute, out favicon);
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
new TranscodingResult(contentExtracted, titleExtracted)
|
||||
{
|
||||
ExtractedContent = transcodedContent,
|
||||
ExtractedTitle = extractedTitle,
|
||||
ExtractedDescription = description,
|
||||
ExtractedFavicon = favicon,
|
||||
ExtractedImage = image,
|
||||
NextPageUrl = nextPageUrl,
|
||||
Images = images
|
||||
};
|
||||
@@ -1835,6 +1863,13 @@ namespace ReadSharp.Ports.NReadability
|
||||
set { _anchorHrefTransformer = value; }
|
||||
}
|
||||
|
||||
|
||||
public Func<AttributeTransformationInput, AttributeTransformationResult> MetaTranformer
|
||||
{
|
||||
get { return _metaTransformer; }
|
||||
set { _metaTransformer = value; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Xml.Linq;
|
||||
|
||||
@@ -21,6 +22,12 @@ namespace ReadSharp.Ports.NReadability
|
||||
|
||||
public string NextPageUrl { get; set; }
|
||||
|
||||
public string ExtractedDescription { get; set; }
|
||||
|
||||
public Uri ExtractedImage { get; set; }
|
||||
|
||||
public Uri ExtractedFavicon { get; set; }
|
||||
|
||||
public XDocument RawDocument { get; set; }
|
||||
|
||||
public IEnumerable<XElement> Images { get; set; }
|
||||
|
||||
@@ -8,6 +8,22 @@ namespace ReadSharp
|
||||
/// </summary>
|
||||
public class Article
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the title.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The title.
|
||||
/// </value>
|
||||
public string Title { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the description.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The description.
|
||||
/// </value>
|
||||
public string Description { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the content.
|
||||
/// </summary>
|
||||
@@ -16,6 +32,22 @@ namespace ReadSharp
|
||||
/// </value>
|
||||
public string Content { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the front image.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The front image.
|
||||
/// </value>
|
||||
public Uri FrontImage { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the favicon.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The favicon.
|
||||
/// </value>
|
||||
public Uri Favicon { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the images.
|
||||
/// </summary>
|
||||
@@ -24,14 +56,6 @@ namespace ReadSharp
|
||||
/// </value>
|
||||
public List<ArticleImage> Images { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the title.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The title.
|
||||
/// </value>
|
||||
public string Title { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the next page URL.
|
||||
/// </summary>
|
||||
|
||||
+6
-3
@@ -68,7 +68,7 @@ namespace ReadSharp
|
||||
/// </summary>
|
||||
/// <param name="uri">An URI to extract the content from.</param>
|
||||
/// <param name="bodyOnly">if set to <c>true</c> [only body is returned].</param>
|
||||
/// <param name="noHeadline">if set to <c>true</c> [no headline (h1) is included].</param>
|
||||
/// <param name="noHeadline">if set to <c>true</c> [no headline (h1) is included in generated HTML].</param>
|
||||
/// <returns>
|
||||
/// An article with extracted content and meta information.
|
||||
/// </returns>
|
||||
@@ -124,9 +124,12 @@ namespace ReadSharp
|
||||
// create article
|
||||
return new Article()
|
||||
{
|
||||
Content = transcodingResult.ExtractedContent,
|
||||
Images = images,
|
||||
Title = transcodingResult.ExtractedTitle,
|
||||
Description = transcodingResult.ExtractedDescription,
|
||||
Content = transcodingResult.ExtractedContent,
|
||||
FrontImage = transcodingResult.ExtractedImage,
|
||||
Images = images,
|
||||
Favicon = transcodingResult.ExtractedFavicon,
|
||||
NextPage = transcodingResult.NextPageUrl != null ? new Uri(transcodingResult.NextPageUrl, UriKind.Absolute) : null
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user