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

PHP挖掘XML和HTML数据

Wikipedia对“数据挖掘”的定义是“数据挖掘是采用统计学方法和人工智能方法,结合数据库管理,从大型数据集提取模式的过程”。这是一个非常深

数据挖掘及其重要性

常用缩略词

  • API: 应用程序编程接口
  • CDATA: 字符数据
  • DOM: 文档对象模式
  • FTP: 文件传输协议
  • HTML: 超文本标记语言
  • HTTP: 超文本传输协议
  • REST: 具象状态传输
  • URL: 统一资源定位符
  • W3C: 万维网联盟
  • XML: 可扩展标记语言

Wikipedia 对 “数据挖掘” 的定义是 “数据挖掘是采用统计学方法和人工智能方法,结合数据库管理,从大型数据集提取模式的过程”。这是一个非常深入的定义,可能超出了大多数人的典型用例。很少有人使用人工智能;通常,数据挖掘只是搜索并汇集大型数据集,以查找有用的信息。

Internet 在飞速发展,并提供了海量信息,因此,能够收集大量数据并使数据变得有意义非常重要。收集个人无法读完的大型数据集并将它们提炼为有用的数据是一个很重要的目标。这种类型的数据挖掘是本文的焦点,本文将专门介绍如何收集和解析这种数据。

回页首

数据挖掘的实际应用

数据挖掘有很多实际应用。您可能假设这样一个场景:您想搜索一个网站,查找其中提供的信息(比如电影或音乐会的出席记录)。您可能需要检索更严肃的信息,比如投票者记录,并获得有用数据。或者,更常见的情况是,您可能需要检查社交网络数据,试图解析该数据,了解某种趋势,比如您的公司被提及的频率,以及这种提及是正面的还是负面的。

回页首

挖掘网站之前的注意事项

在继续介绍后面的内容之前,有一点需要说明:我们假定您将从另一个网站提取数据。如果您已经拥有要处理的数据,则又是完全不同的一种情况。当您从一个网站提取数据时,您需要确保遵守服务条款, 无论您是在做 Web 擦除(稍后将详细介绍)还是在使用一个 API。如果您在做擦除,还需要注意遵守该站点的 robots.txt 文件的规定,该文件描述了允许访问网站脚本的哪些部分。最后,确保不会妨碍站点的带宽。您编写的脚本不能按照脚本能够运行的速度随意访问站点的数据。否则,这不仅可能会导致托管问题,还有可能面临因为脚本太具 “侵略性” 而遭到被禁止或阻塞的风险。

回页首

理解 XML 数据结构

不管您采取何种方法提取数据,都有可能接收到 XML(或 HTML)格式的数据。当 XML 支持共享数据后,XML 就成为 Internet 的标准语言。在考虑提取数据的方法之前,重要的是要先研究 XML 结构和如何处理 XML 数据。

XML 文档的基本结构非常直观,特别是在您以前使用过 HTML 的情况下。XML 文档中的所有数据都用两种方法中的一种方法进行存储。存储数据的主要方法是将数据存储在嵌套标记中。下面举一个最简单的例子,假设您拥有一个地址,则该数据可以按如下方法存储在文档中:

1234 Main Street, Baltimore, MD


您可以嵌套这些 XML 数据点,以创建多个地址的列表。您可以将所有这些地址放到另一个标记中,在本例中这个标记为locations(请参见 清单 1)。


清单 1. XML 中的多个地址

				

    
1234 Main Street, Baltimore, MD
567 1st Street, San Jose, CA
901 Washington Ave, Chicago, IL


要进一步扩展这种方法,可以将这些地址分解为各个组成部分:街道、城市和州,这使得数据处理变得更简单。这样,生成的 XML 文件就更典型,如 清单 2 所示。


清单 2. XML 中完全分解的地址

				

    
1234 Main Street Baltimore MD
567 1st Street San Jose CA
901 Washington Ave Chicago IL


前面提到过,存储 XML 数据的方法有两种,我们刚才看到了其中一种。另一种方法是通过属性存储数据。可以为每个标记分配若干个属性。尽管这种方法不那么常用,但这可能是一种非常有用的工具。有时,它会提供额外的信息,比如一个唯一 ID 或一个事件日期。更常见的情况是添加元数据; 在您的地址示例中,可以使用一个 type 属性来指出该地址是家庭地址还是工作地址,如 清单 3 所示。


清单 3. 添加到 XML 的标记

				

    
1234 Main Street Baltimore MD
567 1st Street San Jose CA
901 Washington Ave Chicago IL


注意,XML 文档总是拥有一个父级根标记/节点,所有其他标记/节点都是该根标记/节点的子级标记/节点。XML 文档的开头部分还可以包含其他声明和定义,以及其他复杂内容(比如 CDATA 块)。强烈建议您参阅 参考资料 部分,以便进一步了解 XML。

回页首

解析 PHP 中的 XML 数据

您已经了解了 XML 的外观和结构,现在我们看看如何解析并以编程方式访问 PHP 中的 XML 数据。有几个针对 PHP 创建的库允许进行 XML 解析,每个库都有其优缺点。这些库包括 DOM、XMLReader/Writer、XML Parser、SimpleXML 等。对于本文的目的,我们主要关注的是 SimpleXML,这是因为它是一个最常用的库,同时也是我的最爱的库之一。

SimpleXML,顾名思义,旨在提供一个非常简单的接口来访问 XML。它可以将 XML 文档转换为内部 PHP 对象格式。访问数据点变得和访问对象变量一样简单。要使用 SimpleXML 解析一个 XML 文档,只需使用 simplexml_load_file() 函数(请参见 清单 4)。


清单 4. 使用 SimpleXML 解析文档

				


就这么简单!但是请注意,多亏了 PHP 的文件流集成,才可以在这里插入一个文件名或 URL,文件流集成会自动取回它。如果 XML 已经载入内存,还可以使用 simplexml_load_string()。如果您在 清单 3 中的 XML 上运行这个代码并使用 print_r() 来查看查看数据的大致结构,您将得到如 清单 5 所示的输出。


清单 5. 已解析的 XML 的输出

				
SimpleXMLElement Object 
(
     [address] => Array
         (
             [0] => SimpleXMLElement Object
                 (
                     [@attributes] => Array
                         (
                             [type] => home
                         )
                     [street] => 1234 Main Street
                     [city] => Baltimore
                     [state] => MD
                 )
              [1] => SimpleXMLElement Object
                 (
                     [@attributes] => Array
                         (
                             [type] => work
                         )
                     [street] => 567 1st Street
                     [city] => San Jose
                     [state] => CA
                 )
              [2] => SimpleXMLElement Object
                 (
                     [@attributes] => Array
                         (
                             [type] => work
                         ) 
                     [street] => 901 Washington Ave
                     [city] => Chicago
                     [state] => IL
                 )
          )
)


然后,您就可以使用标准的 PHP 对象访问和方法访问数据。例如,要回显某人居住过的每个州,可以通过迭代地址来实现(请参见清单 6)。


清单 6. 迭代地址

				
address as $address) {
    echo $address->state, "
\n"; } ?>


访问属性略有不同。与引用对象属性不同的是,您可以将属性作为数组值访问。您可以更改上面的代码样例来显示 type 属性,可以使用 清单 7 中所示代码实现上述操作。


清单 7. 添加属性

				
address as $address) {
    echo $address->state, ': ', $address['type'], "
\n"; } ?>


尽管上述所有示例都涉及迭代,但您也可以直接访问数据并使用您需要的特定信息片段,比如通过下面的代码提取第二个地址的街道地址:$xml->address[1]->street。

现在,您应该有一些基本工具来开始处理 XML 数据。有关的详细信息,强烈建议您参阅 参考资料 中列出的 SimpleXML 文档和其他链接。

回页首

PHP 中的数据挖掘:可能的方法

如前所述,可以用多种方法访问数据,其中两种主要方法是 Web 擦除和 API 使用。

Web 擦除

Web 擦除(scraping)是以编程方式下载所有 Web 页面并从中提取数据的操作。有很多图书专门讨论了这个主题(请参阅 参考资料)。我只简单列举进行 Web 擦除所需的一些工具。首先,PHP 使得将一个 Web 页读入为一个字符串变得非常简单。有许多方法可以完成这个任务,包括通过某个 URL 使用 file_get_contents(),但在这里,您希望能以一种有意义的方式来解析 HTML。

因为 HTML 实质上是一种基于 XML 的语言,所以将 HTML 转换为一种 SimpleXML 结构很有用。但是不能只使用simplexml_load_file() 加载 HTML 页面,因为即使是有效的 HTML,它仍然不是 XML。一种好办法是使用 DOM 扩展,将 HTML 页面作为 DOM 文档载入,然后将其转换为 SimpleXML,如 清单 8 所示。


清单 8. 使用 DOM 方法来获取 Web 页面的 SimpleXML 版本

				
loadHTMLFile('http://example.com/');
$xml = simplexml_import_dom($dom);
?>


现在,您可以像对其他 XML 文档一样遍历 HTML 页面。因此,您现在可以使用 $xml->head->title 来访问页面标题,或者使用 $xml->body->div[0]->div[0]->div[0]->h4[0] 这样的引用来深入页面。

但是,正如您从上一个示例中可以预料到的那样,试图从一个 HTML 页面中查找数据有时可能非常不便,这是因为 HTML 页面通常不像 XML 文件那样有良好的结构。上面那行代码查找三个嵌套的 div 中的第一个 h4;在每种情况下,它都会查找每个父 div 中的第一个 div。

幸运的是,如果您只想查找页面上的第一个 h4,或者其他 “直接数据”,那么 XPath 是一种更简单的实现方法。XPath 是一个非常强大的工具,可以将它作为整个文章系列的主题(请参阅 参考资料 中列示的部分文章)。简言之,可以使用 '/' 来描述层级关系;因此,可以将前面的引用重写为下面的 XPath 搜索(请参见 清单 9)。


清单 9. 直接使用 XPath

				
xpath('/html/body/div/div/div/h4');
?>


或者,您可以只使用 '//' 选项和 XPath,这将搜索所有文档,查找您要查找的标记。因此,您可以找到所有 h4,生成一个数组,然后使用下面的 XPath 访问第一个 h4:
'//h4'

遍历 HTML 分层结构

讨论上述转换和 XPath 的主要原因是,进行 Web 擦除的常见必要任务之一就是自动查找 Web 页面上的其他链接并追索它们,这允许您 “遍历” 网站,找到尽量多的信息。

如果使用 XPath,这个任务将非常麻烦。清单 10 提供了一个由所有带有 “href” 属性的 链接组成的数组,并允许您处理它们。


清单 10. 结合使用多种技术查找页面上的所有链接

				
loadHTMLFile('http://example.com/');
$xml = simplexml_import_dom($dom);
$links = $xml->xpath('//a[@href]');
foreach ($links as $l) {
    echo $l['href'], "
\n"; } ?>


现在,上面的代码找到了所有 链接,但如果您打开您发现的每个可能链接,您就开始快速 “爬行” 整个 Web。因此,最好增强您的代码,确保只访问两类链接:一类是有效的 HTML 链接(不是 FTP 或 Javascript);一类是只返回(通过完整或相对域链接)同一个网站的链接。

一种更简单的方法是使用 PHP 的内置 parse_url() 函数在这些链接上进行迭代,该函数为您处理大量资格审查,如 清单 11 所示。


清单 11. 一个更健壮的站点遍历程序

				
loadHTMLFile("http://{$host}/");
$xml = simplexml_import_dom($dom);
$links = $xml->xpath('//a[@href]');
foreach ($links as $l) {
    $p = parse_url($l['href']);
    if (empty($p['scheme']) || in_array($p['scheme'], array('http', 'https'))) {
        if (empty($p['host']) || ($host == $p['host'])) {
            echo $l['href'], "
\n"; // Handle URL iteration here } } } ?>


关于 HTML 解析的最后一点说明是,对于所有 XML 类语言的一个统一接口,您复习了如何只使用 DOM 扩展将 HTML 转换回 SimpleXML。注意,DOM 库本身非常强大,可以直接使用。如果您非常熟悉 Javascript 和使用 getElementsByTagName 之类的工具来遍历 DOM 文档树,那么您完全可以只使用 DOM 库,不使用 SimpleXML。

您目前应该已经拥有了从 Web 页面上擦除数据所需的工具。一旦您熟悉了本文前面详细介绍的技术,就可以从 Web 页面上读取任何信息,而不仅限于可以关注的链接。我们希望您不必执行这个任务,因为已经存在 API 或其他数据源。

使用 XML API 和数据

此时,您已经掌握了一些基本技能,能够访问和使用 Internet 上的主要 XML 数据 API。它们通常基于 REST,因此只需一个简单的 HTTP 访问就可以检索数据,并使用前面介绍的结束来解析数据。

每个 API 在这方面的表现都是不同的。我们无法一一介绍如何访问每个 API,因此,我们只简要介绍一些基本的 XML API 示例。一个最常见且已经采用 XML 格式的数据源就是 RSS feed。RSS 代表 Really Simple Syndication,通常是一种标准化的格式,用于共享频繁更新的数据,比如博客帖子、新闻标题或播客。要详细了解 RSS 格式,请参见 参考资料。注意,RSS 是一个 XML 文件,有一个名为 父标记,其中有若干 标记,每个标记都提供一组数据点。

下面举例说明。假设我们使用 SimpleXML 来读取纽约时报标题的 RSS feed(参见 参考资料 获取到该 RSS feed 的链接)并格式化一列标题,那些标题都将链接到相应的正文(请参见 清单 12)。


清单 12. 读取纽约时报的 RSS feed

				


图 1 显示了来自纽约时报摘要的输出。


来自纽约时报摘要的输出
来自纽约时报摘要的输出的屏幕截图,列示 13 个标题

现在,我们来探索一个功能更全的基于 REST 的 API。Flickr API 是一个好的起点,因为它提供大量数据,但不需要身份验证。许多 API 都需要身份验证(使用 Oauth 或其他机制),以代表一个 Web 用户进行操作。这个步骤可应用于整个 API,或者只应用于部分 API。参阅每个 API 文档,了解如何进行身份验证。

要了解如何对一个未经身份验证的请求使用 Flickr API,您可以使用它的搜索 API。作为一个示例,我们搜索 Flickr 的所有公共十字弓照片。尽管不必进行身份验证,但与许多 API 一样,仍然需要生成一个 API 密匙,以便在访问数据时使用。请直接参阅 Flickr 的 API 文档,了解如何完成这个任务。拥有一个 API 密匙后,就可以使用 Flickr API 的搜索功能进行探索,如 清单 13 所示。


清单 13. 使用 Flickr API 搜索 “crossbow”

				
 'flickr.photos.search',
    'api_key' => $key,
    'text' => 'crossbow', // Our search term
    'media' => 'photos',
    'per_page' => 20 // We only want 20 results
);

// Now make the request to Flickr:
$xml = simplexml_load_file($apiurl . http_build_query($params));

// From this, iterate over the list of photos & request more info:
foreach ($xml->photos->photo as $photo) {
    // Build a new request with this photo's ID
    $params = array(
        'method' => 'flickr.photos.getInfo',
        'api_key' => $key,
        'photo_id' => (string)$photo['id']
    );
    $info = simplexml_load_file($apiurl . http_build_query($params));
    
    // Now $info holds a vast amount of data about the image including
    //  owner, GPS, dates, description, tags, etc ... all to be used.

    // Let's also request "sizes" to get all of the image URLs:
    $params = array(
        'method' => 'flickr.photos.getSizes',
        'api_key' => $key,
        'photo_id' => (string)$photo['id']
    );
    $sizes = simplexml_load_file($apiurl . http_build_query($params));
    $small = $sizes->xpath("//size[@label='Small']");
    
    // For now, just going to create a simple display of the image,
    //  linked back to Flickr, with title, GPS info, and more shown:
    echo <<
  
    
  
  
  • Title: {$info->photo->title}
  • User: {$info->photo->owner['realname']}
  • Date Taken: {$info->photo->dates['taken']}
  • Location: {$info->photo->location->locality}, {$info->photo->location->county}, {$info->photo->location->region}, {$info->photo->location->country}
EOHTML; } ?>


图 2 显示了这个 Flickr 程序的输出。您的十字弓搜索结果包括一些照片和每张照片的相关信息(标题、用户、位置和摄影日期)。


图 2. 来自清单 13 的 Flickr 程序的示例输出
来自清单 13 的 Flickr 程序的示例输出的屏幕截图

您已经看到,这样的 API 是多么强大,以及如何在同一个 API 中结合各种调用来获取所需的数据。通过这些基本技术,您可以挖掘任何网站和信息源的数据。

考虑一下,如何通过一个 API 或 Web 擦除获取对数据的编程访问。然后使用所展示的方法来访问并迭代所有目标数据。

回页首

存储和报告提取的数据

最后,存储和报告数据在很多方面都是最容易的部分,可能也是最有意思的部分。当您决定如何根据您的实际情况处理这个方面时,您可以任意发挥您的想象力。

通常,获得您收集的所有数据并将它们存储到某个数据库中。然后,设计您的数据结构,使其与您计划将来访问数据的方式相符。此时,尽量多存储一些信息,将来有可能会用到它们。尽管总是可以删除数据,但一旦数据太多,检索额外的信息可能是一个痛苦的过程。但最好还是在刚开始就多存储一些数据,毕竟,您永远也不会知道哪些数据可能会派上用场。

将数据存储到数据库或类似的数据存储器中之后,就可以创建报告了。创建报告可能很简单,只需针对数据库运行几个基本的 SQL 查询,查看某个数据出现的次数即可;或者,报告创建也可能是非常复杂的 Web 用户接口,旨在允许用户深入数据并发现数据之间的关系。

当您辛辛苦苦将所有数据分门别类后,便可以想象一些显示数据的创新方法。

回页首

结束语

通过本文,您了解了 XML 文档的基本结构,以及使用 SimpleXML 来解析 PHP 中的 XML 数据的一种简单方法。您还增加了以类似方式处理 HTML 的能力,并初步了解了如何遍历一个网站,获取没有以 XML 格式提供的数据。通过这些工具,结合本文提供的一些示例,现在您已经拥有了良好的知识基础,可以开始对某个网站进行数据挖掘了。关于这个主题还有许多知识需要学习,无法在一篇文章中对它们进行一一介绍。关于增加您的数据挖掘知识的其他方法,请参阅 参考资料。



推荐阅读
  • 当前,众多初创企业对全栈工程师的需求日益增长,但市场中却存在大量所谓的“伪全栈工程师”,尤其是那些仅掌握了Node.js技能的前端开发人员。本文旨在深入探讨全栈工程师在现代技术生态中的真实角色与价值,澄清对这一角色的误解,并强调真正的全栈工程师应具备全面的技术栈和综合解决问题的能力。 ... [详细]
  • SQLmap自动化注入工具命令详解(第28-29天 实战演练)
    SQL注入工具如SQLMap等在网络安全测试中广泛应用。SQLMap是一款开源的自动化SQL注入工具,支持12种不同的数据库,具体支持的数据库类型可在其插件目录中查看。作为当前最强大的注入工具之一,SQLMap在实际应用中具有极高的效率和准确性。 ... [详细]
  • 为了在Fragment中直接调用Activity的方法,可以通过定义一个接口并让Activity实现该接口来实现。具体步骤包括:首先在Fragment中声明一个接口,并在Activity中实现该接口。接着,在Fragment中通过类型转换检查Activity是否实现了该接口,如果实现了则调用相应的方法。这种方法不仅提高了代码的解耦性,还增强了模块间的通信效率。此外,还可以通过ViewModel或LiveData等现代Android架构组件进一步优化这一过程,以实现更加高效和可靠的通信机制。 ... [详细]
  • 通过自定义 `TextView`,实现了在用户点击或焦点变化时动态调整字体颜色的效果。该方法利用了 `ColorStateList` 和 `Selector` 资源文件,确保了界面交互的流畅性和视觉效果的提升。具体实现中,通过重写 `onTouchEvent` 和 `onFocusChanged` 方法,精确控制了颜色变化的时机和状态。此外,还对性能进行了优化,确保在高频率操作下依然保持高效响应。 ... [详细]
  • 解决基于XML配置的MyBatis在Spring整合中出现“无效绑定语句(未找到):com.music.dao.MusicDao.findAll”问题的方法
    在将Spring与MyBatis进行整合时,作者遇到了“无效绑定语句(未找到):com.music.dao.MusicDao.findAll”的问题。该问题主要出现在使用XML文件配置DAO层的情况下,而注解方式配置则未出现类似问题。作者详细分析了两个配置文件之间的差异,并最终找到了解决方案。本文将详细介绍问题的原因及解决方法,帮助读者避免类似问题的发生。 ... [详细]
  • 本文探讨了如何在 Google Sheets 中通过自定义函数实现 AJAX 调用。具体介绍了编写脚本的方法,以便在电子表格中发起 AJAX 请求,从而实现数据的动态获取与更新。这种方法不仅简化了数据处理流程,还提高了工作效率。 ... [详细]
  • 本文深入解析了 Apache 配置文件 `httpd.conf` 和 `.htaccess` 的优化方法,探讨了如何通过合理配置提升服务器性能和安全性。文章详细介绍了这两个文件的关键参数及其作用,并提供了实际应用中的最佳实践,帮助读者更好地理解和运用 Apache 配置。 ... [详细]
  • 作为140字符的开创者,Twitter看似简单却异常复杂。其简洁之处在于仅用140个字符就能实现信息的高效传播,甚至在多次全球性事件中超越传统媒体的速度。然而,为了支持2亿用户的高效使用,其背后的技术架构和系统设计则极为复杂,涉及高并发处理、数据存储和实时传输等多个技术挑战。 ... [详细]
  • 本文探讨了在Android应用中实现动态滚动文本显示控件的优化方法。通过详细分析焦点管理机制,特别是通过设置返回值为`true`来确保焦点不会被其他控件抢占,从而提升滚动文本的流畅性和用户体验。具体实现中,对`MarqueeText.java`进行了代码层面的优化,增强了控件的稳定性和兼容性。 ... [详细]
  • 深入解析Gradle中的Project核心组件
    在Gradle构建系统中,`Project` 是一个核心组件,扮演着至关重要的角色。通过使用 `./gradlew projects` 命令,可以清晰地列出当前项目结构中包含的所有子项目,这有助于开发者更好地理解和管理复杂的多模块项目。此外,`Project` 对象还提供了丰富的配置选项和生命周期管理功能,使得构建过程更加灵活高效。 ... [详细]
  • 如何在Java中高效构建WebService
    本文介绍了如何利用XFire框架在Java中高效构建WebService。XFire是一个轻量级、高性能的Java SOAP框架,能够简化WebService的开发流程。通过结合MyEclipse集成开发环境,开发者可以更便捷地进行项目配置和代码编写,从而提高开发效率。此外,文章还详细探讨了XFire的关键特性和最佳实践,为读者提供了实用的参考。 ... [详细]
  • 在Spring框架中,基于Schema的异常通知与环绕通知的实现方法具有重要的实践价值。首先,对于异常通知,需要创建一个实现ThrowsAdvice接口的通知类。尽管ThrowsAdvice接口本身不包含任何方法,但开发者需自定义方法来处理异常情况。此外,环绕通知则通过实现MethodInterceptor接口来实现,允许在方法调用前后执行特定逻辑,从而增强功能或进行必要的控制。这两种通知机制的结合使用,能够有效提升应用程序的健壮性和灵活性。 ... [详细]
  • 如何利用Apache与Nginx高效实现动静态内容分离
    如何利用Apache与Nginx高效实现动静态内容分离 ... [详细]
  • 在探讨 AS3 中的数据深度复制技术时,本文详细介绍了实现数据深度克隆的有效方法。通过对比多种方案,最终确定了一种高效且可靠的实现方式,所有代码均来源于公开资源,确保了方法的实用性和可操作性。 ... [详细]
  • 本文旨在构建一个JavaScript函数,用于对用户输入的电子邮件地址和密码进行有效性验证。该函数将确保输入符合标准格式,并检查密码强度,以提升用户账户的安全性。通过集成正则表达式和条件判断语句,该方法能够有效防止常见的输入错误,同时提供即时反馈,改善用户体验。 ... [详细]
author-avatar
寻找4s_666
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有