はてなブログの記事を別サイトに移行した後、旧記事を一括で非公開にしたいケースがあります。
注意点:下書きには戻せない はてなブログのAtomPub APIでは、公開済みの記事を下書き(draft)に戻すことはできません。PUTリクエストで <app:draft>yes</app:draft> を送ると 400 Cannot Change into Draft エラーになります。
そのため、以下の2つの方法があります。
方法1:記事本文を「移転しました」に書き換える AtomPub APIのPUTで記事の <content> を書き換えることは可能です。
import requests import xml.etree.ElementTree as ET import time HATENA_ID = "your_hatena_id" BLOG_ID = "your_blog_id.hatenablog.com" API_KEY = "your_api_key" NEW_SITE_URL = "https://your-new-site.com" ATOM_NS = "http://www.w3.org/2005/Atom" def fetch_all_entries(): entries = [] url = f"https://blog.hatena.ne.jp/{HATENA_ID}/{BLOG_ID}/atom/entry" while url: resp = requests.get(url, auth=(HATENA_ID, API_KEY), timeout=30) resp.raise_for_status() root = ET.fromstring(resp.text) for entry in root.findall(f"{{{ATOM_NS}}}entry"): title_el = entry.find(f"{{{ATOM_NS}}}title") title = title_el.text or "" if title_el is not None else "" edit_link = entry.find(f"{{{ATOM_NS}}}link[@rel='edit']") edit_url = edit_link.get("href") if edit_link is not None else None if edit_url: entries.append({"title": title, "edit_url": edit_url}) next_el = root.find(f"{{{ATOM_NS}}}link[@rel='next']") url = next_el.get("href") if next_el is not None else None return entries def replace_content(entry): title = entry["title"] update_xml = f"""<?xml version="1.0" encoding="utf-8"?> <entry xmlns="http://www.w3.org/2005/Atom" xmlns:app="http://www.w3.org/2007/app"> <title>{title}</title> <content type="text/plain">この記事は {NEW_SITE_URL} に移転しました。</content> </entry>""" resp = requests.put( entry["edit_url"], auth=(HATENA_ID, API_KEY), data=update_xml.encode("utf-8"), headers={"Content-Type": "application/atom+xml; charset=utf-8"}, timeout=30, ) return resp.status_code entries = fetch_all_entries() print(f"Found {len(entries)} entries") for i, e in enumerate(entries): status = replace_content(e) print(f"[{i+1}/{len(entries)}] {status}: {e['title'][:50]}") time.sleep(0.5) 方法2:はてなブログの管理画面から一括削除 記事数が少なければ、管理画面の「記事の管理」から手動で削除する方法もあります。ただし一括選択機能がないため、大量の記事には向きません。
...