【问题标题】:Regex for finding url用于查找 url 的正则表达式
【发布时间】:2013-07-22 03:29:40
【问题描述】:
<a href="http://newday.com/song.mp3">First Link</a>
<div id="right_song"> 
        <div style="font-size:15px;"><b>Pitbull ft. Chris Brown - Pitbull feat. Chris Brown - International Love mp3</b></div> 
        <div style="clear:both;"></div> 
<div style="float:left;"> 
    <div style="float:left; height:27px; font-size:13px; padding-top:2px;"> 
        <div style="float:left;"> 
    <a href="http://secondurl.com/thisoneshouldonlyoutput" rel="nofollow" target="_blank" style="color:green;">Second Link</a></div>'; 

我想使用 pregmatch_all 从此 html 中取出第二个链接。我当前的正则表达式如下所示:

preg_match_all("/\<a.+?href=(\"|')(?!javascript:|#)(.+?)\.mp3(\"|')/i", $html, $urlMatches);

这很好,我得到了两个链接输出,但我只希望输出第二个没有 .mp3 扩展名的链接。请帮帮我

【问题讨论】:

  • 我们不使用正则表达式解析 html
  • 使用 HTML DOM 解析器解析 HTML DOM - simplehtmldom.sourceforge.net
  • 我知道我不应该使用正则表达式,但我现在必须这样做。有什么帮助吗?
  • 不要使用正则表达式解析 HTML。您无法使用正则表达式可靠地解析 HTML,并且您将面临悲伤和挫败感。一旦 HTML 与您的期望发生变化,您的代码就会被破坏。有关如何使用已经编写、测试和调试的 PHP 模块正确解析 HTML 的示例,请参阅 htmlparsing.com/php

标签: php regex html-parsing preg-match-all


【解决方案1】:

说明

这个正则表达式将

  • 匹配&lt;div id="rigth_song"&gt;之后的第一个锚标签,它的href属性的值以.mp3结尾
  • 将避免许多使 html 文本与正则表达式匹配非常困难的极端情况。

&lt;div\sid="right_song"&gt;.*?&lt;a(?=\s|&gt;)(?=(?:[^&gt;=]|='[^']*'|="[^"]*"|=[^'"][^\s&gt;]*)*?\shref=(['"]?)(.*?\.mp3)\1(?:\s|\/&gt;|&gt;))(?:[^&gt;=]|='[^']*'|="[^"]*"|=[^'"][^\s&gt;]*)*&gt;.*?&lt;\/a&gt;

示例

示例文本

注意第二个锚标记中的困难边缘情况,例如字符串href="bad.mp3"嵌套在属性值中;值内有一个大于符号&gt;的javascript;而真正的 href 属性是不带引号的。

<a href="http://newday.com/song.mp3">First Link</a>
<div id="right_song"> 
        <div style="font-size:15px;"><b>Pitbull ft. Chris Brown - Pitbull feat. Chris Brown - International Love mp3</b></div> 
        <div style="clear:both;"></div> 
<div style="float:left;"> 
    <div style="float:left; height:27px; font-size:13px; padding-top:2px;"> 
        <div style="float:left;"> 
<a onmouseover=' href="bad.mp3" ; if ( 6 > x ) {funRotate(href); } ; ' href="http://secondurl.com/thisoneshouldonlyoutput.mp3">First Link</a>
</div>

代码

<?php
$sourcestring="your source string";
preg_match('/<div\sid="right_song">.*?<a(?=\s|>)(?=(?:[^>=]|=\'[^\']*\'|="[^"]*"|=[^\'"][^\s>]*)*?\shref=([\'"]?)(.*?\.mp3)\1(?:\s|\/>|>))(?:[^>=]|=\'[^\']*\'|="[^"]*"|=[^\'"][^\s>]*)*>.*?<\/a>
/imsx',$sourcestring,$matches);
echo "<pre>".print_r($matches,true);
?>

匹配

组 0 获取从 &lt;div 到包含完整匹配锚标记的文本
第 1 组获取围绕 href 值的开头引号,稍后将引用该值
第 2 组获取 href 值

[0] => <div id="right_song"> 
        <div style="font-size:15px;"><b>Pitbull ft. Chris Brown - Pitbull feat. Chris Brown - International Love mp3</b></div> 
        <div style="clear:both;"></div> 
<div style="float:left;"> 
    <div style="float:left; height:27px; font-size:13px; padding-top:2px;"> 
        <div style="float:left;"> 
<a onmouseover=' href="bad.mp3" ; if ( 6 > x ) {funRotate(href); } ; ' href="http://secondurl.com/thisoneshouldonlyoutput.mp3">First Link</a>
[1] => "
[2] => http://secondurl.com/thisoneshouldonlyoutput.mp3

【讨论】:

  • 不可以只添加div id验证或者div style验证吗?
  • 您的示例文本没有平衡的打开和关闭 div 标签。这是关于正则表达式可以对 html 文档中的匹配字符串执行的操作的限制。匹配嵌套的 div 标签是一个数量级更复杂的问题。如果您知道这是页面上的第二场比赛,那么您最好只参加第二场比赛,否则您将陷入创建有问题的正则表达式或使用解析工具的困境。
  • html 代码是从互联网上加载的,我无法控制它的编码方式。还是谢谢
  • 我更新了表达式以匹配所需 div 标签之后的第一个锚标签。这确实允许许多额外的边缘情况可能无法按预期处理。
猜你喜欢
  • 2017-04-26
  • 2014-01-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-10
  • 2016-12-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多