我在弄清楚如何从网络抓取工具中存储和扫描大量访问过的URL时遇到问题。这个想法是,访问过的URL的数量最终会存储在内存中太多,我应该将它们存储在文件中,但我想知道,这不会变得非常低效吗?如果获得一批URL并且我想检查URL是否已经访问过,我必须逐行检查访问过的文件并查看是否匹配?
我曾考虑使用缓存但是当在缓存中找不到URL时问题仍然存在,我仍然需要检查文件。我是否必须逐行检查每个URL的文件,是否有更好/更有效的方法来执行此操作?
答案 0 :(得分:4)
此处的关键数据结构可以是Bloom Filter,Guava提供实现。 Bloom-filter会告诉你(也许你已经访问了URL)或者你肯定没有。如果结果是,你可以去检查文件是否已经访问过,否则你去访问URL并将其存储在文件和Bloom过滤器中。
现在,要优化文件搜索,您可以散列URL以获得固定大小byte[]
而不是不固定的字符串长度(例如:md5)。
byte[] hash = md5(url);
if(bloomFilter.maybe(hash)){
checkTheFile(hash);
}else{
visitUrl(url);
addToFile(hash);
addToBloomFilter(hash);
}
当您检查密钥是否存在时,您可以使用数据库并使用哈希作为主键来获取O(1)
访问时间,或者您可以自己实现index。
答案 1 :(得分:0)
每个网址有一个文件怎么样?如果该文件存在,则已对该URL进行了爬网。
然后,您可以变得更复杂,并且此文件包含指示上次爬网结果的数据,您希望在下次爬网之前等待的时间等等。(例如,能够发现404s很方便)并决定是再次尝试还是放弃该URL。)
使用这种方法,值得对URL进行规范化,以便URL中的微小差异不会导致不同的文件。
我在我的节点爬虫(https://www.npmjs.com/package/node-nutch)中使用了这种技术,它允许我将状态存储在文件系统(用于简单爬网)或S3(用于涉及多个服务器的爬网)中