2011-10-18 88 views
1

首先内部的子:我知道我不应该使用正则表达式来解析HTML。我已经读过数十亿次了。但是工具我必须使工作是基于正则表达式的工具,所以我不能使用HTML解析器或任何其他事情。无论如何,我感谢你所有的关注,但如果我需要做的工作与正则表达式,伟大的。如果没有,对不起,我们不得不放弃此功能。正则表达式PHP - 查找<div></div>标签

的问题是:

简短的解释:我需要一个正则表达式返回一个包含在标签中生成PHP网页的子(WordPress的,对什么事情)。

很长的解释:我需要找到位于我的页面内存在的各种<div class="post-bodycopy clearfix">内的游戏名称的每个实例(在本例中,游戏的名称Batman: Arkham City)。这意味着我只想要在帖子正文内的游戏名称,而不是在帖子标题或侧边栏或任何地方。然后,我会用preg替换或类似的东西替换这个名称。

我在网上搜索了类似的问题,但我只能找到这样的“给我所有的内部标签”的问题。

这里是我生成的代码中的典型职务:

<div class="post-268445 post hentry category-world-community-gamer tag-games tag-geral tag-lancamentos tag-noticias tag-pc tag-ps3 tag-xb360" id="post-268445"> 
<div class="post-kicker"><?php get_cat_icon(); ?><a href="http://www.gameblogs.com.br/category/world-community-gamer/" title="World Community Gamer" onclick="return TrackClick('http://www.gameblogs.com.br/category/world-community-gamer/','')"><img src="http://www.gameblogs.com.br/wp-content/uploads/world-community-gamer.png" width="48" height="48" alt="" title="World Community Gamer" /></a></div> 
<div class="post-headline">  <h2> <a href="http://www.worldcommunitygamer.com/2011/10/data-para-batman-arkham-city-no-pc.html?utm_source=gameblogs&utm_campaign=data-para-batman-arkham-city-no-pc" rel="bookmark" title="Permanent Link to Data para Batman: Arkham City no PC" target="_blank" onclick="return TrackClick('http://www.worldcommunitygamer.com/2011/10/data-para-batman-arkham-city-no-pc.html?utm_source=gameblogs&utm_campaign=data-para-batman-arkham-city-no-pc','')">Data para Batman: Arkham City no PC</a></h2> </div> 
<div class="post-byline"><img src="http://www.gameblogs.com.br/wp-content/themes/atahualpa353/images/icons/user.gif" alt="" /> <a href="http://www.gameblogs.com.br/author/_otaviofqueiroz/" title="Posts de @_otaviofqueiroz" onclick="return TrackClick('http://www.gameblogs.com.br/author/_otaviofqueiroz/','')">@_otaviofqueiroz</a>, do <img src="http://www.gameblogs.com.br/wp-content/themes/atahualpa353/images/icons/home.gif" alt="" /> <a href="http://www.worldcommunitygamer.com/" target="_blank" target="_blank" onclick="return TrackClick('http://www.worldcommunitygamer.com/','')">WCG | World Community Gamer: Jogos, Análises e Tecnologia</a>, <img src="http://www.gameblogs.com.br/wp-content/themes/atahualpa353/images/icons/calendar_month.png" alt="" /> 18/10/11 | Compartilhe: <a href="http://twitter.com/share" class="twitter-share-button" data-url="http://www.worldcommunitygamer.com/2011/10/data-para-batman-arkham-city-no-pc.html?utm_source=gameblogs&utm_campaign=data-para-batman-arkham-city-no-pc" data-text="WCG | World Community Gamer: Jogos, Análises e Tecnologia: Data para Batman: Arkham City no PC" data-count="horizontal" data-via="GameBlogsBR" data-lang="fr" target="_blank" onclick="return TrackClick('http://twitter.com/share','')">Tweet</a><script type="text/javascript" src="http://platform.twitter.com/widgets.js"></script></div><div class="post-bodycopy clearfix"><p> <a href="http://www.worldcommunitygamer.com/2011/10/data-para-batman-arkham-city-no-pc.html" imageanchor="1" style="margin-left: 1em; margin-right: 1em;" target="_blank" onclick="return TrackClick('http://www.worldcommunitygamer.com/2011/10/data-para-batman-arkham-city-no-pc.html','')"><img src="/wp-content/plugins/wordpress-image-resizer/thumb/phpThumb.php?fltr=usm&#038;src=http://2.bp.blogspot.com/-9oKlgIND3qY/Tp3Aimju2nI/AAAAAAAABxA/Q585nqpdsRI/s1600/batman_arkham_city_screens16-620x348.jpg&#038;w=200" align='left'></a> 
<p>A Warner divulgou a data de lançamento para Batman: Arkham City no PC. O jogo que terá a sua versão para os consoles (PS3 e Xbox 360) lançada nessa sexta-feira, chegará as lojas na versão PC no dia 18 de Novembro. Apesar da demora [...]<br /><a href=http://www.worldcommunitygamer.com/2011/10/data-para-batman-arkham-city-no-pc.html?utm_source=gameblogs&#038;utm_campaign=data-para-batman-arkham-city-no-pc>[continua no site original...]</a></p></div> 
<div class="post-footer"><img src="http://www.gameblogs.com.br/wp-content/themes/atahualpa353/images/icons/tag.gif" alt="" /> <a href="http://www.gameblogs.com.br/tag/games/" rel="tag" onclick="return TrackClick('http://www.gameblogs.com.br/tag/games/','')">Games</a>, <a href="http://www.gameblogs.com.br/tag/geral/" rel="tag" onclick="return TrackClick('http://www.gameblogs.com.br/tag/geral/','')">Geral</a>, <a href="http://www.gameblogs.com.br/tag/lancamentos/" rel="tag" onclick="return TrackClick('http://www.gameblogs.com.br/tag/lancamentos/','')">lançamentos</a>, <a href="http://www.gameblogs.com.br/tag/noticias/" rel="tag" onclick="return TrackClick('http://www.gameblogs.com.br/tag/noticias/','')">Notícias</a>, <a href="http://www.gameblogs.com.br/tag/pc/" rel="tag" onclick="return TrackClick('http://www.gameblogs.com.br/tag/pc/','')">PC</a>, <a href="http://www.gameblogs.com.br/tag/ps3/" rel="tag" onclick="return TrackClick('http://www.gameblogs.com.br/tag/ps3/','')">PS3</a>, <a href="http://www.gameblogs.com.br/tag/xb360/" rel="tag" onclick="return TrackClick('http://www.gameblogs.com.br/tag/xb360/','')">XB360</a><br>Todos os posts do <a href="http://www.gameblogs.com.br/category/world-community-gamer/" onclick="return TrackClick('http://www.gameblogs.com.br/category/world-community-gamer/','')">World Community Gamer</a></div></div><!--/Post --> 

我已经尝试了查找以下内容:

$<div class\=\"post-bodycopy clearfix\">(.+?)(Batman: Arkham City)(.+?)(?=<div class\=\"post-footer\">)$s 

含义:找到DIV开始标记,接着任何东西,其次是蝙蝠侠:阿卡姆城,其次是任何东西,直到开幕后的页脚div标签,考虑多线。

而对于替换以下:

<div class="post-bodycopy clearfix">/1<a href="http://www.mylink">Batman: Arkham City</a>/3 

出于某种原因,正则表达式工作在http://regexlib.com,返回所有预期的部分,但不是在我的直播网站。这一定是一些小问题。

不过,我相信,我的soluton没有找到这样一个子最优雅(和服务器消耗/更便宜的)方式,因为我救各个部分只是改变其中之一。

有一个聪明的方式来实现这一目标?请?

非常感谢!

+0

为什么*无法使用解析器?它认为破解你的代码来使用HTML解析器比正则表达式更容易。 – Blender

+0

你是问如何在html页面中找到“蝙蝠侠:阿卡姆城”,或者你问如何在html页面上找到这个星球上的每一个游戏? – bozdoz

+0

@bozdoz每页只有一个特定的游戏。谢谢。 – Daniel

回答

0

$标题= '蝙蝠侠:阿甘之城';

搜索:{(?<=<div class="post-bodycopy clearfix">)(.+?)($title)(.+?)(?=<div class="post-footer">)}s

取代:
\1<a href="http://www.mylink">\2</a>\3

$1<a href="http://www.mylink">$2</a>$3

编辑
你可以试试下面的。例如PHP是这里http://ideone.com/JtH4s

$title = 'Batman: Arkham City'; 
$divclass = 'post-bodycopy clearfix'; 

$rxtag = 
'< 
(?: 
    \?php\s+.*?\? 
    | (?: 
     (?: 
      (?:script|style)\s* 
     | (?:script|style)\s+(?:".*?"|\'.*?\'|[^>]*?)+\s* 
     )> .*? </(?:script|style)\s* 
    ) 
    | (?: 
     /?[A-Za-z_:][\w:.-]*\s*/? 
     | [A-Za-z_:][\w:.-]*\s+(?:".*?"|\'.*?\'|[^>]*?)+\s*/? 
     | !(?:DOCTYPE.*?|--.*?--) 
    ) 
) 
> 
'; 

// Or, 
// $rxtag_optional = '<[^<>]+?>'; 
// $rxtag = $rxtag_optional; 



$rxmain = 
"~(?xs: 
    (<div (?=\\s)[^>]* 
      (?<=\\s) class \\s* = \\s* \" \\s* (?i-x:$divclass) \\s* \" 
      [^>]* (?<!/) 
    > 
    (?: 
     (?! </?div | (?-x:$title)) 
     (?> $rxtag | [^<] | <) 
    )*? 
    ) 
    ((?-x:$title)) 
    (
     (?: (?!</?div) (?> $rxtag | [^<] | <))*? 
     </div \\s*> 
    ) 
) 
~"; 

//print "$rxmain\n\n"; 

$count = 0; 

$newhtml = preg_replace($rxmain, 
         "$1<a href=\"http://www.mylink\">$2</a>$3", 
         $html, 
         1, 
         $count); 
+0

所以我错过了?<=开头的部分。谢谢。但我正在和一些同事讨论这个问题,我们发现事情会变得比现在复杂得多,因为游戏的名字不能包含标签,例如。可能吗? – Daniel

+0

经过一些更多的测试后,这种方式由于某种原因,正则表达式仍然在div标签之外捕捉到一些蝙蝠侠:阿卡姆城。 :( – Daniel

+0

你可以尝试在我的文章中添加新的正则表达式。 – sln

0

我放在一起的例子here具有以下的正则表达式在PHP中:

'|(<div class="post-bodycopy clearfix">)(.*?)(Batman: Arkham City)(.*?)(</div>)|e' 

我添加了一个蝙蝠侠:阿甘之城在HTML串的底部,只是为了测试。它似乎在工作。让我知道。

0

如果你坚持使用正则表达式,你的<div class="post-bodycopy clearfix">...</div>内容永远不会包含任何嵌套的DIV,这里是一个双回调的解决方案,应该做一个体面的工作:

// Linkify title inside post-bodycopy DIV text. 
function p($text) { 
    global $title, $link; 
    // Set title to be found and linkify URL address. 
    $title = 'Batman: Arkham City'; 
    $link = 'http://www.mylink'; 
    // Match non-nested "post-bodycopy" class DIV element. 
    $re = '%<div class="post-bodycopy clearfix">(.+?)</div>%si'; 
    return preg_replace_callback($re, 'p_cb', $text); 
} 
function p_cb($matches) { 
    // Match tag (in $1) and non-tag stuff (in $2). 
    $re = '% 
      (</?\w+ # Either $1: An open or close tag. 
      (?:\s+[\w\-.:]+(?:\s*=\s*(?:"[^"]*"|\'[^\']*\'|[^\s<>]+))?)* 
      \s*/?> 
     ) 
     | ([^<]+) # Or $2: Non-tag stuff. 
     %x'; 
    $matches[1] = preg_replace_callback($re, 'p_cb_cb', $matches[1]); 
    return '<div class="post-bodycopy clearfix">'. $matches[1] .'</div>'; 
} 
function p_cb_cb($matches) { 
    global $title, $link; 
    # Return open and close tags unchanged. 
    if (isset($matches[1]) && $matches[1]) return $matches[1]; 
    # Process non-tag text, converting text to link. 
    $matches[2] = str_replace(
     $title, 
     '<a href="'. $link .'">'. $title .'</a>', 
     $matches[2]); 
    return $matches[2]; 
} 

p()函数处理HTML文件内容。它的正则表达式匹配<div class="post-bodycopy clearfix">...</div>元素并将DIV内容传递给p_cb()回调函数。这个第一个回调函数然后使用匹配打开或关闭标签(到捕获组$1)或非标签内容(到捕获组$2)的正则表达式来走向/处理DIV的内容。这又调用第二个回调函数p_cb_cb(),该函数简单地返回打开和关闭标记(在$1中),然后使用str_replace()$title文本的所有实例转换为所需的链接。

请注意,您的HTML标记无效。它有许多未加引号的标签属性值(应引用它们)。