『追放された俺でも、サイトマップ更新で無双する件。』のソースコード全文です:
import tkinter as tk
from tkinter import filedialog, messagebox, scrolledtext
import os
import xml.etree.ElementTree as ET
from datetime import datetime
class SitemapUpdater:
def __init__(self, master):
self.master = master
self.master.title("Sitemap自動更新ツール - 追放された俺でも、サイトマップ更新で無双する件。")
self.sitemap_path = ""
self.folder_path = ""
# パス表示ラベル
self.label_sitemap = tk.Label(master, text="sitemap.xml: 未選択", anchor="w", wraplength=600)
self.label_sitemap.pack(fill="x", padx=10, pady=2)
self.label_folder = tk.Label(master, text="対象フォルダ: 未選択", anchor="w", wraplength=600)
self.label_folder.pack(fill="x", padx=10, pady=2)
# 操作ボタン
tk.Button(master, text="XMLファイルを選択", command=self.load_sitemap).pack(pady=4)
tk.Button(master, text="フォルダを選択", command=self.select_folder).pack(pady=4)
tk.Button(master, text="更新・保存", command=self.update_sitemap).pack(pady=10)
# ステータス表示欄
self.status_text = scrolledtext.ScrolledText(master, height=12, wrap=tk.WORD)
self.status_text.pack(fill="both", expand=True, padx=10, pady=5)
def log(self, message):
"""ステータスログに出力"""
timestamp = datetime.now().strftime("[%H:%M:%S] ")
self.status_text.insert(tk.END, timestamp + message + "\n")
self.status_text.see(tk.END)
def load_sitemap(self):
path = filedialog.askopenfilename(filetypes=[("XML files", "*.xml")])
if path:
self.sitemap_path = path
self.label_sitemap.config(text=f"XMLファイル: {path}")
self.log("XMLファイルを選択しました。")
def select_folder(self):
folder = filedialog.askdirectory()
if folder:
self.folder_path = folder
self.label_folder.config(text=f"対象フォルダ: {folder}")
self.log("対象フォルダを選択しました。")
def update_sitemap(self):
if not self.sitemap_path or not self.folder_path:
messagebox.showwarning("エラー", "XMLファイルとフォルダの両方を選択してください。")
return
self.log("XMLファイルを読み込み中...")
tree = ET.parse(self.sitemap_path)
root = tree.getroot()
ns = {'ns': 'http://www.sitemaps.org/schemas/sitemap/0.9'}
ET.register_namespace('', ns['ns'])
updated = False
updated_count = 0
for url in root.findall("ns:url", ns):
loc = url.find("ns:loc", ns)
lastmod = url.find("ns:lastmod", ns)
if loc is not None and lastmod is not None:
url_path = self.url_to_path(loc.text)
full_path = os.path.join(self.folder_path, url_path)
if os.path.isfile(full_path):
file_time = os.path.getmtime(full_path)
file_dt = datetime.fromtimestamp(file_time)
try:
lastmod_dt = datetime.fromisoformat(lastmod.text.replace("Z", "+00:00")).replace(tzinfo=None)
except ValueError:
self.log(f"⚠ 日付形式不正: {lastmod.text}")
continue
if file_dt > lastmod_dt:
lastmod.text = file_dt.strftime("%Y-%m-%dT%H:%M:%S+00:00")
self.log(f"✅ 更新: {url_path}")
updated = True
updated_count += 1
else:
self.log(f"🟢 最新です: {url_path}")
else:
self.log(f"⚠ ファイルが見つかりません: {url_path}")
if updated:
now = datetime.now().strftime("%Y%m%d-%H%M%S")
save_path = os.path.join(os.path.dirname(self.sitemap_path), f"sitemap-{now}.xml")
tree.write(save_path, encoding="utf-8", xml_declaration=True)
self.log(f"💾 {updated_count} 件更新し、保存しました: {save_path}")
messagebox.showinfo("保存完了", f"{updated_count} 件の<lastmod>を更新し、保存しました。")
else:
self.log("🔍 すべてのファイルが最新の状態です。")
messagebox.showinfo("更新不要", "すべてのファイルが最新の状態です。")
def url_to_path(self, url):
"""URLからファイルパスを抽出(例: https://example.com/a/b.html → a/b.html)"""
parts = url.split("://")[-1].split("/", 1)
return parts[1] if len(parts) > 1 else ""
if __name__ == "__main__":
root = tk.Tk()
##タイトルバーアイコン表示用
data = '''R0lGODdhEAAQAIcAAOStRN6lPdyiOtmeONidN9ebNtaZNdSYNNCTMdCQLsiLLceJLMaHKsSFKsCCKcCBKb1+KLx+KL1+Jbx8I7Z6J7d4JLZ3I7R3JLN3JrV2IrF1JLR0ILJ0JbJ0JLJ0IqxvI6tvIapvIqpvIadrHqBmIJ9mHp9lHZxlH6BkG5tjH5tjHJphHJRhIZRhIJlgGphfGZVfG5RgHpNfHZNfHJZeGpNdHZVcG5FeHpFdH5BbGo9aG45aHIlaIJBZF4lWG4pTFohVGIRTG4ZSF4ZSFYJRF4JPFIFPF3xNGIBJD3xKFHpLFXlIE3xHEHhHE3dDDnZEEG5BEWlEGW1BEWxBEmw/EGk9DWg9EGg9D2w8DWc8EGU7DFw2DWE1C1w1DVU1EFo0DlYyDVUyDFcxDFUxC1ExDU8wD08uC0wtDEosDEktD0csDlQqBVQqBE4nBU4nBEsnBkoqC0cqDEcoCkUqDEIoDEEpD0EoDEApDz8oDkAnDj4qEzopFDooEzkoEz4nDj0nDkcjA0ElCUEiBkMhAz8mDDwlDDomDzkmEDklDTkkDjcmEzYmEjgkDjYjDTQjDzMjDzMiDjMhDTIkEzIiEDAhDzAhDi8kEyshEjEgDDAgDS4gDy4gDiwgDy4fDi4fDS0fDiofETceBzUdBjEdBy8cByweDiweDSweDCseDSscCioeDikeDyodDikdDykdDSocDCkcDSkcDDEbBjAaBisZBi0YBSsXBSgaCigXBigWBSgWBCcfEiceEScdECYdECYdDyccDiccDSccDCUcDyMcECIcEScbDCcbCyUbDCQbDiMbDyIbDyEbECQaDSQaDCMaDiIaDyEaDyYZCSMZDSIZDSIYCiEYDCEYCycWBSYVBCIXCSIWByAZDh8ZDx8XDB8XCh0ZEB0ZDx4YDR0YDxwYDhsYDx4XDB0XDRwXDRsXDh0VChwVChoWDgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAEAAQAEAI/wDLhSu2y5IiPnr29JF0iZcybul8OVJTRYQDBAEADGBQoceYO5WgBZOmS9CbNmvYuAE0KBCkTcCiwfI0So6PHDReuFBxooaXV826/fpUiMcNGTNgxGjBIgqrYNyIqcKExkgKDBEeQPhg48qcSa2UbcJDRsgKEBUmbEDxQ8oZRK7Qmbu2DZesWbVs5dKVDdstY9bGLQO16FCdNGXKqMmTSNOqZ+TADUslCgcHDRYyeAhB4kgmU8mYwdJGCs4XKE2SLLEiJg4jTsN8UfqzpQQFBQUEHGjQoYgZQ516PVKjxcSFBQYIJJAwYkgYP56ilWpEJwuVJ0yQOMHCBYydSFCdHSOjFSrIDh1AiCiZ0oVQrGnsznlbp+5bNWOoTJ0SdgwZNXEBAQA7'''
root.tk.call('wm', 'iconphoto', root._w, tk.PhotoImage(data=data))
####
app = SitemapUpdater(root)
root.mainloop()