代码之家  ›  专栏  ›  技术社区  ›  Bill Karwin

屏幕抓取:正则表达式还是XQuery表达式?

  •  6
  • Bill Karwin  · 技术社区  · 17 年前

    我在回答面试中的一些问答题,问题是我将如何做屏幕抓取。也就是说,从网页中挑选内容,假设您没有更好的结构化方式直接查询信息(例如web服务)。

    我的解决办法是使用 函数 表示表达式相当长,因为我需要的内容在HTML层次结构中相当深。在我找到一个元素之前,我必须通过一种公平的方式搜索祖先 id 属性例如,在Amazon.com页面上搜索产品维度如下所示:

    //a[@id="productDetails"]
    /following-sibling::table
    //h2[contains(child::text(), "Product Details")]
    /following-sibling::div
    //li
    /b[contains(child::text(), "Product Dimensions:")]
    /following-sibling::text()
    

    这是一个非常糟糕的表达,但这就是为什么Amazon提供了web服务API。无论如何,这只是一个例子。问题不是关于亚马逊,而是关于屏幕抓取。

    面试官不喜欢我的解决方案。他认为它很脆弱,因为亚马逊改变页面设计可能需要重写XQuery表达式。调试一个与它所应用的页面中的任何内容都不匹配的XQuery表达式是很困难的。

    我并不反对他的说法,但我不认为他的解决方案有任何改进:他认为最好使用 正则表达式 ,并搜索装运重量附近的内容和标记。例如,使用Perl:

    $html =~ m{<li>\s*<b>\s*Product Dimensions:\s*</b>\s*(.*?)</li>}s;
    

    <LI> ),或添加CSS属性或更改 <b> <span> 或者将标签“产品尺寸:”更改为“尺寸:”或许多其他类型的更改。我的观点是正则表达式不能解决他在我的XQuery解决方案中指出的缺点。

    但除此之外,正则表达式可以发现误报,除非向表达式添加足够的上下文。它还可能无意中匹配恰好位于注释、属性字符串或CDATA节中的内容。

    PS:为了论证起见,假设没有web服务API或其他更直接的方式来获取所需的内容。

    8 回复  |  直到 17 年前
        1
  •  4
  •   John Saunders    17 年前

    我不知道XQuery,但在我看来它像一个XPATH表达式。如果是这样的话,那么有这么多的“/”操作符,看起来有点贵。

        2
  •  3
  •   MarkusQ    17 年前

    出于经理给出的原因,我会使用正则表达式,再加上一些(更具可移植性,外部程序员更容易遵循,等等)。

    地方的 变化,而你的是脆弱的关于 全球的 变化。任何破坏他的东西都有可能破坏你的,但反之亦然。

    最后,将slop/flex构建到他的解决方案中要容易得多(例如,如果您必须处理输入中的多个微小变化)。

        3
  •  2
  •       17 年前

    当然//XPATH Expersion的废弃成本相当高。

        4
  •  1
  •   Anonymous    17 年前

    我正在使用 BeautifulSoup 用于报废。

        5
  •  1
  •   Brian Guthrie    17 年前

    事实上,我发现CSS搜索表达式比两者都更容易阅读。在您选择的语言中可能至少存在一个库,它将解析页面并允许您编写CSS指令来定位特定元素。如果附近有一个合适的类或ID钩子,那么表达式就非常简单。否则,抓取看起来合适的元素并遍历它们以找到您需要的元素。

    至于易碎品,它们都是易碎品。根据定义,屏幕抓取取决于该页面的作者,而不是大幅更改其布局。选择一个可读性强、以后易于更改的解决方案。

        6
  •  1
  •   Pontus Gagge    17 年前

    我相当喜欢这本书 HTML agility pack :结合XPath的表达能力,您可以容忍不符合XHTML的网页。

        7
  •  1
  •   Rafal Rusin    16 年前

    //b[contains(child::text(), "Product Dimensions:")]/following-sibling::text()
    

    这是一个很好的选择。

    当做

    Rafal Rusin

        8
  •  1
  •   jlee88my    13 年前

    要处理html页面,最好使用HTMLAgilityPack(以及一些Linq代码)。这是解析所有元素和/或使用XPath进行直接搜索的好方法。在我看来,它比正则表达式更准确,更容易编程。以前我有点不愿意使用它,但它很容易添加到您的项目中,我认为这是处理html的de-factor标准。 http://htmlagilitypack.codeplex.com/

    祝你好运