热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

利用Microsoft的HTML分析器来获得Web站点的数据

拆取Web页利用Microsoft的HTML分析器来获得Web站点的数据JeremyRuleMicrosoftCorporation2000年5月程序员面临的一个共同任务就是收集W

拆取 Web 页


利用 Microsoft 的 HTML 分析器来获得 Web 站点的数据
Jeremy Rule
Microsoft Corporation
2000年5月

程序员面临的一个共同任务就是收集 Web 站点的数据,并将它分布到数据库或其他 Web 页。例如,程序员可能需要从气象站点获得天气预报图,从在线股票经纪人那里获得股票报价,以及从新闻站点获得行业新闻。然后,这些信息被放在一个 Web 页上,供 CIO、商人或销售经理使用。或者,也许程序员需要跟踪历来的气象资料,并需要每天将来自气象站的天气预报信息存入数据库。其应用不胜枚举。
过去,这些选择相当受限制。现在,通过使用象 WinInet.dll 这样的 HTTP 组件或许多其他第三方组件,您就可以获取 Web 页,并利用几百种字符串处理功能来获得网页中您所感兴趣的部分。这一技术已在应用,但很不理想。如果您致力于计算机科学(或者有足够的时间),就会为 HTML 创建一个分析器,以标记 Web 页,然后分析您需要的网页部分。不过,由于 Internet Explorer 的体系结构中已包含了可重复使用的用分析器,这些都不需要了。
Internet Explorer 不只是一个程序,更是许多可重复使用组件的集合与容器。在拆取 Web 页时,最有意思的两个组件是 shdocvw.dllmshtml.dll。第一个组件 shdocvw.dll,包含称为 WebBrowser 的 Microsoft(R) ActiveX(R) 控件,它真实地显示 Web 页。在运行 Internet Explorer 时,显示 Web 页的主窗口就是这样的控件。第二个组件 mshtml.dll,含有能分析 WebBrowser 控件中所包含文档的 HTML 分析器。
可能有这种情况,在您的应用程序内部,已经用 WebBrowser 控件来驻留 Web 页,但仍需要重新创建一个小浏览器来启动 Web 页的拆取。
文件菜单上,请单击新建工程,以创建“标准 EXE”,然后在工程菜单上单击部件,以添加 Microsoft HTML Object LibraryMicrosoft Internet Controls。(见图 1。)

图 1.
在工具箱中,可看见 WebBrowser 组件。拖动其中之一,文本框和主窗体上的命令按钮。将此文本框的 Text 属性设置为 “http://moneycentral.msn.com/”,将此命令按钮的 Caption 属性设置为“浏览(&B)”。(见图 2。)

图 2.
双击该命令按钮,然后在事件处理器中放入下列代码,导航至文本框中命名的 Web 站点:
Private Sub Command1_Click()
    WebBrowser1.Navigate Text1.Text
End Sub
保存并运行该程序。试着按浏览按钮,导航到文本框中指定的站点。您已经创建了一个基本的 Web 浏览器 — 就其本身而言没什么用,甚至没什么意义,但它却是迈向 Web 拆取技术的第一步。
回到工程中,在代码窗口中选择 WebBrowser1 对象,然后选择 DocumentComplete 的事件处理器。一旦整个 Web 页下载到此浏览器中,即触发该事件:
Private Sub WebBrowser1_DocumentComplete_
(ByVal pDisp As Object, URL As Variant)
End Sub
传递到该事件中的 URL 就是我们导航所至的位置,它在日后确定浏览器所在的页面时将更为有用。WebBrowser 控件有一个属性称为 Document(文档),可将其视为 IHTMLDocument 来处理:
Private Sub WebBrowser1_DocumentComplete(_ ByVal pDisp As Object, URL As Variant)
    Dim Doc As IHTMLDocument2
    Set Doc = WebBrowser1.Document
    //下一步:分析该文档
End Sub
较新的 IHTMLDocument2 具有 IHTMLDocument 中无法使用的特性。可对系统使用 IHTMLDocument 替代老版本的 Internet Explorer,如果您有勇气的话,甚至可以使用 IHTMLDocument3。补充说明一下,我们假设您已经导航到 Word 文档或 XML 文档,而非 HTML 文档。不要将变量 doc 声明为 IHTMLDocument2,可将其声明为 Word 的文档或 XML 的 DOMDocument
在进行下一步之前,理解 HTML 文档的结构是非常重要的。和 XML 不一样,HTML 文档的组合有一定的自由度。例如,您会遇到未关闭标记的 HTML 文档。HTML 文档确实有某种结构。结构好的 HTML 文档通常具有下列元素:
   
       header information like the
   
   
       elements like  and  and
   
请注意 HTML 的树状结构。标记包含标记又包含标记,如此等等。特别是,每一个标记元素都包含一个 0 到 n 个标记元素的集合。 标记可以包含 标记。每个 标记可以包含 标记,后者又可以包含其他标记如锚或图像等。
现在,分析整个 http://moneycentral.msn.com/,并在带 MSFT 符号的页填上第二个 标记。然后,调用此窗体上的提交:
Private Sub WebBrowser1_DocumentComplete(ByVal pDisp As Object, URL As Variant)
    Dim doc As IHTMLDocument2
    Set doc = WebBrowser1.Document
   
    If URL = _
    "http://moneycentral.msn.com/home.asp" Then
        '填充带输入标记的元素集合
        Dim Inputs As IHTMLElementCollection
        Set Inputs = doc.All.tags("INPUT")
        '选择第一个输入标记
        Dim Element As IHTMLElement
        Set Element = Inputs.Item(1, 1)
        
        '使用正确的界面
        Dim InputElement As IHTMLInputElement
        Set InputElement = Element
        InputElement.Value = Text1.Text
        
        '调用此页第一个窗体上的提交
        doc.Forms.Item(0, 0).submit
End Sub
在此您会看到,标记集合如何包含可视为其特定类型的标记。每一个标记都可用 IHTMLElement 界面表示,或用指定为该标记类型的界面表示。例如, 标记可用 IHTMLTableElement 或 IHTMLElement 表示。
标记的集合都包含下列重要的方法和属性:
长度。可将其理解为计数,或集合中项目的数量。
项目。用于选择集合中的特殊元素。“项目”有两个参数,第二个参数即命名的标记。
标记。将要过滤的元素传递给标记。标记 ("A") 将返回集合内所有锚的集合。要想有效地拆取页,就需要学会使用标记集合。
现在可能您会问,“为什么不直接转到 http://moneycentral.msn.com/scripts/webquote.dll?ipage=qd&Symbol=msft?”当然是可以的,但这个例子告诉大家如何在更复杂的情况下操纵 HTML 窗体。
如果您未做进一步的改动即运行该程序,就会注意到它将陷入无休止的循环,没完没了地下载同一个页面。程序不断地寻找要填充的窗体,并反复调用 DocumentComplete。要修正这个缺陷,应在 DocumentComplete 中置入一些逻辑,告诉分析器,只有在正确的页面上才提交窗体。
接下来,让我们放入这个逻辑,并引入实际的股票报价。另外,我们不捕获文本框中的 URL,而是捕获股票符号:
Private Sub Command1_Click()
    WebBrowser1.Navigate _
     "http://moneycentral.msn.com/home.asp"
End Sub
Private Sub WebBrowser1_DocumentComplete(ByVal pDisp As Object, URL As Variant)
    Dim doc As IHTMLDocument2
    Set doc = WebBrowser1.Document
   
    If URL = "http://moneycentral.msn.com/home.asp" Then
        '填充带输入标记的元素集合
        Dim Inputs As IHTMLElementCollection
        Set Inputs = doc.All.tags("INPUT")
        '选择第一个输入标记
        Dim Element As IHTMLElement
        Set Element = Inputs.Item(1, 1)
        
        '使用正确的界面
        Dim InputElement As IHTMLInputElement
        Set InputElement = Element
        InputElement.Value = Text1.Text
        
        '调用该页第一个窗体上的提交
        doc.Forms.Item(0, 0).submit
    ElseIf URL = _
    "http://moneycentral.msn.com/scripts/webquote.dll?ipage=qd&Symbol=" _
                 & Text1.Text Then
        Dim Tables As IHTMLElementCollection
        Set Tables = doc.All.tags("TABLE")
        '获得第 14 个表的第二个项目(基于 0)
        Dim Quote As IHTMLElement
        Set Quote = _
        Tables.Item(14, 14).All.tags("TD").Item(2, 2)
        '显示开始标记和结束标记之间的文本
        MsgBox Quote.innerText
    End If
End Sub

图 3.
到了这最后一步,自定义的浏览器已被转入有效的 Web 拆取器。重要的是,要注意有了 IHTMLElement 之后获得文本的可用选项。有 4 个属性:
innerText:开始标记和结束标记之间的文本。
innerHTML:开始标记和结束标记之间的文本和 HTML。
outerText:对象的文本。
outerHTML:对象的文本和 HTML。
还要注意从 4 个表(基于 0)的 11 个元素中检索到的最终报价字符串。如果 MoneyCentral? 决定重新调整该页怎么办?您最好的策略是根据合理的假定来查询页面。如果您知道报价几乎总是放在新闻标题的前面,那么就从新闻标题往回查询那个表。还有一种策略是,当更改页面的格式时,有一种简单的方法来更新分析器。一种方法就是将分析的职能细分为较小的组件。每个组件可以实现一个预定义的界面,接受要分析的 IHTMLDocument。与实际的 Web 页失去同步的分析组件可被替换。这样带来的好处是,多个编程人员都可以编写分析器,只需给定要实现的界面和要拆取的 Web 站点即可。
为了避免复杂,将 IHTMLDocument 从 DocumentComplete 函数传递 COM DLL,后者可以分析 IHTMLDocument 并返回想要的有效负载。这有利于程序的模块化,并易于更新与 Web 站点失去同步的分析部分。它还使多个开发者能同时处理这个项目,因为他们有一个干净的界面来编写分析器。
在把新的程序推向市场以前,还有几个实际问题要考虑。首先,很可能 MoneyCentral 和其他许多站点不愿意别人下载他们的内容,也不喜欢看广告。您可能得与摘取其内容的站点签订一份协议。
还有很重要的一点要注意,即如果您是 Web 站点的操作员,那么还有更好的办法将您的内容提供给其他系统。虽然可以让其他人来拆取您的 Web 页,但这仍很笨拙。还有一个更好的方法是,提供 XML 来表现内容。并且,随着 XML 被广泛采用,Web 站点开始提供其数据的 XML 表现形式以及 HTML 界面,也不值得大惊小怪。在这样的时刻到来之前,您也许还得拆取 Web 页。Web 页的拆取往往失之笨拙,但 Microsoft HTML 分析器可令其稍微好一些。 
 

推荐阅读
  • Node.js 教程第五讲:深入解析 EventEmitter(事件监听与发射机制)
    本文将深入探讨 Node.js 中的 EventEmitter 模块,详细介绍其在事件监听与发射机制中的应用。内容涵盖事件驱动的基本概念、如何在 Node.js 中注册和触发自定义事件,以及 EventEmitter 的核心 API 和使用方法。通过本教程,读者将能够全面理解并熟练运用 EventEmitter 进行高效的事件处理。 ... [详细]
  • 深入解析 Django 中用户模型的自定义方法与技巧 ... [详细]
  • 本文详细探讨了Java集合框架的使用方法及其性能特点。首先,通过关系图展示了集合接口之间的层次结构,如`Collection`接口作为对象集合的基础,其下分为`List`、`Set`和`Queue`等子接口。其中,`List`接口支持按插入顺序保存元素且允许重复,而`Set`接口则确保元素唯一性。此外,文章还深入分析了不同集合类在实际应用中的性能表现,为开发者选择合适的集合类型提供了参考依据。 ... [详细]
  • 进程(Process)是指计算机中程序对特定数据集的一次运行活动,是系统资源分配与调度的核心单元,构成了操作系统架构的基础。在早期以进程为中心的计算机体系结构中,进程被视为程序的执行实例,其状态和控制信息通过任务描述符(task_struct)进行管理和维护。本文将深入探讨进程的概念及其关键数据结构task_struct,解析其在操作系统中的作用和实现机制。 ... [详细]
  • 如何在Spark数据排序过程中有效避免内存溢出(OOM)问题
    本文深入探讨了在使用Spark进行数据排序时如何有效预防内存溢出(OOM)问题。通过具体的代码示例,详细阐述了优化策略和技术手段,为读者在实际工作中遇到类似问题提供了宝贵的参考和指导。 ... [详细]
  • 我正在使用 Ruby on Rails 构建个人网站。总体而言,RoR 是一个非常出色的工具,它提供了丰富的功能和灵活性,使得创建自定义页面变得既高效又便捷。通过利用其强大的框架和模块化设计,我可以轻松实现复杂的功能,同时保持代码的整洁和可维护性。此外,Rails 的社区支持也非常强大,为开发过程中遇到的问题提供了丰富的资源和解决方案。 ... [详细]
  • PHP中元素的计量单位是什么? ... [详细]
  • 智能网联汽车自动驾驶功能测试场地的方法与标准要求
    智能网联汽车自动驾驶功能测试场地的方法与标准要求 ... [详细]
  • 从零起步:使用IntelliJ IDEA搭建Spring Boot应用的详细指南
    从零起步:使用IntelliJ IDEA搭建Spring Boot应用的详细指南 ... [详细]
  • 本文深入解析了 Apache 配置文件 `httpd.conf` 和 `.htaccess` 的优化方法,探讨了如何通过合理配置提升服务器性能和安全性。文章详细介绍了这两个文件的关键参数及其作用,并提供了实际应用中的最佳实践,帮助读者更好地理解和运用 Apache 配置。 ... [详细]
  • 本文作为“实现简易版Spring系列”的第五篇,继前文深入探讨了Spring框架的核心技术之一——控制反转(IoC)之后,将重点转向另一个关键技术——面向切面编程(AOP)。对于使用Spring框架进行开发的开发者来说,AOP是一个不可或缺的概念。了解AOP的背景及其基本原理,对于掌握这一技术至关重要。本文将通过具体示例,详细解析AOP的实现机制,帮助读者更好地理解和应用这一技术。 ... [详细]
  • 结语 | 《探索二进制世界:软件安全与逆向分析》读书笔记:深入理解二进制代码的逆向工程方法
    结语 | 《探索二进制世界:软件安全与逆向分析》读书笔记:深入理解二进制代码的逆向工程方法 ... [详细]
  • 本题库精选了Java核心知识点的练习题,旨在帮助学习者巩固和检验对Java理论基础的掌握。其中,选择题部分涵盖了访问控制权限等关键概念,例如,Java语言中仅允许子类或同一包内的类访问的访问权限为protected。此外,题库还包括其他重要知识点,如异常处理、多线程、集合框架等,全面覆盖Java编程的核心内容。 ... [详细]
  • Ceph API微服务实现RBD块设备的高效创建与安全删除
    本文旨在实现Ceph块存储中RBD块设备的高效创建与安全删除功能。开发环境为CentOS 7,使用 IntelliJ IDEA 进行开发。首先介绍了 librbd 的基本概念及其在 Ceph 中的作用,随后详细描述了项目 Gradle 配置的优化过程,确保了开发环境的稳定性和兼容性。通过这一系列步骤,我们成功实现了 RBD 块设备的快速创建与安全删除,提升了系统的整体性能和可靠性。 ... [详细]
  • 在稀疏直接法视觉里程计中,通过优化特征点并采用基于光度误差最小化的灰度图像线性插值技术,提高了定位精度。该方法通过对空间点的非齐次和齐次表示进行处理,利用RGB-D传感器获取的3D坐标信息,在两帧图像之间实现精确匹配,有效减少了光度误差,提升了系统的鲁棒性和稳定性。 ... [详细]
author-avatar
mobiledu2502894753
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有