使用Python批量下载网站PDF遇权限错误的技术求助
解决批量下载PDF时的Permission Denied错误
我看了你这段批量下载NERC网站PDF的代码,遇到的IOError: [Errno 13] Permission denied: u'/trademark policy'问题其实很好定位——问题出在你直接用链接的文本作为文件名保存。
错误原因分析
当你用l.text作为文件名时,遇到了像/trademark policy这样的文本,其中的/在操作系统里是路径分隔符。系统会误以为你要在根目录(比如Unix的/或者Windows的C:/)创建名为trademark policy的文件,但普通用户根本没有根目录的写入权限,所以直接触发了权限拒绝错误。另外还有个隐藏问题:你用"w"模式写入PDF文件,这是文本模式,而PDF是二进制文件,这样写出来的文件大概率会损坏打不开。
修复方案
我们需要做两个关键修改:清理文件名里的非法字符,改用二进制模式写入文件。下面是修改后的完整代码和细节说明:
import mechanize from time import sleep br = mechanize.Browser() br.open('http://www.nerc.com/comm/CCC/Pages/AgendasHighlightsandMinutes-.aspx') f = open("source.html", "w") f.write(br.response().read()) filetypes = [".pdf"] myfiles = [] for l in br.links(): for t in filetypes: if t in str(l): myfiles.append(l) def downloadlink(l): # 清理文件名中的非法字符:替换路径分隔符和其他不允许的字符为下划线 safe_filename = l.text.replace('/', '_').replace('\\', '_').replace(':', '_').replace('?', '_').replace('"', '_').replace('<', '_').replace('>', '_') # 处理空文件名的情况,避免创建无效文件 if not safe_filename.strip(): safe_filename = f"unnamed_pdf_{hash(l.url)}.pdf" # 确保文件名以.pdf结尾,防止有些链接文本不带后缀 if not safe_filename.lower().endswith('.pdf'): safe_filename += '.pdf' # 用二进制模式写入PDF文件,避免文件损坏 with open(safe_filename, 'wb') as f: br.click_link(l) f.write(br.response().read()) print(f"{safe_filename} 已成功下载") for l in myfiles: sleep(1) downloadlink(l)
关键修改点说明
- 清理非法字符:把
/、\、:这些操作系统不允许出现在文件名里的字符全部替换成下划线,确保系统把它当成普通文件名而非路径。 - 二进制写入:用
wb模式打开文件,这是保存二进制文件(比如PDF、图片)的正确方式,能避免文件内容损坏。 - 健壮性处理:添加了空文件名判断和自动补全
.pdf后缀的逻辑,避免因为链接文本异常导致的下载失败。
这样修改后,不仅能解决权限拒绝的问题,还能保证下载的PDF文件正常可用。
内容的提问来源于stack exchange,提问作者Pela647




