【问题标题】:Matching a Specific URL Pattern with PHP使用 PHP 匹配特定的 URL 模式
【发布时间】:2013-09-09 22:01:54
【问题描述】:

我正在尝试读取 HTML 文件并捕获与特定 URL 模式匹配的所有锚标记,以便在另一个页面上显示这些链接。模式如下所示:

https://docs.google.com/file/d/aBunchOfLettersAndNumbers/edit?usp=drive_web

我对 RegEx 不满意。我已经尝试了很多东西,并在 Stack Overflow 上阅读了很多答案,但我没有找到正确的语法。

这是我现在拥有的:

preg_match ('/<a href="https:\/\/docs.google.com\/file\/d\/(.*)<\/a>/', $file, $matches)

当我在一个带有两个匹配锚标记的 HTML 页面上进行测试时,第一个结果包括第一个和第二个匹配以及介于两者之间的所有内容,而第二个结果包括第一个匹配的一部分、第二个匹配的一部分以及所有内容介于两者之间。

虽然我很乐意捕获匹配的锚标记以及内部 HTML,但如果我可以生成一个多维数组,其中包含每个匹配的锚标记的 HREF 属性以及匹配的内部 HTML (所以我可以自己格式化链接,而不必使用更多的正则表达式来删除不需要的属性)。我会为此使用 preg_match_all 吗?那会是什么样子?

我是不是走在正确的道路上,还是应该使用 DOM 和 XPath 查询来查找这些东西?

谢谢。

【问题讨论】:

  • 你应该完全使用 DOM。
  • 正则表达式不是魔杖,您可以在碰巧涉及字符串的每个问题上挥手。用正则表达式解析 HTML 只会让人心痛和痛苦。

标签: php regex html-parsing


【解决方案1】:

哦,天哪,我不敢相信这里的每个答案都使用“/”分隔符。如果您的模式中有斜线,请使用其他内容以提高可读性。

这是一个更好的答案(如果您的锚点可能具有除 href 之外的其他属性,您可能需要调整):

$hrefPattern = "(?P<href>https://docs\.google\.com/file/d/[a-z0-9]+/edit\?usp=drive_web)";
$innerPattern = "(?P<inner>.*?)";
$anchorPattern = "<a href=\"$hrefPattern\">$innerPattern</a>";
preg_match_all("@$anchorPattern@i", $file, $matches);

这会给你类似的东西:

[
    0 => ['<a href="https://docs.google.com/file/d/foo/edit?usp=drive_web"><span>More foo</span></a>'],
    "href" => ["https://docs.google.com/file/d/foo/edit?usp=drive_web"],
    "inner" => ["<span>More foo</span>"]
]

当然,您应该为此使用 DOM。

【讨论】:

    【解决方案2】:

    (.*) 替换为(.*?) - 使用惰性量化:

    preg_match('/<a href="https:\/\/docs.google.com\/file\/d\/(.*?)<\/a>/', $file, $matches);
    

    【讨论】:

      【解决方案3】:

      您可以使用以下正则表达式:

      /<a.*?href="(https:\/\/docs\.google\.com\/file\/d\/.*?)".*?>(.*?)<\/a>/
      

      这将为您提供来自 hrefinnerHTML 的 URL。

      分解

      &lt;a.*?href=" 匹配开头的a 标记和直到href=" 之前的任何字符

      (https:\/\/docs\.google\.com\/file\/d\/.*?)" 匹配(并捕获)直到href 结束(即直到"

      .*?&gt; 匹配a 标记&gt; 末尾的所有字符

      (.*?)&lt;\/a&gt; 匹配(并捕获)innerHTML 直到结束 a 标记(即&lt;/a&gt;)。

      【讨论】:

        【解决方案4】:

        戴夫,

        DOM 会更好。但这是有效的正则表达式。

        $url = 'href="https://docs.google.com/file/d/aBunchOfLettersAndNumbers/edit?usp=drive_web"';
        
        preg_match ('/href="https:\/\/docs.google.com\/file\/d\/(.*?)"/', $url, $matches);
        

        结果:

        array (size=2)
            0 => string 'href="https://docs.google.com/file/d/aBunchOfLettersAndNumbers/edit?usp=drive_web"' (length=82)
            1 => string 'aBunchOfLettersAndNumbers/edit?usp=drive_web' (length=44)
        

        您可以使用 html 标记,但最重要的是,在您的问题中,您在 preg_match 行中的代码不包含开始标记的结尾 >,这会将其丢弃,并且需要 (.? ) 而不是 (.)。添加的 ?告诉它寻找任何数量未知的字符。 (.*) 表示我相信的任何一个字符。

        【讨论】:

        • 好的,所以如果 DOM 是执行此操作的首选方式,我是否会将 HTML 页面加载到 DOMDocument 中,然后使用 xpath 查询遍历所有锚标记以查找匹配的文本字符串我正在寻找的网址?我正在寻找的链接在很多情况下都不会出现。在这种情况下,DOM 解决方案是否仍然有效?
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2023-01-10
        • 1970-01-01
        • 2011-04-23
        • 1970-01-01
        • 1970-01-01
        • 2013-01-17
        • 1970-01-01
        相关资源
        最近更新 更多