#!/usr/bin/env python3 """ Phase 1: 获取所有诗人列表 从 A-Z 分页抓取所有诗人 """ import json import requests import re import os from datetime import datetime from time import sleep CONFIG_DIR = os.path.join(os.path.dirname(__file__), '..', 'config') INDEX_FILE = os.path.join(CONFIG_DIR, 'poets_index.json') BASE_URL = "https://www.public-domain-poetry.com" LETTERS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' DELAY = 5 # 秒 def fetch_letter_page(letter): """抓取单个字母页面的诗人列表""" url = f"{BASE_URL}/name.php?l={letter}&s=author" headers = { 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36' } print(f" 抓取字母 {letter}...") response = requests.get(url, headers=headers, timeout=30) response.raise_for_status() return response.text def parse_poets_from_html(html): """从 HTML 解析诗人列表""" poets = [] # 匹配诗人链接,slug 格式为小写字母和连字符,如 "a-h-laidlaw" # 排除 .php 文件和 /stories/ 路径 pattern = r']*>([^<0-9][^<]{2,50})' matches = re.findall(pattern, html, re.IGNORECASE) for slug, name in matches: # 清理 slug = slug.strip().lower() name = name.strip() # 过滤无效项 if len(name) < 3 or name in ['Home', 'Contact', 'Search']: continue # 跳过已经存在的 if not any(p['slug'] == slug for p in poets): poets.append({ 'slug': slug, 'name': name, 'url': f"{BASE_URL}/{slug}", 'status': 'pending', 'download_date': None, 'poems_count': 0 }) return poets def build_index(): """构建诗人索引(遍历 A-Z)""" index = { 'fetch_date': datetime.now().isoformat(), 'source_url': BASE_URL, 'letters': LETTERS, 'poets': [] } all_poets = [] for i, letter in enumerate(LETTERS, 1): print(f"\n[{i}/26] 处理字母 {letter}") try: html = fetch_letter_page(letter) poets = parse_poets_from_html(html) print(f" ✅ 找到 {len(poets)} 个诗人") all_poets.extend(poets) except Exception as e: print(f" ❌ 错误: {e}") # 延迟(除了最后一个) if i < len(LETTERS): sleep(DELAY) # 去重(按 slug) seen = set() unique_poets = [] for poet in all_poets: if poet['slug'] not in seen: seen.add(poet['slug']) unique_poets.append(poet) index['poets'] = unique_poets return index def save_index(index): """保存索引""" os.makedirs(os.path.dirname(INDEX_FILE), exist_ok=True) with open(INDEX_FILE, 'w', encoding='utf-8') as f: json.dump(index, f, indent=2, ensure_ascii=False) print(f"\n💾 索引已保存: {INDEX_FILE}") print(f"📊 总计: {len(index['poets'])} 个诗人") def main(): # 检查是否已有索引 if os.path.exists(INDEX_FILE): print(f"⚠️ 索引文件已存在: {INDEX_FILE}") with open(INDEX_FILE, 'r', encoding='utf-8') as f: existing = json.load(f) print(f" 上次更新: {existing.get('fetch_date')}") print(f" 诗人数量: {len(existing.get('poets', []))}") response = input("\n是否重新获取? (y/N): ") if response.lower() != 'y': print("👋 保持现有索引") return # 获取并保存 print("\n🔍 开始抓取诗人列表...") print(f"⏱️ 预计时间: {len(LETTERS) * DELAY // 60} 分钟\n") index = build_index() save_index(index) print("\n✅ Phase 1 完成") print("下一步: 运行 download_poems.py 开始下载诗歌") if __name__ == '__main__': main()