Веб-сканирование в ширину, но не в глубину - PullRequest
0 голосов
/ 09 июля 2020

Я делаю свой первый поисковый робот, используя java и jsoup. Я нашел этот фрагмент кода, который работает, но не так, как я хочу. Проблема в том, что он фокусируется на глубине ссылок, но я хочу сканировать страницы по ширине. Потратьте некоторое время, пытаясь переработать код, сосредоточившись на широте, но он все равно идет слишком глубоко, начиная с первой ссылки. Есть идеи, как я могу ползать по ширине?

public class WebCrawlerWithDepth {
    private static final int MAX_DEPTH = 4;
    private HashSet<String> links;

    public WebCrawlerWithDepth() {
        links = new HashSet<>();
    }

    public void getPageLinks(String URL, int depth) {
        if ((!links.contains(URL) && (depth < MAX_DEPTH))) {
            System.out.println("Depth: " + depth + " " + URL);
                links.add(URL);

                Document document = Jsoup.connect(URL).get();
                Elements linksOnPage = document.select("a[href]");

                depth++;
                for (Element page : linksOnPage) {
                    getPageLinks(page.attr("abs:href"), depth);
               }
           }
       }
  

Ответы [ 2 ]

1 голос
/ 09 июля 2020

По сути, так же, как вы от глубины до ширины в алгоритми c кодировании, вам нужна очередь.

Добавьте каждую ссылку, которую вы извлекли, в очередь и извлекайте новые страницы в сканироваться из этой очереди.

Вот мой вариант вашего кода:

public class WebCrawlerWithDepth {

    private static final int MAX_DEPTH = 4;
    private Set<String> visitedLinks;
    private Queue<Link> remainingLinks;

    public WebCrawlerWithDepth() {
        visitedLinks = new HashSet<>();
        remainingLinks = new LinkedList<>();
    }

    public void getPageLinks(String url, int depth) throws IOException {
        remainingLinks.add(new Link(url, 0));
        int maxDepth = Math.max(1, Math.min(depth, MAX_DEPTH));
        processLinks(maxDepth);
    }

    private void processLinks(final int maxDepth) throws IOException {
        while (!remainingLinks.isEmpty()) {
            Link link = remainingLinks.poll();
            int depth = link.level;
            if (depth < maxDepth) {
                Document document = Jsoup.connect(link.url).get();
                Elements linksOnPage = document.select("a[href]");
                for (Element page : linksOnPage) {
                    String href = page.attr("href");
                    if (visitedLinks.add(href)) {
                        remainingLinks.offer(new Link(href, depth + 1));
                    }
                }
            }
        }
    }

    static class Link {

        final String url;
        final int level;

        Link(final String url, final int level) {
            this.url = url;
            this.level = level;
        }
    }
}
0 голосов
/ 09 июля 2020

Вместо того, чтобы выполнять итерацию непосредственно по ссылкам на текущей странице, вам нужно сохранить их в Queue. Здесь должны храниться все ссылки для посещения со всех страниц. Затем вы получите следующую ссылку из Queue для посещения.

...