サイトマップって、作るのは自動が良いですよね。

で、作るのも面倒なんで、Geminiと相談してこんなん作成しました。

引数に、作りたい URL をセットすることで、適当なサイトマップが出力されます。

指定URLに対して、前方一致するものだけを対象にしますよ。

 

#!/usr/bin/python3

import sys
import requests
from bs4 import BeautifulSoup
import xml.etree.ElementTree as ET
import argparse

def is_internal_link(url, site_base_url_prefix):
    """
    URL が指定されたプレフィックスで始まるか判定する(非推奨な場合あり)。

    Args:
        url (str): 判定したい絶対URL文字列(urljoinで変換済みを想定)。
        site_base_url_prefix (str): 自サイトの正確な開始プレフィックス(例: 'https://www.your-site.com/')。

    Returns:
        bool: 内部リンクとみなせれば True、そうでなければ False。
    """
    # urljoin で絶対URLに変換された後の url を想定
    if url.startswith(site_base_url_prefix):
        # ただし、フラグメント (#...) や mailto:, tel: などは別途除外が必要
        if '#' in url or url.startswith('mailto:') or url.startswith('tel:'):
             return False
        return True
    else:
        return False

def recursive_crawl_site(site_domain, url, visited):
    if url in visited:
        return [] # すでに訪れたURLなら処理しない

    visited.add(url)
    all_urls = [url] # このURL自体も収集    
    
    try:
        response = requests.get(url)
        response.raise_for_status()
        soup = BeautifulSoup(response.content, 'html.parser')

        for link in soup.find_all('a', href=True):
            href = link['href']
            next_url = requests.compat.urljoin(url, href)

            # ここで自サイト内リンクか判定し、必要なら正規化・フィルタリング
            # is_internal_link 関数を仮定
            if is_internal_link(next_url, site_domain) and next_url not in visited:
                 # 再帰呼び出し
                all_urls.extend(recursive_crawl_site(site_domain, next_url, visited))

    except requests.exceptions.RequestException as e:
        print(f"Error crawling {url}: {e}", file=sys.stderr)
        # エラー時も再帰は停止しない(設計による)

    return all_urls    

def generate_sitemap_xml(urls):
    urlset = ET.Element('urlset', xmlns="http://www.sitemaps.org/schemas/sitemap/0.9")

    for url in urls:
        url_element = ET.SubElement(urlset, 'url')
        loc = ET.SubElement(url_element, 'loc')
        loc.text = url
        # 必要に応じて <lastmod>, <changefreq>, <priority> を追加

    # XML宣言を追加して整形
    tree = ET.ElementTree(urlset)
    ET.indent(tree, space="  ") # 整形
    return ET.tostring(urlset, encoding='utf-8', xml_declaration=True)


# オプション処理
TARGETURL = "https://hogehoge.domain.com/"

DEBUG = False
parser = argparse.ArgumentParser(description='using \n \nex)\n mksitemap.py "https://hogehoge.domain.com"')
parser.add_argument('url', help='url')
if DEBUG == False :
    args = parser.parse_args()
    TARGETURL=args.url

# 実行例
if __name__ == "__main__":
    site_url = TARGETURL
    visited = set()
    discovered_urls = recursive_crawl_site(site_url,site_url,visited)
    sitemap_xml_bytes = generate_sitemap_xml(discovered_urls)
    sitemap_xml_string = sitemap_xml_bytes.decode('utf-8')

    print(sitemap_xml_string)

 

Joomla templates by a4joomla