str_replace失败并带有特定字符

时间:2014-02-28 02:51:39

标签: php regex xpath

运行一个似乎有声音部分的简单str_replace,但是当我用这些部分运行str_replace时,输出是不正确的。

foreach($x->query("//img") as $node) 
{   
    $absoluteImage = make_absolute($node->getAttribute("src"), $url);
    $iterateImage = str_replace($node->getAttribute("src"), $absoluteImage, $html);   
}

function make_absolute($url, $base) { 

    // Return base if no url
    if( ! $url) return $base;

    // Already absolute URL
    if(parse_url($url, PHP_URL_SCHEME) != '') return $url;

    // Only containing query or anchor
    if($url[0] == '#' || $url[0] == '?') return $base.$url;

    // Parse base URL and convert to local variables: $scheme, $host, $path
    extract(parse_url($base));

    // If no path, use /
    if( ! isset($path)) $path = '/';

    // Remove non-directory element from path
    $path = preg_replace('#/[^/]*$#', '', $path);

    // Destroy path if relative url points to root
    if($url[0] == '/') $path = '';

    // Dirty absolute URL
    $abs = "$host$path/$url";

    // Replace '//' or '/./' or '/foo/../' with '/'
    $re = array('#(/\.?/)#', '#/(?!\.\.)[^/]+/\.\./#');
    for($n = 1; $n > 0; $abs = preg_replace($re, '/', $abs, -1, $n)) {}

    // Absolute URL is ready!
    return $scheme.'://'.$abs;
}

该代码适用于从相对绝对URL替换img标记的src部分的scraper。 make_absolute是完成工作的函数,它工作正常。当我回显$ absoluteImage和$ node-> getAttribute(“src”)时,它们都会打印出正确的结果。绝对URL和相对URL。但是当我用这两个部分运行str_replace函数时,结果是不正确的。请参阅以下数据:

相对网址:

<img border="0" src="media/splash/a1.jpg" width="123" height="49">
<img border="0" src="media/splash/a2.jpg" width="136" height="49">
<img border="0" src="media/splash/pixel_clear.gif" width="187" height="1"><br>
<img border="0" src="media/splash/b1.jpg" width="123" height="66">
<img border="0" src="media/splash/b2.jpg" width="136" height="66">
<img border="0" src="media/splash/b3.jpg" width="187" height="66">
<img border="0" src="media/splash/c1.jpg" width="123" height="150">
<img border="0" src="media/splash/c2.jpg" width="136" height="150">
<img border="0" src="media/splash/c3.jpg" width="187" height="150">
<img border="0" src="media/splash/pixel_clear.gif" width="123" height="1">
<img border="0" src="media/splash/d1.jpg" width="136" height="127">
<img border="0" src="media/splash/d2.jpg" width="187" height="127">
<img border="0" src="media/splash/pixel_clear.gif" width="446" height="59">
<img border="0" src="media/splash/f1.jpg" width="446" height="147"><br>
<img border="0" src="media/splash/g1.jpg" width="446" height="142"></td>

生成的绝对URL:

<img border="0" src="http://www.bjnormand.com/media/splash/a1.jpg" width="123" height="49">
<img border="0" src="http://www.bjnormand.com/media/splash/a2.jpg" width="136" height="49">
<img border="0" src="http://www.bjnormand.com/http://www.bjnormand.com/http://www.bjnormand.com/media/splash/pixel_clear.gif" width="187" height="1"><br>
<img border="0" src="http://www.bjnormand.com/media/splash/b1.jpg" width="123" height="66">
<img border="0" src="http://www.bjnormand.com/media/splash/b2.jpg" width="136" height="66">
<img border="0" src="http://www.bjnormand.com/media/splash/b3.jpg" width="187" height="66">
<img border="0" src="http://www.bjnormand.com/media/splash/c1.jpg" width="123" height="150">
<img border="0" src="http://www.bjnormand.com/media/splash/c2.jpg" width="136" height="150">
<img border="0" src="http://www.bjnormand.com/media/splash/c3.jpg" width="187" height="150">
<img border="0" src="http://www.bjnormand.com/http://www.bjnormand.com/http://www.bjnormand.com/media/splash/pixel_clear.gif" width="123" height="1">
<img border="0" src="http://www.bjnormand.com/media/splash/d1.jpg" width="136" height="127">
<img border="0" src="http://www.bjnormand.com/media/splash/d2.jpg" width="187" height="127">
<img border="0" src="http://www.bjnormand.com/http://www.bjnormand.com/http://www.bjnormand.com/media/splash/pixel_clear.gif" width="446" height="59">
<img border="0" src="http://www.bjnormand.com/media/splash/f1.jpg" width="446" height="147"><br>
<img border="0" src="http://www.bjnormand.com/media/splash/g1.jpg" width="446" height="142">

我唯一可以看到的是失败的3行在图像名称中有一个'_'。

任何人都知道发生了什么事?

更新 尝试这一点,以密切关注每次迭代,但没有运气:

$count = 0;
$imgArr = array();
foreach($x->query("//img") as $node) 
{
    if ($node->getAttribute("src")) {
        $imgArr[] = $node->getAttribute("src");
        $count++;
    }
}
for($i = 0; $i < count($imgArr); $i++) {
    $html = str_replace($imgArr[$i], make_absolute($imgArr[$i], $url), $html);
}

echo $html;

2 个答案:

答案 0 :(得分:1)

每次进行循环时,您都会在整个HTML块上运行字符串替换。因为您有多次出现相同的图像,所以每次在循环中点击相同的图像时都会替换它。

一种解决方案是将其更改为包含属性周围的引号,以便它只匹配完整的图像名称:

$iterateImage = str_replace('"'.$node->getAttribute("src").'"', '"'.$absoluteImage.'"', $html);

另一种选择是跟踪您已完成替换的图像,并确保每次只替换一次。但是,如果您有一个图像的名称是另一个图像名称的一部分(例如image.jpgmyimage.jpg,则可能仍有问题。

答案 1 :(得分:0)

您可以尝试对包含下划线的任何网址执行快速正则表达式:

// Dirty absolute URL
$abs = "$host$path/$url";

if (preg_match('/(_)/', $url)) $abs = "$url";