我有一个从各种来源抓取 URL 的脚本,从而产生了一个相当大的列表。目前,我刚刚收集了一组 if 语句,用于过滤掉我不想要的网站。这显然是不可维护的,所以我试图找到一种快速而强大的解决方案来过滤 url 掩码的黑名单。
我能想到的最好的事情是循环遍历一组正则表达式并过滤任何匹配的内容。这真的是我最好的选择还是有另一种方法可以更好地完成这项工作?
如果要排除域名或某些没有“可变部分”的 URL,解决方案可能是使用数据库,其中包含仅包含 URL 的表,具有正确的索引,并进行快速匹配。
找出一个 URL 是否必须被处理然后只是一个问题或对该数据库进行快速查询(这通常意味着“URL 等于”或“URL 以”开头) ——这可以像 SQLite 一样简单DB,适合文件,不需要额外的服务器。
PHP 数组的想法有一个缺点:当你的数组变得更大时,它会占用越来越多的内存才能将它保存在内存中——而且,总有一天,你会占用太多内存并且会命中memory_limit
; 如果您有超过几千个 URL,那么该解决方案可能不是最好的解决方案。
尽管如此,如果你只有几个 URL 或模式,PHP 数组的想法,循环它,并将每个值与strpos
(对于“包含”或“开始于”)或preg_match
(对于正则表达式)进行比较就可以了 - - 并且是最容易实现的。
如果你想使用一些复杂的匹配规则,使用某种正则表达式可能是你唯一真正的方法......无论是在 PHP 端,preg_match
还是在 SQL 服务器上(例如,MySQL 支持正则表达式,据我所知——不过,对性能一无所知;有关更多信息,请参阅11.4.2. 正则表达式)
您应该将站点保存在哈希中并像这样查找。它简单而优雅:
$excluded['www.google.com'] = true;
$excluded['www.mapquest.com'] = true;
$excluded['www.yahoo.com'] = true;
$url = "http://www.google.com?q=barefoot+winery";
$urlArray = parse_url($url)
if (! isset($excluded[$urlArray['host']]))
{
scrape($url)
}
正如帕斯卡所说,一段时间后你会遇到内存问题。但到那时,维护 url 将是一个更大的问题。发生这种情况时去寻找数据库。
如果您需要能够指定模式,那么循环遍历一组正则表达式可能就可以了。
如果您只需要查看完全匹配而没有模式,则可以使用 strpos 等来进行直接字符串匹配,这应该会更快一些。
您每次都会将一长串项目加载到内存中吗?我认为 egrep 或 grep 将是最好的方法。在 Linux 上,您的文件将保留在文件缓存中,并且结果将非常快,并且由于 egrep 将通过文件运行,因此并非每个 apache 线程都会在内存中拥有列表的副本。