【问题标题】:Locating specific string and capturing data following it定位特定字符串并捕获其后的数据
【发布时间】:2009-11-10 05:17:20
【问题描述】:

我很久以前建立了一个站点,现在我想将数据放入数据库中,而无需复制和粘贴它已经增长到的 400 多个页面,以便我可以驱动站点数据库。

我的网站有这样的元标记(每个页面不同):

<meta name="clan_name" content="Dark Mage" />

所以我正在做的是使用 cURL 将整个 HTML 页面作为字符串放在一个变量中。我也可以用 fopen 等来做...,但我认为这并不重要。

我需要在字符串中移动以找到“Dark Mage”并将其存储在一个变量中(这样我就可以放入 sql 中)

关于找到黑暗法师存储在变量中的最佳方法的任何想法?我试图使用 substr,然后只是从 clan_name 中的 e 中减去字符数,但那是失败的。

【问题讨论】:

    标签: php html parsing


    【解决方案1】:

    只需使用 PHP DOM 函数解析页面,特别是 loadHTML()。然后,您可以遍历树或使用 xpath 来查找您要查找的节点。

    <?
    $doc = new DomDocument;
    $doc->loadHTML($html);
    $meta = $doc->getElementsByTagName('meta');
    foreach ($meta as $data) {
      $name = $meta->getAttribute('name');
      if ($name == 'clan_name') {
        $content = $meta->getAttribute('content');
        // TODO handle content for clan_name
      }
    } 
    ?>
    

    编辑 如果您想在将 HTML 字符串加载到内存之前删除某些标签(例如 &lt;script&gt;),请尝试使用 strip_tags() 函数。像这样的东西只会保留元标记:

    <?
      $html = strip_tags($html, '<meta>');
    ?>
    

    【讨论】:

    • 这是否要求 HTML 格式正确?
    • 不!与 loadXML() 相比,这就是这个函数的美妙之处。查看文档中的示例(您会发现它的格式不正确)。
    • 不错;这使得这是一个比我更好的答案。 +1
    • 解决问题的方法总是不止一种...如果是受限的服务器安装,可能是 DOM 功能被禁用了。那么正则表达式方法可能是唯一的选择。
    • 第三个参数 (true) 在 PHP 5.3 中被添加。您可能运行的是旧版本。
    【解决方案2】:

    在 PHP 的 preg_match() 中使用如下的正则表达式

    /<meta name="clan_name" content="([^"]+)"/
    

    如果您不熟悉正则表达式,请继续阅读。

    开头和结尾的正斜杠分隔正则表达式。分隔符内的内容非常简单,除了结尾。

    方括号分隔一个字符类,字符类开头的插入符号是一个否定运算符;那么,把这个字符类放在一起:

    [^"]
    

    表示“匹配任何不是双引号的字符”。

    + 是一个量词,它要求前一个项目至少出现一次,并且匹配与第一个相邻的前一个项目的数量。所以这个:

    [^"]+
    

    表示“匹配一个或多个不是双引号的字符”。

    最后,括号使正则表达式引擎将它们之间的任何内容存储在一个子模式中。所以这个:

    ([^"]+)
    

    表示“匹配一个或多个不是双引号的字符并将它们存储为匹配的子模式。

    在 PHP 中,preg_match() 将匹配项存储在您通过引用传递的数组中。完整模式存储在数组的第一个元素中,第一个子模式存储在第二个元素中,如果还有其他子模式,则以此类推。

    所以,假设你的 HTML 页面在变量“$page”中,下面的代码:

    $matches = array();
    $found = preg_match('/<meta name="clan_name" content="([^"]+)"/', $page, $matches);
    
    if ($found) {
        $clan_name = $matches[1];
    }
    

    应该得到你想要的。

    【讨论】:

    • 您还可以捕获“名称”并让if 进行检查,而不是依赖匹配计数。
    • 你能举一个超级快速的例子吗?在这种情况下,我从来没有真正喜欢检查 count($matches) ;看起来并不那么健壮。
    • 我正在考虑使用'/&lt;meta name="([^"]+)" content="([^"]+)"/' 作为正则表达式并查看(found &amp;&amp; $matches[1] == 'clan_name') 或其他内容。
    • 知道了,谢谢。现在我想了想,我的“count($matches)”是多余的,因为如果子模式不匹配,$found 将是 FALSE。编辑。
    【解决方案3】:

    使用preg_match。一个可能的正则表达式模式是/clan_name.+content="([^"]+)"/

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多