MakeSiteMap.py テクニカルドキュメント
プログラムの動作
MakeSiteMap.py は、指定されたウェブサイトをクロールし、その構造を視覚的に分かりやすいHTML形式のサイトマップツリービューとして出力するPythonスクリプトです。このプログラムは、以下の主要な機能を通じてウェブサイトの構造分析を支援します。
ウェブサイトのクロール: 指定されたルートURLから出発し、同一ドメイン内のリンクを再帰的にたどってウェブページを収集します。
メタデータの抽出: 各クロールされたページからHTMLタイトル (
<title>タグの内容) と最終更新日 (Last-ModifiedHTTPヘッダーがあれば) を抽出・記録します。URLのフィルタリング:
特定のファイル拡張子(例:
.pdf,.jpg,.zipなど)を持つURLを自動的に除外する機能があります。これにより、HTMLコンテンツ以外の不必要なリソースがサイトマップに含まれるのを防ぎます。ユーザー定義の正規表現パターンに基づいて、特定のパスやクエリパラメータを含むURLを除外することができます。これにより、開発用ページやデータベースへのリンクなど、サイトマップに含めたくない部分を細かく制御できます。
階層的なサイトマップの生成: 収集したURLとそのメタデータに基づき、ウェブサイトのディレクトリ構造を模倣した階層的なツリービュー(HTML
<details>要素を使用)を生成します。これにより、ウェブサイト全体の構造を一目で把握しやすくなります。インタラクティブな表示: 生成されるHTMLサイトマップは、Tailwind CSSを用いてスタイリングされており、各ディレクトリ(パス)を展開・折りたたむことができるインタラクティブなUIを提供します。
このプログラムは、ウェブサイトの構造が複雑で全体像を把握しにくい場合や、SEOの観点からサイト構造を見直したい場合、あるいはサイトのアクセシビリティを評価する際などに非常に有用です。
原理
MakeSiteMap.py は、Webクローラとして機能し、以下のアルゴリズムと技術を利用してサイトマップを生成します。
URLの初期設定と引数処理:
プログラムは、デフォルトのルートURL、出力ファイル名、ファイル除外設定を持ちます。
コマンドライン引数でこれらの設定を上書きすることが可能です。
Webクローリング (Depth-First Searchに類似):
crawl_recursive関数が再帰的に呼び出され、指定されたstart_urlからクローリングを開始します。visitedセットを用いて、既にクロール済みのURL(フラグメントを除去し正規化されたURL)を記録し、無限ループや重複クロールを防ぎます。HTTP GETリクエストには
requestsライブラリを使用します。レスポンスのステータスコードが200(成功)でない場合や、フェッチ中にエラーが発生した場合は、そのURLの処理をスキップします。
URLの正規化とフィルタリング:
normalize_url関数は、urllib.parseモジュールを使用してURLを解析し、URLのフラグメント(例:#section)を除去して正規化します。これにより、同じコンテンツを指す異なるURLが重複してクロールされるのを防ぎます。is_target_url関数は、URLのパスに基づいて、.htmlや.shtml以外のファイル拡張子を持つURL(EXCLUDE_FILESがTrueの場合)を除外します。is_excluded_path関数は、正規表現で定義された除外パターン (EXCLUDE_PATHS) にURLのパス(クエリパラメータも含む)がマッチするかどうかをチェックし、マッチする場合はそのURLをクロール対象から除外します。
コンテンツの解析とメタデータ抽出:
requestsで取得したバイナリコンテンツの文字コードはcharset_normalizer.detectを使用して自動的に判別され、適切なエンコーディングで文字列にデコードされます。clean_html_content関数は、取得したHTMLコンテンツから余分な改行やスペースを削除し、解析しやすい形に整形します。get_page_title関数は、正規表現r"<title>(.*?)</title>"を使用してHTMLコンテンツから<title>タグの内容を抽出し、ページのタイトルとして利用します。HTTPレスポンスヘッダーに
Last-Modifiedが存在する場合、その日付を解析し、サイトマップの最終更新日として記録します。
リンクの抽出:
find_urls_in_html関数は、正規表現r"url:\s*[\"']([^\"']+)[\"']|href=[\"']([^\"']+)[\"']|src=[\"']([^\"']+)[\"']"を使用して、HTMLコンテンツ内のhref,src,url()属性からすべての潜在的なリンクを抽出します。抽出されたリンクは、
urljoinを使用して絶対URLに変換されます。クロール中のページのベースドメインと一致するURLのみが、さらに処理されます。
階層構造の構築:
build_hierarchy_dict関数は、クロールによって収集されたフラットなURLとメタデータのリストを受け取り、これをパスに基づいた階層的な辞書構造に変換します。URLのパス(クエリパラメータも含む)を
/で分割し、各セグメントを辞書のキーとしてネストすることでツリー構造を表現します。最終的なURLはリーフノードとして、そのタイトルや最終更新日と共に保存されます。
HTMLサイトマップの生成:
render_tree関数は、構築された階層辞書を再帰的にトラバースし、HTMLの<details>,<summary>,<ul>,<li>要素を組み合わせて、折りたたみ可能なツリービューを生成します。ディレクトリ(パスセグメント)は
<details>と<summary>で表現され、展開・折りたたみ機能を提供します。個々のページ(URL)は
<li>要素で表示され、そのタイトル、元のURLへのリンク、および最終更新日が含まれます。generate_html_sitemap_tree関数は、上記のHTMLツリーとTailwind CSSを用いたスタイルを含む完全なHTML5文書を構築し、指定された出力ファイルに保存します。
このように、MakeSiteMap.py は標準的なWebクローリングとHTML解析の技術を組み合わせ、Webサイトの構造をインタラクティブな形式で可視化する強力なツールです。
必要な非標準ライブラリとインストール方法
MakeSiteMap.py の実行には、以下の非標準Pythonライブラリが必要です。
requests: HTTPリクエストを送信するために使用されます。charset_normalizer: Webページコンテンツの文字コードを自動的に判別するために使用されます。
これらのライブラリは、Pythonのパッケージ管理システムである pip を使って簡単にインストールできます。コマンドラインで以下のコマンドを実行してください。
pip install requests charset-normalizer
必要な入力ファイル
このプログラムは、特別な入力ファイルを必要としません。 クロールの開始点となるルートURLは、コマンドライン引数として直接指定されます。引数が指定されない場合は、プログラム内にハードコードされたデフォルトのURLが使用されます。
生成される出力ファイル
MakeSiteMap.py は、以下の種類の出力ファイルを生成します。
ファイル名: デフォルトでは
sitemap.htmlですが、コマンドライン引数で変更可能です。内容: ウェブサイトの階層的な構造を示すHTML形式のサイトマップツリービューです。
HTML5形式の文書として記述されます。
Tailwind CSSフレームワークを用いてスタイリングされ、見た目が整理されています。
各ディレクトリやサブパスは
<details>および<summary>タグで囲まれ、展開・折りたたみが可能です。各ページ(URL)は
<li>タグでリスト表示され、以下の情報が含まれます。ページのタイトル
元のURLへのリンク (
target="_blank"で新しいタブで開きます)URLのパス部分(クエリパラメータも含む)
最終更新日 (HTTPヘッダーから取得できた場合)
Webブラウザでこのファイルを開くことで、サイトの構造をインタラクティブに探索できます。
コマンドラインでの使用例 (Usage)
MakeSiteMap.py は、以下の形式でコマンドラインから実行できます。
python MakeSiteMap.py [RootURL] [OutputFile] [ExcludeFiles(True/False)]
RootURL: クロールを開始するウェブサイトのルートURLを指定します。例:
http://example.com/省略した場合、プログラム内のデフォルトURLが使用されます。
OutputFile: 生成されるHTMLサイトマップのファイル名を指定します。例:
my_site_map.html省略した場合、デフォルトで
sitemap.htmlが使用されます。
ExcludeFiles(True/False): HTML以外のファイルをサイトマップから除外するかどうかを設定します。True(または1,t):.pdf,.jpg,.zipなどの一般的なファイル拡張子を持つURLを除外します。False(または0,f): すべてのファイル拡張子を持つURLを含めます(ただし、EXCLUDE_PATHSによる除外は適用されます)。省略した場合、デフォルトで
Trueが使用されます。
コマンドラインでの具体的な使用例
1. デフォルト設定での実行
最もシンプルな実行方法です。プログラムにハードコードされているデフォルトのルートURLをクロールし、sitemap.html を生成します。
python MakeSiteMap.py
実行結果の説明:
デフォルトで設定されている http://d2mate.mdxes.iir.isct.ac.jp/D2MatE/D2MatE_programs.html?page=statistcs をルートURLとしてクロールが開始されます。クロール中に取得されたHTML以外のファイルは除外され、最終的に sitemap.html という名前で、クロールされたページのタイトル、URL、最終更新日を含む階層的なサイトマップファイルが生成されます。
2. 特定のルートURLと出力ファイルを指定する
独自のウェブサイトのサイトマップを作成したい場合など。
python MakeSiteMap.py "https://www.python.org/" "python_sitemap.html"
実行結果の説明:
https://www.python.org/ をルートURLとしてクロールが開始されます。クロール中にHTML以外のファイルは除外され、結果は python_sitemap.html というファイルに保存されます。このHTMLファイルには、Python公式サイトの構造がツリービューで表示されます。
3. ファイル除外設定を無効にして実行する
サイトマップに画像やPDFなどの非HTMLファイルへのリンクもすべて含めたい場合。
python MakeSiteMap.py "http://example.com/blog/" "blog_full_sitemap.html" False
実行結果の説明:
http://example.com/blog/ をルートURLとしてクロールが実行されます。この際、False が指定されているため、画像 (.jpg, .png) やPDF (.pdf) など、通常除外されるファイル拡張子を持つURLもサイトマップに含められます。生成されたサイトマップは blog_full_sitemap.html として保存され、Webサイト内のあらゆる種類のファイルへのリンクが表示されます(ただし、EXCLUDE_PATHSによる除外は引き続き適用されます)。