如何使用正则表达式更正已抓取 html 中的图片链接

How to correct image links in scraped html using regex

使用 SimpleHTMLDom 抓取页面上的 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 中缺少 <>。

如果你想使用它,请使用 DOMDocument or other HTML parser (edit: you already are using SimpleHTMLDom but I'm unfamiliar with it, ),最好是长 运行,特别是如果你想调整或获取其他元素。

<?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() 删除 ./../,并且可能 ../../

<?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;

全部产生相同的结果。