如何自动从古腾堡项目下载书籍?代码无输出问题排查
排查并修复古腾堡书籍自动下载代码的问题
我来帮你一步步找出代码的问题,解决无输出无报错的情况:
核心问题分析
你的代码之所以没有任何输出,最关键的原因是正则表达式匹配不到内容,后续的循环逻辑根本没有执行起来,再加上宽泛的异常捕获,掩盖了其他潜在问题。下面是具体问题和修复方案:
1. 正则表达式匹配错误
你在get_content里用了<和>来匹配HTML标签,但requests.get返回的是原始HTML文本(比如<span class="mw-headline">),而非转义后的实体字符,导致这个正则完全匹配不到任何内容,content变成空列表,循环直接跳过。
2. 异常处理过于宽泛
try-except直接捕获所有异常且无日志输出,就算中间有错误也无法察觉,不利于排查问题。
3. 书籍名称未清理冗余字符
get_book_name提取的内容包含>和</a>这类多余字符,直接作为文件名会引发问题。
4. 相对URL未拼接完整域名
页面里提取的书籍URL是相对路径(比如../ebooks/1342),需要和古腾堡的域名拼接成完整URL才能正常下载。
修复后的完整代码
import requests import re import os import urllib.request # 全局域名,用于拼接相对URL BASE_DOMAIN = "http://www.gutenberg.org" def get_response(url): # 添加超时和异常捕获,避免请求卡住 try: response = requests.get(url, timeout=10) response.raise_for_status() # 抛出HTTP错误 return response.text except requests.exceptions.RequestException as e: print(f"请求URL失败: {url}, 错误信息: {e}") return "" def get_content(html): # 修改正则,匹配原始HTML标签,而非转义实体 reg = re.compile(r'<span class="mw-headline".*?</span></h2><ul><li>.*?</a></li></ul>', re.S) return re.findall(reg, html) def get_book_url(response): reg = r'a href="(.*?)"' urls = re.findall(reg, response) # 拼接完整URL return [BASE_DOMAIN + url if url.startswith('/') else BASE_DOMAIN + '/' + url for url in urls] def get_book_name(response): reg = re.compile(r'>(.*?)</a>') names = re.findall(reg, response) # 清理名称中的特殊字符,避免文件名错误 return [name.strip().replace('/', '_').replace('\\', '_') for name in names] def download_book(book_url, book_name): save_dir = "F:\\books" # 创建保存目录(如果不存在) if not os.path.exists(save_dir): os.makedirs(save_dir) # 生成保存路径,用清理后的书名 path = os.path.join(save_dir, f"{book_name}.html") try: if not os.path.exists(path): urllib.request.urlretrieve(book_url, path) print(f"成功下载: {book_name}") else: print(f"文件已存在: {book_name}") except Exception as e: print(f"下载失败: {book_name}, 错误信息: {e}") def get_url_name(start_url): html = get_response(start_url) if not html: return content_list = get_content(html) if not content_list: print("未匹配到任何书籍内容,请检查正则表达式或页面结构是否变化") return for content in content_list: book_urls = get_book_url(content) book_names = get_book_name(content) # 确保URL和名称数量对应 for url, name in zip(book_urls, book_names): download_book(url, name) def main(): start_url = 'http://www.gutenberg.org/wiki/Category:Classics_Bookshelf' get_url_name(start_url) if __name__ == '__main__': main()
关键修复说明
- 修正了
get_content的正则表达式,匹配原始HTML标签而非转义实体 - 新增了URL拼接逻辑,把相对路径转为完整可访问的URL
- 优化了书籍名称的提取和清理,避免文件名包含非法字符
- 添加了请求超时和详细的异常日志,方便排查问题
- 自动创建保存目录,避免路径不存在的错误
内容的提问来源于stack exchange,提问作者Manofsteel
相关产品推荐
相关产品推荐

