Как рекурсивно получать веб-ссылки, не достигая максимальной глубины рекурсии

#python #recursion #beautifulsoup

#python #рекурсия #beautifulsoup

Вопрос:

Я уже некоторое время обдумываю эту проблему, для личного проекта мне нужно получить любую ссылку с указанных начальных веб-страниц, которая не является внешней ссылкой, т.Е. Не покидает исходный веб-сайт.
Я уже использую bs4 для очистки веб-страниц от ссылок, однако я не могу найти способ продолжать делать это для каждой очищенной ссылки, не достигнув в конечном итоге максимальной глубины рекурсии.
Моя предыдущая попытка состояла из чего-то вроде этого:

 link_list = []
link_buffer = ["www.example.com"]

def get_links(current_link):
    new_links = []
    soup = BeautifulSoup(current_link, "html.parser")
    for link in soup.find_all("a"):
        if link.has_attr("href"):
            ... # check here if the link does not leave the website
            new_links.append(link)
    return new_links

def get_all_the_links(list_of_links):
    target = list_of_links.pop()
    link_list.append(target)
    ...
    for link in get_links(target):
         ...
         if link not in link_list:
             list_of_links.append(link)
    
    if list_of_links.len() != 0: # recursiveness
        get_all_the_links(list_of_links)
    
get_all_the_links(link_buffer)
  

Я также просмотрел scrapy, однако нашел его слишком сложным для того, что я пытаюсь сделать, поскольку я просто планирую сохранить эти ссылки в текстовый файл, а затем обработать их позже.

Комментарии:

1. Проблема, скорее всего, в циклических ссылках. Представьте, что страница A указывает на страницу B, а страница B указывает на страницу A. Тогда ваш алгоритм будет вечно переключаться между страницами A и B. Быстрое исправление: поддерживайте набор already_visited и посещайте только те ссылки, которые вы еще не посетили.

2. Извините, у меня уже есть нечто подобное, и я отредактировал свой код, чтобы отразить это. Я считаю, что моя главная проблема заключается в том, что сайт, который я хочу просмотреть, на самом деле очень большой, поэтому мне нужен более сложный подход, чем просто сканирование по нему.

3. Не используйте рекурсию. Используйте бесконечный while цикл, который принимает URL-адрес из list или Queue , пока он не станет пустым. Когда вы анализируете каждую страницу и находите новые URL-адреса, добавляйте их в список / очередь. Как упоминал Stef , вам нужно отслеживать URL-адреса, которые вы посетили, чтобы не застрять в цикле. Вам также потребуется нормализовать URL-адреса. Смотрите en.wikipedia.org/wiki/URI_normalization

Ответ №1:

Приведенный вами пример кода немного запутан. Но в целом вам просто нужна дополнительная переменная хранилища для посещенных ссылок и проверьте, известна ли ссылка уже раньше

 visited_links = set()
...

def get_all_the_links(list_of_links):
    target = list_of_links.pop()
    if target in visited_links:
         # Ignore the current link and move on to next one.
         get_all_the_links(list_of_links)
    else:
         visited_links.add(target)
         ...
         # process link here...
         ...