解析和使用网站数据的“智能”方式?

时间:2009-08-03 17:04:23

标签: html web-services parsing webpage html-content-extraction

如何智能地解析搜索结果在页面上返回的数据?

例如,假设我想通过解析许多图书提供商网站的搜索结果来创建一个搜索在线图书的网络服务。我可以获取页面的原始HTML数据,并做一些正则表达式以使数据适用于我的Web服务,但如果任何网站更改了页面的格式,我的代码就会中断!

RSS确实是一个了不起的选择,但许多网站没有基于XML / JSON的搜索。

是否有任何套件可以帮助自动在页面上传播信息?一个疯狂的想法是让模糊的AI模块识别搜索结果页面上的模式,并相应地解析结果......

12 个答案:

答案 0 :(得分:24)

我最近做了一些,这是我的经历。

有三种基本方法:

  1. 正则表达式。
    • 最灵活,最容易使用松散结构的信息和不断变化的格式。
    • 难以进行结构/标签分析,但更容易进行文本匹配。
    • 内置数据格式验证。
    • 比其他人更难维护,因为您必须为要用于提取/转换文档的每个模式编写正则表达式
    • 通常慢于2和3.
    • 适用于类似格式的项目列表
    • 一个好的正则表达式开发/测试工具和一些示例页面将有所帮助。我在这里有关于RegexBuddy的好话​​。试试他们的演示。
    • 我在这方面取得了最大的成功。灵活性使您可以使用讨厌,野蛮,野外的HTML代码。
  2. 将HTML转换为XHTML并使用XML提取工具。清理HTML,将其转换为合法的XHTML,并使用XPath / XQuery / X-将其作为XML数据进行查询。
    • 工具:TagSoup,HTMLTidy等
    • HTML-to-XHML转换的质量非常重要,且变化很大。
    • 最佳解决方案,如果您想要的数据是由HTML布局和标签(HTML表格,列表,DIV / SPAN组等中的数据)构建的,则
    • 最适合获取链接结构,嵌套表格,图像,列表等
    • 应该比选项1快,但比选项3慢。
    • 如果内容格式更改/可变,但文档结构/布局不可用,则效果很好。
    • 如果数据不是由HTML标签构建的,那么您就遇到了麻烦。
    • 可与选项1一起使用。
  3. 分析器生成器(ANTLR等) - 创建用于解析的语法&分析页面。
    • 我没有尝试过这个,因为它不适合我的(杂乱的)页面
    • 如果HTML结构高度结构化,非常稳定,规则且永不改变,则最合适。
    • 如果文档中有易于描述的模式,但它们不涉及HTML标记并涉及递归或复杂行为,请使用此方法
    • 不需要XHTML输入
    • 最快的吞吐量,通常是
    • 学习曲线大,但更易于维护
  4. 我在选项2中使用web harvest进行了修改,但我发现它们的语法有点奇怪。混合使用XML和一些伪Java脚本语言。如果您喜欢Java,并且喜欢XML风格的数据提取(XPath,XQuery),它可能是您的门票。


    编辑:如果您使用正则表达式,请确保使用具有延迟量词和捕获组的库! PHP的旧正则表达式库缺少这些,它们对于在HTML中打开/关闭标记之间的数据匹配是必不可少的。

答案 1 :(得分:3)

如果没有修复 HTML结构进行解析,我不愿意维护正则表达式来查找数据。您可能更幸运通过构建树的适当解析器来解析HTML。然后选择那些更易于维护的元素。

显然,最好的方法是引擎的一些XML输出,带有可以解析和验证的固定标记。我认为,对于生成的树进行一些“黑暗”探测的HTML解析库比正则表达式更容易维护。

这样,您只需检查<a href="blah" class="cache_link">...转入<a href="blah" class="cache_result">...或其他任何内容。

最重要的是,使用正则表达式来渲染特定元素将是严峻的。一种更好的方法是构建一个类似于页面模型的DOM,并查找标签中字符数据的“锚点”。

向该网站发送电子邮件,说明XML API案例......您可能会被录用!

答案 2 :(得分:3)

您没有说出您正在使用的语言。在Java领域,您可以使用TagSoup和XPath来帮助减少痛苦。有一个来自this blog的例子(当然,根据你的需要,XPath会变得更加复杂):

URL url = new URL("http://example.com");
SAXBuilder builder = new SAXBuilder("org.ccil.cowan.tagsoup.Parser"); // build a JDOM tree from a SAX stream provided by tagsoup
Document doc = builder.build(url);
JDOMXPath titlePath = new JDOMXPath("/h:html/h:head/h:title");
titlePath.addNamespace("h","http://www.w3.org/1999/xhtml");
String title = ((Element)titlePath.selectSingleNode(doc)).getText();
System.out.println("Title is "+title);

我建议外部化XPath表达式,以便在站点更改时有一定程度的保护。

这是一个示例XPath,我绝对不会用来截屏这个网站。没办法,不是我:

"//h:div[contains(@class,'question-summary')]/h:div[@class='summary']//h:h3"

答案 3 :(得分:2)

您尚未提及您正在使用的技术堆栈。如果你正在解析HTML,我会使用一个解析库:

还有一些网络服务正是您所说的 - 商业和免费。他们抓住网站并提供网络服务接口。

提供一些屏幕抓取的通用网络服务是Yahoo Pipes。 previous stackoverflow question on that

答案 4 :(得分:2)

这不是万无一失但你可能想要查看一个解析器,例如Beautiful Soup如果布局发生变化,它不会神奇地找到相同的信息,但它比编写复杂的正则表达式要容易得多。注意这是一个python模块。

答案 5 :(得分:1)

您是否考虑过使用html操作库? Ruby有一些非常好的。例如hpricot

使用好的库,您可以使用CSS选择器或xpath指定所需页面的各个部分。这些比使用正则表达式更强大。

来自hpricot wiki的示例:

 doc = Hpricot(open("qwantz.html"))
 (doc/'div img[@src^="http://www.qwantz.com/comics/"]')
   #=> Elements[...]

我相信你可以找到一个在.NET或Python等中做类似事情的库。

答案 6 :(得分:1)

不幸的是,'抓取'是最常见的解决方案,正如您所说的尝试从网站解析HTML。您可以检测到页面的结构更改并标记要修复的警报,因此更改结果不会导致bum数据。在语义网成为现实之前,这几乎是保证大型数据集的唯一方法。

或者,您可以坚持使用API​​提供的小型数据集。雅虎正在努力通过API提供可搜索的数据(参见YDN),我认为亚马逊API开辟了大量的书籍数据等。

希望有所帮助!

编辑:如果您使用的是PHP,我建议使用SimpleHTMLDOM

答案 7 :(得分:1)

尝试使用Google搜索屏幕抓取+您喜欢的语言。 我知道python的几个选项,你可能会找到相应的首选语言:

  • 美丽的汤
  • mechanize:类似于perl WWW:Mechanize。为您提供类似浏览器的浏览器以使用网页
  • lxml:python绑定到libwww
  • scrapemark:使用模板抓取页面
  • pyquery:允许您在xml / xhtml文档中进行jQuery查询
  • scrapy:用于编写蜘蛛抓取和解析网页的高级抓取和网页抓取框架

根据要抓取的网站,您可能需要使用上述一种或多种方法。

答案 8 :(得分:0)

如果您可以使用类似Tag Soup的内容,那就是一个可以开始的地方。然后,您可以将页面视为XML API,有点。

它有Java和C ++实现,可能有效!

答案 9 :(得分:0)

http://www.parselets.com的欧芹看起来很漂亮。

它允许您使用JSON定义'parslets',您可以在页面上定义要查找的内容,然后为您解析该数据。

答案 10 :(得分:0)

正如其他人所说,您可以使用构建DOM表示的HTML解析器并使用XPath / XQuery进行查询。我在这里发现了一篇非常有趣的文章:Java理论与实践:使用XQuery进行屏幕抓取 - http://www.ibm.com/developerworks/xml/library/j-jtp03225.html

答案 11 :(得分:-2)

很公平,我将按照推荐使用Tag汤方法。

作为一个后续问题 - 这些大型刮刀型网站究竟是如何做到的?我见过一个可以扫描数千个网站的求职搜索引擎(例如Indeed.com)!是成千上万的正则表达式?它几乎不可能......