Какие ссылки должны входить в sitemap?

Мне необходимо написать (без использования посторонних библиотек) генератор карты сайта.

Я написал код, но работает он не для всех сайтов. Проблема заключается в том, что при проходе по ссылкам появляются бесконечные рекурсии. На сайте www.sitemaps.org нету ни слова про то какие ссылки должны входить, а какие нет. Вопрос в том, какие ссылки явлеяются нужными для составления sitemap.xml?

import requests
import pprint
import re
import time
import threading
from bs4 import BeautifulSoup
from urllib.parse import urlparse, urljoin, urlunsplit, urlsplit
from xml.etree import cElementTree as ET
from functools import lru_cache


class SiteMap(object):
    def __init__(self, site):
        self.site = self.__secure(site)
        self.urls = list()
        self.hostname = ''
        self.regex = r"https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)"
        self.excluded_resources = (".epub", ".mobi", ".docx", ".doc", ".opf", ".7z", ".ibooks", ".cbr", ".avi", ".mkv", ".mp4", ".jpg", ".jpeg", ".png", ".gif" ,".pdf", ".iso", ".rar", ".tar", ".tgz", ".zip", ".dmg", ".exe")
    
    @lru_cache()
    def __get_urls_from_soup(self, soup):
        for sp in soup.find_all('a', href=True):
            link = sp.get('href')
            yield self.__get_absolute_url(link)

    def __secure(self, url):
        https_url = url.replace('http://', 'https://')

        with requests.Session() as session:
            response = session.get(https_url)
            if response.status_code == 200:
                return https_url
            else:
                return url

    def __get_absolute_url(self, url):
        if not url.startswith(self.site):
            return urljoin(self.site, url)
        else:
            return url

    def __is_signin_or_singup(self, url):
        link = urlparse(url)
        if 'login' in link.path or 'signup' in link.path or 'signin' in link.path:
            return True
        else:
            return False

    def __excluded_resources(self, url):
        for resource in self.excluded_resources:
            if url.endswith(resource):
                return True
        
        return False
    
    def __get_urls_from_site(self, url, urls):
        url = self.__get_absolute_url(url)
        response = None
        
        with requests.Session() as session:
            try:
                response = session.get(url)
            except requests.TooManyRedirects:
                response = session.get(url, allow_redirects=False)
            finally:
                if not response:
                    return urls
                elif response.status_code != 200:
                    return urls

        soup = BeautifulSoup(response.text, 'html.parser')

        for link in self.__get_urls_from_soup(soup):
            if link in urls or not link.startswith(self.site) or not re.fullmatch(self.regex, link) or self.__is_signin_or_singup(link) or self.__excluded_resources(link):
                continue
            
            with open(self.hostname, 'a', encoding='utf-8') as file:
                file.write(link + '\n')
            
            urls.append(link)
            urls = self.__get_urls_from_site(link, urls)
        
        return urls
    
    def create(self):
        urls = list()
        urls.append(self.site)

        parse = urlparse(self.site)
        self.hostname = parse.hostname

        self.urls = self.__get_urls_from_site(self.site, urls)
        pprint.pprint(self.urls)
    
    def save(self, filename):
        urlset = ET.Element("urlset", xmlns="http://www.sitemaps.org/schemas/sitemap/0.9")
        for url in self.urls:
            link = ET.SubElement(urlset, "url")
            ET.SubElement(link, "loc").text = url
        
        tree = ET.ElementTree(urlset)
        tree.write(filename)


if __name__ == '__main__':

    threads = dict()
    sitemaps = list()
        
    sites = [
        "http://crawler-test.com/",
        "http://google.com/",
        "https://vk.com",
        "https://yandex.ru",
        "https://stackoverflow.com"
    ]

    for site in sites:
        sitemap = SiteMap(site)
        thread = threading.Thread(target=sitemap.create)
        thread.start()  

        threads[thread.ident] = dict({
            'thread': thread,
            'time_start': int(time.time()),
            'time_end': 0})
        sitemaps.append(sitemap)

    for thread in threads:
        threads[thread]['thread'].join()
        threads[thread]['time_end'] = int(time.time())
        print(f"Time to process thread #{thread} is {threads[thread]['time_end'] - threads[thread]['time_start']}")
    
    for sitemap in sitemaps:
        sitemap.save(f"{sitemap.hostname}.xml")
        print(f"Count of urls {sitemap.hostname} is {len(sitemap.urls)}")
        

Сайты с которыми код работает - "http://crawler-test.com/", "http://google.com/", "https://vk.com"

Сайты с которыми я вхожу в бесконечную рекурсию - "https://yandex.ru", "https://stackoverflow.com"


Ответы (0 шт):