【问题标题】:Using a regular expression to extract URLs from links in an HTML document使用正则表达式从 HTML 文档中的链接中提取 URL
【发布时间】:2011-09-21 15:34:01
【问题描述】:

我需要捕获给定 html 中的所有链接。

这里是示例代码:

<div class="infobar">
    ... some code goes here ...
    <a href="/link/some-text">link 1</a>
    <a href="/link/another-text">link 2</a>
    <a href="/link/blabla">link 3</a>
    <a href="/link/whassup">link 4</a>
    ... some code goes here ...
</div>

我需要获取div.infobar 中以/link/ 开头的所有链接

我试过了:

preg_match_all('#<div class="infobar">.*?(href="/link/(.*?)") .*?</div>#is', $raw, $x);

但它给了我唯一的第一场比赛。

感谢您的建议。

【问题讨论】:

  • 也许有一个 html 解析器可以更轻松地为您做到这一点?
  • 我已经得到了它,首先使用 preg_match 获取 div.infobar 的内部,然后使用 preg_match_all 获取链接。但是由于正则表达式提供了更大的灵活性,为什么我不应该使用它呢?我只需要一个好的模式。我想知道如何只用 1 个 preg_match_all 来完成它
  • 你不能用一个正则表达式来做到这一点。您首先需要隔离 div,然后从中提取所需的链接。 -- 粗短的 cmets 是关于什么的:您可以使用 phpQuery 或 QueryPath 更轻松地提取链接,使用 foreach (qp($html)-&gt;find("div.infobar a") as $a) { print $a-&gt;attr("href"); }
  • HTML 不是常规语言,所以是unwise to use a regular expression to parse HTML
  • @stereofrog,公平点;对于这种特定情况,我无法改进anubhava's answer,我认为有点轻率是一种很好的方式来表明尝试使用错误的工具来完成这项工作会导致令人难以置信的挫败感。

标签: php regex preg-match-all


【解决方案1】:

http://simplehtmldom.sourceforge.net/

// Create DOM from URL or file
$html = file_get_html('http://www.google.com/');

// Find all links
foreach($html->find('a') as $element)
       echo $element->href . '<br>'; 

【讨论】:

    【解决方案2】:

    修改我之前的答案。您需要分两步完成:

    //This first step grabs the contents of the div.
    preg_match('#(?<=<div class="infobar">).*?(?=</div>)#is', $raw, $x);
    
    //And here, we grab all of the links.
    preg_match_all('#href="/link/(.*?)"#is', $x[0], $x);
    

    【讨论】:

    • 谢谢。但这次它得到了最后一个:D
    • 我把它分成两个步骤。 div第一次匹配,然后就不能再匹配了。
    【解决方案3】:

    我建议为此目的使用DOMDocument 而不是使用正则表达式。考虑以下简单代码:

    $content = '
    <div class="infobar">
        <a href="/link/some-text">link 1</a>
        <a href="/link/another-text">link 2</a>
        <a href="/link/blabla">link 3</a>
        <a href="/link/whassup">link 4</a>
    </div>';
    $dom = new DOMDocument();
    $dom->loadHTML($content);
    
    // To hold all your links...
    $links = array();
    
    // Get all divs
    $divs = $dom->getElementsByTagName("div");
    foreach($divs as $div) {
      // Check the class attr of each div
      $cl = $div->getAttribute("class");
      if ($cl == "infobar") {
        // Find all hrefs and append it to our $links array
        $hrefs = $div->getElementsByTagName("a");
        foreach ($hrefs as $href)
           $links[] = $href->getAttribute("href");
      }
    }
    var_dump($links);
    

    输出

    array(4) {
      [0]=>
      string(15) "/link/some-text"
      [1]=>
      string(18) "/link/another-text"
      [2]=>
      string(12) "/link/blabla"
      [3]=>
      string(13) "/link/whassup"
    }
    

    【讨论】:

    • 让我们看看操作是否仍然认为正则表达式更好:d
    • 这个和正则表达式之间的执行时间是多少?我只需 2 个 preg_match_all 函数就可以做到这一点。
    • 执行时间将与基于正则表达式的代码相当(甚至更好),但更重要的是,与正则表达式代码相比,基于 DOM 的代码不会在意外时间中断。
    【解决方案4】:

    试试这个(我添加了+):

    preg_match_all('#<div class="infobar">.*?(href="/link/(?:.*?)")+ .*?</div>#is', $raw, $x);
    

    【讨论】:

      猜你喜欢
      • 2010-10-04
      • 2010-12-31
      • 2010-12-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多