【问题标题】:using preg_match_all to get name of image使用 preg_match_all 获取图像名称
【发布时间】:2011-09-04 00:11:26
【问题描述】:

在使用 curl 后,我从外部页面获得了所有类似这样的源代码(我感兴趣的部分)

   (page...)<td valign='top' class='rdBot' align='center'><img src="/images/buy_tickets.gif" border="0" alt="T"></td> (page...)

所以我正在使用 preg_match_all,我只想获得“buy_tickets.gif”

$pattern_before = "<td valign='top' class='rdBot' align='center'>";
$pattern_after = "</td>";
$pattern = '#'.$pattern_before.'(.*?)'.$pattern_after.'#si';

preg_match_all($pattern, $buffer, $matches, PREG_SET_ORDER);

到目前为止一切都很好......但问题是有时外部页面发生变化并且我正在寻找它的图像在链接内

(page...)<td valign='top' class='rdBot' align='center'><a href="blaa" title="ble"><img src="/images/buy_tickets.gif" border="0" alt="T"></a></td> (page...)

我不知道如何让我的代码始终工作(不仅仅是当图像没有链接时)

希望你理解

提前致谢

【问题讨论】:

    标签: php xml regex dom


    【解决方案1】:

    Don't use regex to parse HTML,使用 PHP 的 DOM Extension。试试这个:

    $doc = new DOMDocument;
    
    @$doc->loadHTMLFile( 'http://ventas.entradasmonumental.com/eventperformances.asp?evt=18' ); // Using the @ operator to hide parse errors
    
    $xpath  = new DOMXPath( $doc );
    
    $img = $xpath->query( '//td[@class="BrdBot"][@align="center"][1]//img[1]')->item( 0 ); // Xpath->query returns a 'DOMNodeList', get the first item which is a 'DOMElement' (or null)
    
    $imgSrc = $img->getAttribute( 'src' );
    
    $imgSrcInfo = pathInfo( $imgSrc );
    
    $imgFilename = $imgSrcInfo['basename']; // All you need
    

    【讨论】:

    • @SalmanPK -- 在推荐 w3Schools 之前,我建议阅读 w3fools.com。简而言之,很多人认为它们是一种劣质资源。通过链接到 PHP 手册,您可能会做得更好。
    • @Supdley 感谢您指出 :),这是一个关于 XPath 语法的好链接:msdn.microsoft.com/en-us/library/ms256086.aspx
    • @SalmanPK 我已经尝试过了,但我无法让它工作。图像它位于具有该类“rdbot”的 td 内的链接内,但它不是该类的唯一 td
    • @Zuker,我已经更新了代码。如果有任何问题,请检查并让我知道 :) 如果您可以提供您要废弃的页面的 URL,这将有所帮助。
    • @salmanPK 这是页面ventas.entradasmonumental.com/eventperformances.asp?evt=18。我想捕捉这张图片“ventas.entradasmonumental.com/images/buy_tickets.gif”。使用您的代码,我收到警告:DOMDocument::loadHTMLFile(): htmlParseStartTag: misplaced tag in ... 非常感谢!
    【解决方案2】:

    你会得到很多建议,不要使用正则表达式从 HTML 代码中提取内容。

    有时在这类事情上使用正则表达式是合适的,我并不总是同意这里(和其他地方)关于这个主题的有些僵化的建议。但是在这种情况下,我会说正则表达式不适合您。

    使用正则表达式在 HTML 代码中搜索内容的问题正是您遇到的问题——HTML 代码可能千差万别,使得任何正则表达式几乎不可能正确。

    为您的情况编写一个正则表达式几乎是可能的,但它将是一个非常复杂的正则表达式,而且非常脆弱——即如果 HTML 代码稍微超出您期望的参数,则容易失败。

    将此与推荐的解决方案进行对比,即使用 DOM 解析器。将 HTML 代码加载到 DOM 解析器中,您将立即拥有一个可以查询单个元素和属性的对象结构。

    您提供的详细信息使得使用这个而不是正则表达式几乎是一件容易的事。

    PHP 有一个内置的 DOM 解析器,可以如下调用:

    $mydom = new DOMDocument;
    $mydom->loadHTMLFile("http://....");
    

    然后您可以使用 XPath 在 DOM 中搜索您想要的特定元素或属性:

    $myxpath = new DOMXPath($mydom);
    $myattr = $xpath->query("//td[@class="rdbot"]//img[0]@src");
    

    希望对您有所帮助。

    【讨论】:

    • 谢谢 Spudley 我从来没有使用过这个,我正在尝试并且我得到“警告:DOMDocument::loadHTMLFile(): htmlParseStartTag: misplaced tag in ...”在 td 内链接该类“rdbot”,但它不是该类的唯一 td
    【解决方案3】:
    function GetFilename($file) {
        $filename = substr($file, strrpos($file,'/')+1,strlen($file)-strrpos($file,'/'));
        return $filename;
    }
    echo GetFilename('/images/buy_tickets.gif');
    

    这将输出 buy_tickets.gif

    【讨论】:

      【解决方案4】:

      您只需要“td”标签内的图像吗?

      $regex='/<img src="\/images\/([^"]*)"[^>]*>/im';
      

      编辑:

      获取应该工作的特定图像:

      $regex='/<td valign=\'top\' class=\'rdBot\' align=\'center\'>.*src="\/images\/([^"]*)".*<\/td>/
      

      【讨论】:

      • 我只需要那里列出的图像,而不是所有图像。有时图像在链接内
      • Trey 这是来自 preg_match_all 的吗?像这样? $regexp = '/.*src="\/images\/([^"]*)".*/'; preg_match_all($regexp, $buffer, $matches, PREG_SET_ORDER)
      • 是的,实际上它应该在正则表达式的末尾有一个“im”:$regex='/&lt;td valign=\'top\' class=\'rdBot\' align=\'center\'&gt;.*src="\/images\/([^"]*)".*&lt;\/td&gt;/im
      • 嗯,我不能让它工作,我正在尝试你的页面,但我没有得到任何匹配
      • 这些正则表达式非常脆弱: 第一个正则表达式:img 和 src 之间有 2 个空格是什么意思?如果 img 和 src 之间还有另一个属性呢?如果 src 和 "=" 或 = 和 " 之间有空格怎么办?如果你有 src=' 而不是 src=" 怎么办?这些只是会破坏您的正则表达式的一些最常见的情况。对于第二个......这是一个失败:src之前的反转属性,空格,贪婪.*(这将匹配第一个td之后的任何地方),不允许“ vs '......这种正则表达式是人们推荐使用解析器的原因:它中断。
      【解决方案5】:

      不建议使用正则表达式解析 HTML,正如几位发帖人所提到的那样。

      但是,如果您的图片路径始终遵循模式 src="/images/name.gif",您可以在 Regex 中轻松提取它:

      $pattern = <<<EOD 
      #src\s*=\s*['"]/images/(.*?)["']# 
      EOD;
      

      如果您确定图像始终遵循路径“/images/name.ext”,并且您不关心图像链接在页面中的位置,那么这将完成工作。如果您有更详细的要求(例如仅在特定类中匹配),请忘记 Regex,它不是适合这项工作的工具。


      我刚刚在您的 cmets 中读到您需要在特定标签中匹配。使用解析器,它将为您省去无数麻烦。

      如果你还想通过正则表达式,试试这个:

      \(?<=<td .*?class\s*=\s*['"]rdBot['"][^<>]*?>.*?)(?<!</td>.*)<img [^<>]*src\s*=\s*["']/images/(.*?)["']\i
      

      这应该可行。它确实在 C# 中工作,我不完全确定 php 的正则表达式品牌。

      【讨论】:

        猜你喜欢
        相关资源
        最近更新 更多
        热门标签