leetcode
leetcode 1101 ~ 1150
网络爬虫

网络爬虫

难度:

标签:

题目描述

代码结果

运行时间: 172 ms, 内存: 0.0 MB


/*
 * LeetCode 1236: Network Crawler
 * Using Java Streams to perform the crawling operation. The approach is similar to the BFS method but leverages Streams to process the URLs.
 */

import java.util.*;
import java.util.stream.*;

interface HtmlParser {
    List<String> getUrls(String url);
}

public class Solution {
    public List<String> crawl(String startUrl, HtmlParser htmlParser) {
        String hostName = getHostName(startUrl);
        Set<String> visited = Collections.synchronizedSet(new HashSet<>(Collections.singleton(startUrl)));
        Queue<String> queue = new LinkedList<>(visited);
        while (!queue.isEmpty()) {
            String currentUrl = queue.poll();
            List<String> newUrls = htmlParser.getUrls(currentUrl).stream()
                .filter(url -> url.contains(hostName) && visited.add(url))
                .collect(Collectors.toList());
            queue.addAll(newUrls);
        }
        return new ArrayList<>(visited);
    }

    private String getHostName(String url) {
        return url.split("/")[2]; // Splitting by '/' and taking the 3rd element which is the host name
    }
}

解释

方法:

本题解采用广度优先搜索(BFS)策略来遍历所有与起始URL具有相同域名的网页。首先,定义一个队列来存储待访问的URL,并将起始URL加入队列和已访问集合。然后,从队列中逐个取出URL,利用HtmlParser的getUrls方法获取该URL页面上的所有链接。对于每个链接,如果它未被访问过且域名与起始URL相同,就将其加入队列和已访问集合。最终,返回已访问集合中的所有URL,即为所有可达的同域名URL。

时间复杂度:

O(N*M)

空间复杂度:

O(N)

代码细节讲解

🦆
在广度优先搜索中,如何确保不会访问到与起始URL域名不同的网页?
在广度优先搜索(BFS)的实现中,我们通过对每个新发现的URL进行域名检查来确保只访问与起始URL域名相同的网页。具体方法是,定义一个辅助函数 `get_domain_name` 用于从URL中提取域名,然后在将URL添加到队列之前,比较其域名与起始URL的域名是否相同。只有当域名相同时,该URL才会被加入队列和已访问集合。这样可以有效防止访问到不同域名的网页。
🦆
对于HtmlParser的getUrls方法,它是否能保证总是返回所有有效的链接,或者有可能返回无效或不可访问的链接?
HtmlParser的getUrls方法的行为依赖于其具体实现。一般而言,我们假设它返回页面上的所有链接(包括相对链接和绝对链接),但不必然保证这些链接都是有效或可访问的。在实际应用中,返回的URL列表可能包含已经失效或无法访问的链接,因此在实际使用中可能需要额外的错误处理或验证机制来确保链接的有效性。
🦆
在解析URL以获取域名时,如果URL格式不标准(如缺少协议头或以非标准形式出现),get_domain_name函数的行为如何?
如果URL格式不标准,如缺少协议头(例如,'http://'或'https://'),`get_domain_name`函数可能无法正确解析域名。在当前的实现中,函数通过分割URL字符串来获取域名,如果URL不符合预期的格式,这种简单的分割方法可能会导致错误或异常。因此,对于不标准或异常的URL格式,可能需要更健壮的解析策略,如使用正则表达式或专门的URL解析库来处理这种情况。
🦆
在BFS的实现中,有没有可能出现队列操作(如put和get)的性能瓶颈,特别是在处理大量URL时?
在处理大量的URL时,队列操作(如put和get)确实可能成为性能瓶颈。队列的大小可能迅速增长,尤其是在网页链接密集的情况下,这可能导致内存消耗大量增加。此外,频繁的队列操作可能影响总体性能。为了优化,可以考虑使用更高效的队列实现,例如使用并发队列(在多线程环境中),或者对URL进行批处理以减少队列操作次数。另外,使用更高效的数据结构(如双端队列)可能也有助于提升性能。

相关问题