返回 链接(不包括 mailto 链接)时出现问题
本文关键字:链接 问题 mailto 不包括 返回 | 更新日期: 2023-09-27 18:18:25
我正在使用HTML敏捷包来定义一个返回网页链接的函数。问题是它返回包括 mailto 在内的所有链接。
在程序的稍后,当链接被处理时,mailto链接会断开。我正在尝试消除它们包含在_links的函数输出列表中
我的函数定义为:
var linkNodes = _htmlDocument.Value.DocumentNode.SelectNodes("//a");
if (linkNodes == null)
return Enumerable.Empty<Link>();
var links = new List<Link>();
foreach (var linkNode in linkNodes)
{
var href = linkNode.GetAttributeValue("href", "#");
if (!Uri.IsWellFormedUriString(href, UriKind.RelativeOrAbsolute))
continue;
var url = href.ToAbsoluteUri(Url);
var follow = linkNode.GetAttributeValue("rel", "follow");
links.Add(new Link(Url, url, linkNode.InnerText, follow));
}
_links = links;
我的 LINQ 几乎有效(在摆脱 mailto 方面起作用,但返回字符串而不是与使用的战士匹配的节点(:
var linkNodes = _htmlDocument.Value.DocumentNode.SelectNodes("//a[@href]")
.Select(a => a.Attributes["href"].Value)
.Where(href => !href.StartsWith("mailto:")) // skip emails, find only url links
.ToList();
关于选择和位置:
根据MSDN
Linq Select
会根据集合的项目将您的集合转换为新形式。下面是一个简单的示例。
IEnumerable<int> collectionOfInt = Enumerable.Range(0, 10);
IEnumerable<string> collectionOfString = collectionOfInt.Select(i => i.ToString());
IEnumerable<int> lengthOfStrings = collectionOfString.Select(str => str.Length);
首先,您有一个从 0 到 9 的int
集合。如您所见,Select 返回一个新的字符串集合,但基于collectionOfInt
项,因此您有来自"0","1",...,"9"
的字符串。请注意,Select 的执行是延迟的,因此必须使用 ToList
来实际执行该查询。
当您在collectionOfString
上执行Select
时也是如此。如您所见,您丢失了实际的字符串,您将获得这些字符串的长度(1,1,...,1
(。
现在你的 Linq
var linkNodes = _htmlDocument.Value.DocumentNode.SelectNodes("//a[@href]")
.Select(a => a.Attributes["href"].Value)
.Where(href => !href.StartsWith("mailto:"))
.ToList();
你有一个节点集合,但实际上Select(a => a.Attributes["href"].Value)
会把你的节点变成字符串的集合,你会丢失实际的节点。
.Select(a => a.Attributes["href"].Value) // Changes main collection into values
.Where(href => !href.StartsWith("mailto:")) // searches on values not main collection thus returns values again.
所以你必须把它全部放在Where
部分,因为Where
不会改变集合类型。仅当该元素的条件为 true 时,它才会从集合中选择元素。
根据我的解释,href
在前面的查询中是a.Attributes["href"].Value
。因此,为了不丢失原始元素,只需将a.Attributes["href"].Value
包裹在href
所以你会有
.Where(node => !node.Attributes["href"].Value.StartsWith("mailto:")) // searches on nodes collection thus returns nodes
关于空异常部分:
Where
Linq 查询不会搜索空项。 因此,只要上一个查询中的href
或a.Attributes["href"].Value
为 null,它就会跳过该项而不选择它。
在你内联Select
到现在Where
,只检查node
的可空性,而不执行函数!node.Attributes["href"].Value.StartsWith("mailto:")
。
基本上是因为Value
有可能出现 null,所以您将在无法处理 null 的StartsWith("mailto:")
上获得异常。
在 C#6 中,您可以使用混合null conditional
和Null-coalescing
运算符来解决此问题。
htmlDocument.Value.DocumentNode.SelectNodes("//a[@href]")
.Where(node => !node.Attributes["href"].Value?.StartsWith("mailto:") ?? false).ToList();
如果 Value?.
的值为 null,则它不会继续执行StartsWith("mailto:")
,而是直接返回 null。
因为?.
的返回类型是nullable bool
所以当运算符的左侧为 null 时?? false
将返回 false。