php - 如何使用正则表达式更正抓取的 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 中丢失。
解决方案
使用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();
或者使用您当前的代码产生相同的结果,但可能容易破坏使用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;
或者做更长的检查并用$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;
都产生相同的结果。
推荐阅读
- javascript - 理解并解决为什么这个未实例化的属性会产生错误?
- java - Webview 数据绑定慢(渲染慢)
- c# - 如何将复杂的sql变成linq
- reactjs - Redux `connect()` 返回一个对象
- c - outportb 和 8086 汇编中的 out 指令之间是否存在显着差异?
- php - 为什么空输出函数字符串不覆盖整数?
- python - 将文本分成句子 NLTK vs spaCy
- php - 在镜像构建阶段使用 gcsfuse
- java - 从 Kotlin 到 Java 的原始转换
- excel - Excel VBA 打开文件夹并获取其中每个文件的 GPS 信息 (Exif) (2)