使用PHP的正则表达式还是DOMDocument来匹配和删除URL?

3
我正在尝试使用DOM从HTML页面中提取链接:
$html = file_get_contents('links.html');
$DOM = new DOMDocument();
$DOM->loadHTML($html);
$a = $DOM->getElementsByTagName('a');
foreach($a as $link){
    //echo out the href attribute of the <A> tag.
    echo $link->getAttribute('href').'<br/>';
}

输出:

http://dontwantthisdomain.com/dont-want-this-domain-name/
http://dontwantthisdomain2.com/also-dont-want-any-pages-from-this-domain/
http://dontwantthisdomain3.com/dont-want-any-pages-from-this-domain/
http://domain1.com/page-X-on-domain-com.html

http://dontwantthisdomain.com/dont-want-link-from-this-domain-name.html
http://dontwantthisdomain2.com/dont-want-any-pages-from-this-domain/
http://domain.com/page-XZ-on-domain-com.html

http://dontwantthisdomain.com/another-page-from-same-domain-that-i-dont-want-to-be-included/
http://dontwantthisdomain2.com/same-as-above/
http://domain3.com/page-XYZ-on-domain3-com.html

我希望删除所有与dontwantthisdomain.com、dontwantthisdomain2.com和dontwantthisdomain3.com匹配的结果,以便输出看起来像这样:
http://domain1.com/page-X-on-domain-com.html
http://domain.com/page-XZ-on-domain-com.html
http://domain3.com/page-XYZ-on-domain3-com.html

有些人说我不应该使用正则表达式来处理HTML,而另一些人则认为这样做没问题。请问有没有人能指出最好的方法来从我的HTML文件中删除不需要的URL? :)


你的脚本剩下的输出已经不是HTML了,对吧?因此,在使用DOM解析器从HTML中抓取链接后,通过正则表达式进行过滤是完全可以的。虽然在这种情况下,可能有更简单的替代方案。例如,您可以使用parse_url获取域名(host),然后仅检查它是否在不需要的域名黑名单中。 - Martin Ender
2个回答

2
也许是这样的:

可能是这样的:

function extract_domains($buffer, $whitelist) {
    preg_match_all("#<a\s+.*?href=\"(.+?)\".*?>(.+?)</a>#i", $buffer, $matches);
    $result = array();
    foreach($matches[1] as $url) {
        $url = urldecode($url);
        $parts = @parse_url((string) $url);
        if ($parts !== false && in_array($parts['host'], $whitelist)) {
            $result[] = $parts['host'];
        }
    }
    return $result;
}

$domains = extract_domains(file_get_contents("/path/to/html.htm"), array('stackoverflow.com', 'google.com', 'sub.example.com')));

它会对所有标签中的href属性进行粗略匹配,提取引号之间的内容,然后根据你的域名白名单进行过滤。

为什么要使用@parse_url?只是问一下。抑制错误不是一个好主意。 - davidkonrad
如果 parse_url() 失败,它将产生一个警告(或至少是一个通知)。由于数据是我认为的“用户输入”,所以无法确定会在 href="" 属性中放置什么样的诡计。我抑制了错误,然后在紧接着下面的 if语句 中使用严格不等于手动检查它。 - SamT

1

无正则表达式解决方案(无潜在错误):

$html='
http://dontwantthisdomain.com/dont-want-this-domain-name/
http://dontwantthisdomain2.com/also-dont-want-any-pages-from-this-domain/
http://dontwantthisdomain3.com/dont-want-any-pages-from-this-domain/
http://domain1.com/page-X-on-domain-com.html

http://dontwantthisdomain.com/dont-want-link-from-this-domain-name.html
http://dontwantthisdomain2.com/dont-want-any-pages-from-this-domain/
http://domain.com/page-XZ-on-domain-com.html

http://dontwantthisdomain.com/another-page-from-same-domain-that-i-dont-want-to-be-included/
http://dontwantthisdomain2.com/same-as-above/
http://domain3.com/page-XYZ-on-domain3-com.html
';

$html=explode("\n", $html);
$dontWant=array('dontwantthisdomain.com','dontwantthisdomain2.com','dontwantthisdomain3.com');
foreach ($html as $link) {
    $ok=true;
    foreach($dontWant as $notWanted) {
        if (strpos($link, $notWanted)>0) { 
            $ok=false;
        }
        if (trim($link=='')) $ok=false;
    }
    if ($ok) $final_result[]=$link;
}

echo '<pre>';
print_r($final_result);
echo '</pre>';

输出

Array
(
    [0] => http://domain1.com/page-X-on-domain-com.html
    [1] => http://domain.com/page-XZ-on-domain-com.html
    [2] => http://domain3.com/page-XYZ-on-domain3-com.html
)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接