【问题标题】:HTML Agility Pack Screen Scraping XPATH isn't returning dataHTML 敏捷包屏幕抓取 XPATH 不返回数据
【发布时间】:2010-03-23 13:00:03
【问题描述】:

我正在尝试为 Digikey 编写屏幕抓取工具,以便我们公司能够在零件停产时准确跟踪定价、零件可用性和产品更换。我在 Chrome Devtools 和 Firefox 上的 Firebug 中看到的 XPATH 与我的 C# 程序看到的似乎存在差异。

我目前正在抓取的页面是http://search.digikey.com/scripts/DkSearch/dksus.dll?Detail&name=296-12602-1-ND

我目前使用的代码非常快而且很脏......

   //This function retrieves data from the digikey
   private static List<string> ExtractProductInfo(HtmlDocument doc)
   {
       List<HtmlNode> m_unparsedProductInfoNodes = new List<HtmlNode>();
       List<string> m_unparsedProductInfo = new List<string>();

       //Base Node for part info
       string m_baseNode = @"//html[1]/body[1]/div[2]";

       //Write part info to list
       m_unparsedProductInfoNodes.Add(doc.DocumentNode.SelectSingleNode(m_baseNode + @"/table[1]/tr[1]/td[1]/table[1]/tr[1]/td[1]"));
       //More lines of similar form will go here for more info
       //this retrieves digikey PN

       foreach(HtmlNode node in m_unparsedProductInfoNodes)
       {
           m_unparsedProductInfo.Add(node.InnerText);
       }

       return m_unparsedProductInfo;
   }

虽然我使用的路径似乎是“正确的”,但当我查看列表“m_unparsedProductInfoNodes”时,我总是得到 NULL

知道这里发生了什么吗?我还要补充一点,如果我在 baseNode 上执行“SelectNodes”,它只会返回一个 div,其中唯一重要的子节点是“cs=####”,这似乎因浏览器用户代理而异。如果我无论如何都尝试使用它(将 /cs=0 放在无法识别的浏览器的路径中),它会坚持认为我的表达式不会评估为节点集,但留下它们仍然会留下所有数据过去的问题div[2] 返回为 NULL。

【问题讨论】:

  • 一个指向你试图抓取的 HTML 的链接会有很大帮助。如果它是敏感数据或不易链接,那么匿名示例将很有用。无论如何,您 m_baseName 正确地只返回一个 div 元素,因为这就是 XPath 表达式所得到的:任何 html 元素的第一个 body 元素中的第二个 div 元素。应该只有一个html 元素,因此应该只返回一个div。你觉得这个表达式有什么作用?
  • search.digikey.com/scripts/DkSearch/… 是部分示例。在检查了它返回的内容之后,DIV 看起来是正确的,奇怪的是如果它不为 NULL,我就无法引用它之外的任何内容。我已经获取了通过 LoadHtml 存储的 HTML 并保存了它。在使用 Firebug 检查之后,一切看起来都应该在它应该在的位置,所以我将暂时排除 UserAgent 问题。例如,当我想查找 DK 零件号时,我使用以下路径://html[1]/body[1]/div[2]/table[1]/tr[1]/td[1]/table[ 1]/tr[1]/td[1]。返回值为NULL
  • 另外,当查看它返回的 m_base div 时,唯一重要的子节点是 CS=#### (似乎随着浏览器用户代理设置而变化)但是如果我在我的路径中包含它我得到“表达式必须评估为节点集”。错误信息。
  • 这只是一些糟糕的编码,我在没有 C# 知识的情况下开始了这个项目(我不太了解变量是如何分类的)。现在更好理解了,所以我真的需要回去纠正这个问题。

标签: c# screen-scraping html-agility-pack web-scraping


【解决方案1】:

尝试使用这个 XPath 表达式:

/html[1]/body[1]/div[2]/cs=0[1]/rf=141[1]/table[1]/tr[1]/td[1]/table[1]/tr[1]/td[1]

在 Firefox 中使用 Google Chrome 开发人员工具和 Firebug,网页似乎在第一个表格之前有一个“cs”和“rf”标签。比如:

<cs="0">
  <rf="141">
    <table>
    ...
    </table>
  </rf>
</cs>

当您想要解析 已知 HTML 文件但没有得到预期的结果时,了解正在发生的事情可能会有用。在这种情况下,我只是这样做了:

string xpath = "";

//In this case I'll get all cells and see what cell has the text "296-12602-1-ND"

foreach (HtmlNode node in doc.DocumentNode.SelectNodes("//td"))
{
    if (node.InnerText.Trim() == "296-12602-1-ND")
        xpath = node.XPath; //Here it is
}

或者您可以在文档加载后调试您的应用程序,然后遍历每个子节点,直到找到要从中获取信息的节点。如果你只是在找到 InnerText 的时候设置断点,你可以只通过父母,然后继续寻找其他节点。我通常会在“监视”窗口中手动输入命令并使用树视图导航以查看属性、属性和子项。

【讨论】:

  • 我昨天确实这样做了,是的,当单步执行 XPATH 树时,CS 和 RF 标签会显示出来。但是,如果您无论如何都包含它们,那么它会抱怨它“不是节点集”。如果你忽略它们,它不再抱怨,但我得到 NULL。我很困惑。今天早上我正在尝试 python/beautiful soup 看看它是否只是 HTML Agility 中的一个错误或其他什么。此外,digikey 在从表格标签中清除任何有用信息方面做得非常好,将它们减少到最低限度的 、没有 ID 或我能看到的任何其他有助于识别它们的直接路径。
【解决方案2】:

只是为了更新:

我从 c# 切换到更友好的 Python(我的编程经验是 asm、c 和 python,整个 OO 是全新的)并设法纠正了我的 xpath 问题。标签确实是问题,但幸运的是它是独一无二的,所以一点正则表达式和一条删除线,我的状态很好。我不确定为什么这样的标签会破坏 XPATH。如果有人有一些见解,我想听听。

【讨论】:

    猜你喜欢
    • 2012-07-18
    • 2010-11-06
    • 2016-06-01
    • 2014-03-20
    • 2015-02-16
    • 1970-01-01
    • 2011-03-04
    • 2018-03-04
    • 1970-01-01
    相关资源
    最近更新 更多