首页 > 解决方案 > 如何使用正则表达式更正抓取的 html 中的图像链接

问题描述

使用 SimpleHTMLDom 进行抓取会检索页面上的 HTML,但不会像在 Web 浏览器中看到的那样检索 HTML,除非写入包含其在网站上的位置的完整 url,否则它们将丢失正确显示所需的信息。这些链接可以是多种多样的,有些没有前导斜杠 (/),有些则使用 (../)。所以我创建了一个脚本,希望使用正则表达式检索(img src),然后循环遍历每个,检查是否包含域名,如果没有,注入它。

$homepage = "https://example.com/";
$html = '<img class="drt" src="100.png"><img src="../101.png"><img src="/102.png"><img src="103.png">';

$check_img = preg_match_all("/<img .*?(?=src)src=\"([^\"]+)\"/si", $html, $m); 

foreach ($m[1] as $img){    
    if (strpos($img, $homepage) == false) {
        if (strpos($img, '../') !== false) {
            $html = str_replace('../', $homepage, $img);
        } elseif ($img[0] == '/') {
            $html = str_replace('/', $homepage, $img);
        } else {
            $html = substr_replace($img, $homepage, 0, 0);
        }      
    }    
}
echo $html;

但它只注入最后一个图像,并且由于某种原因 <> 从 html 中丢失。

标签: phpregexstr-replace

解决方案


使用DOMDocument或其他 HTML 解析器(编辑:你已经在使用 SimpleHTMLDom 但我不熟悉它,如果你想使用它,请看这里),从长远来看,特别是如果你想调整或获取其他元素,它会更好。

<?php
$homepage = "https://example.com/";
$html = '<img class="drt" src="100.png"><img src="../101.png"><img src="/102.png"><img src="103.png">';

$dom = new DOMDocument();
$dom->loadHTML($html);

foreach ($dom->getElementsByTagName('img') as $img) {
    $src = $img->getAttribute('src');
    if (strpos($img, '//') === false) {
        $src = $homepage.basename($src);
        $img->setAttribute('src', $src);
    }
}

// hacky way! remove unwanted doctype ect
$ret = preg_replace('~<(?:!DOCTYPE|/?(?:html|body|head))[^>]*>\s*~i', '', $dom->saveHTML());
echo trim(str_replace('<meta http-equiv="Content-Type" content="text/html;charset=utf-8">', '', $ret));

// proper way! but you dont have correct DOM, no <body>
// remove <!DOCTYPE 
//$dom->removeChild($dom->doctype);           
// remove <html><body></body></html> 
//$dom->replaceChild($dom->firstChild->firstChild->firstChild, $dom->firstChild);
//
//echo $dom->saveHTML();

https://3v4l.org/1sf3B

或者使用您当前的代码产生相同的结果,但可能容易破坏使用basename()删除./and ../,并且可能../../

<?php
$homepage = "https://example.com/";
$html = '<img class="drt" src="100.png"><img src="../101.png"><img src="/102.png"><img src="103.png">';

$check_img = preg_match_all("/<img .*?(?=src)src=\"([^\"]+)\"/si", $html, $m); 

foreach ($m[1] as $img){    
    if (strpos($img, '//') === false) 
        $html = str_replace($img, $homepage.basename($img), $html);    
}
echo $html;

示例:https ://3v4l.org/LvL82

或者做更长的检查并用$html替换的$src值替换

<?php
$homepage = "https://example.com/";
$html = '<img class="drt" src="100.png"><img src="../101.png"><img src="/102.png"><img src="103.png">';

$check_img = preg_match_all("/<img .*?(?=src)src=\"([^\"]+)\"/si", $html, $m); 

foreach ($m[1] as $img){    
    if (strpos($img, '//') === false) {
        $old_img = $img;
        
        if (strpos($img, '../') !== false) {
            $img = str_replace('../', $homepage, $old_img);
        } elseif ($img[0] == '/') {
            $img = str_replace('/', $homepage, $old_img);
        } else {
            $img = $homepage.$old_img;
        }  
        
        $html = str_replace($old_img, $img, $html);
    }    
}
echo $html;

都产生相同的结果。


推荐阅读