Bil*_*win 6 regex xquery screen-scraping
我正在回答一些面试的测验问题,问题是如何进行屏幕抓取.也就是说,假设您没有更好的结构化方式直接查询信息(例如Web服务),从网页中挑选内容.
我的解决方案是使用XQuery表达式.表达式相当长,因为我需要的内容在HTML层次结构中非常深入.在找到具有id属性的元素之前,我必须以一种公平的方式搜索祖先.例如,抓取Product Dimensions的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()
Run Code Online (Sandbox Code Playgroud)
这是一个非常讨厌的表达,但这就是亚马逊提供Web服务API的原因.无论如何,这只是一个例子.问题不在于亚马逊,而在于屏幕刮擦.
面试官不喜欢我的解决方案.他认为它很脆弱,因为亚马逊改变页面设计可能需要重写XQuery表达式.调试与它所应用的页面中的任何内容都不匹配的XQuery表达式很难.
我并不反对他的陈述,但我认为他的解决方案没有任何改进:他认为最好使用正则表达式,并在运输重量附近搜索内容和标记.例如,使用Perl:
$html =~ m{<li>\s*<b>\s*Product Dimensions:\s*</b>\s*(.*?)</li>}s;
Run Code Online (Sandbox Code Playgroud)
我的反驳是,这也很容易让亚马逊改变他们的HTML代码.他们可能会给在首都(HTML标签<LI>),或者添加CSS属性或更改<b>到<span>或更改标签"产品尺寸:"到"尺寸:"或其他许多种变化.我的观点是正则表达式无法解决他在XQuery解决方案中提到的弱点.
但此外,正则表达式可以找到误报,除非您为表达式添加了足够的上下文.它还可能无意中匹配恰好位于注释,属性字符串或CDATA部分内的内容.
我的问题是,你用什么技术来进行屏幕抓取?你为什么选择这个解决方案?是否有一些令人信服的理由使用它?或者从不使用另一个?除了上面展示的那些之外,还有第三种选择吗?
PS:假设为了论证,没有Web服务API或其他更直接的方式来获取所需内容.
由于经理给出的原因,我会使用正则表达式,再加上一些(更便携,更容易让外部程序员遵循,等等)。
你的反驳观点忽略了一点,即他的解决方案对于局部变化来说是脆弱的,而你的解决方案对于全球变化来说是脆弱的。任何破坏他的东西都可能会破坏你的,但反之则不然。
最后,将 slop / flex 构建到他的解决方案中要容易得多(例如,如果您必须处理输入中的多个微小变化)。