【问题标题】:Compare XPath list to find the closest to another node?比较 XPath 列表以找到最接近另一个节点?
【发布时间】:2012-03-08 17:38:54
【问题描述】:

我有以下节点

"/html[1]/body[1]/div[1]/div[1]/div[3]/div[1]/div[7]/p[1]/#text[1]"

我怎样才能确定其中最后一个是最接近的?

"/html[1]/body[1]/div[1]/div[1]/div[3]/div[1]/div[4]/div[1]/img[1]"
"/html[1]/body[1]/div[1]/div[1]/div[3]/div[1]/div[4]/div[3]/a[1]/img[1]"
"/html[1]/body[1]/div[1]/div[1]/div[3]/div[1]/div[4]/div[3]/a[2]/img[1]"
"/html[1]/body[1]/div[1]/div[1]/div[3]/div[1]/div[4]/div[5]/img[1]"
"/html[1]/body[1]/div[1]/div[1]/div[3]/div[1]/div[5]/div[1]/img[1]"

不一定是最后一个。

我是这样到达那里的:

protected string GuessThumbnail(HtmlDocument document)
{
    HtmlNode root = document.DocumentNode;
    IEnumerable<string> result = new List<string>();

    HtmlNode description = root.SelectSingleNode(DescriptionPredictiveXPath);
    if (description != null) // in this case, we predict relevant images are the ones closest to the description text node.
    {
        HtmlNode node = description.ParentNode;
        while (node != null)
        {
            string path = string.Concat(node.XPath, ImageXPath);
            node = node.ParentNode;
            IEnumerable<HtmlNode> nodes = root.SelectNodesOrEmpty(path);

            // find the image tag that's closest to the text node.
            if (nodes.Any())
            {
                var xpaths = nodes.Select(n => n.XPath);
                xpaths.ToList();

                // return closest
            }
        }
    }
    // figure some other way to do it

    throw new NotImplementedException();
}

【问题讨论】:

  • 您的意思是在文档结构中与目标元素的距离最近吗?
  • 是的,就是这样。我想以某种方式找出div[7] 更接近div[5] 而不是div[4],如果有多个div[5],则检查下一级,等等。直到找到最接近的元素。
  • 您的代码是否使用 CodePlex 的 Html Agility Pack?
  • 另外,您需要排序的元素是否总是在同一级别具有相同的元素类型,即 div 到 div 等?问题是如果索引器不是,则您无法确定它们的接近程度,并且这消除了简单地比较 xpath 的能力。如果它们是不同的节点,那么区分的唯一方法是遍历树并记录每个发现的节点的距离度量。

标签: c# xpath html-agility-pack closest prediction


【解决方案1】:

考虑为每个节点分配“深度优先顺序在整个树中的位置”。这样比较 2 个节点会非常简单。

如果您可以将任意数据附加到您的节点 - 直接添加它。否则有所有节点的字典来定位地图。

请注意,根据您需要进行此比较的次数,此方法可能会降低您的速度,但它应该易于实施和衡量,它符合您的要求。

【讨论】:

    【解决方案2】:

    是这样的吗:

        protected string GuessThumbnail(HtmlDocument document)
        {
            HtmlNode root = document.DocumentNode;
            HtmlNode description = root.SelectSingleNode(DescriptionPredictiveXPath);
    
            if (description != null)
            {
                // in this case, we predict relevant images are the ones closest to the description text node.
                HtmlNode parent = description.ParentNode;
                while (parent != null)
                {
                    string path = string.Concat(parent.XPath, ImageXPath);
                    IList<HtmlNode> images = root.SelectNodesOrEmpty(path).ToList();
    
                    // find the image tag that's closest to the text node.
                    if (images.Any())
                    {
                        HtmlNode descriptionOutermost = description.ParentNodeUntil(parent); // get the first child towards the description from the parent node.
                        int descriptionIndex = descriptionOutermost.GetIndex(); // get the index of the description's outermost element.
    
                        HtmlNode closestToDescription = null;
                        int distanceToDescription = int.MaxValue;
    
                        foreach (HtmlNode image in images)
                        {
                            int index = image.ParentNodeUntil(parent).GetIndex(); // get the index of the image's outermost element.
                            if (index > descriptionIndex)
                            {
                                index *= -1;
                            }
                            int distance = descriptionIndex - index;
                            if (distance < distanceToDescription)
                            {
                                closestToDescription = image;
                                distanceToDescription = distance;
                            }
                        }
                        if (closestToDescription != null)
                        {
                            string source = closestToDescription.Attributes["src"].Value;
                            return source;
                        }
                    }
    
                    parent = parent.ParentNode;
                }
            }
            // figure some other way to do it
    
            throw new NotImplementedException();
        }
    
    
    public static HtmlNode ParentNodeUntil(this HtmlNode node, HtmlNode parent)
    {
        while (node.ParentNode != parent)
        {
            node = node.ParentNode;
        }
        return node;
    }
    public static int GetIndex(this HtmlNode node)
    {
        return node.ParentNode.ChildNodes.IndexOf(node);
    }
    

    【讨论】:

      猜你喜欢
      • 2017-07-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-02
      • 1970-01-01
      • 2020-09-16
      • 2019-08-26
      • 1970-01-01
      相关资源
      最近更新 更多