教科书批量下载全指南:工具、脚本与版权边界详解

发布时间:2026/9/19 18:24:40
教科书批量下载全指南:工具、脚本与版权边界详解 教科书批量下载这件事我猜你不是第一次搜。新学期教材清单一下来一科一本电子课本加上配套的练习册、答案解析、教师用书一个学期攒下来十几本是常事上了大学更夸张一节课三四份PDF一门课几十个文件全手点下来光下载就能耗掉你一下午的耐心。但“批量下载”这四个字听着爽操作起来很容易踩线。有些资源公开免费、随便下有些需要账号登录、平台明确给了下载按钮还有一些只能在线看本质上就是一张张网页图片。这三种情况对应的方法完全不同版权边界也完全不同。所以我先把话说在前头这篇文章所有方法都建立在“你本来就有权访问和下载这些内容”的前提上。免费公开的电子课本、学校购买的电子教辅、出版社开放的样章随便操作付费墙后面、需要额外权限才能动的东西别琢磨技术手段去绕真需要就找学校图书馆或出版社走正规渠道。下面我把合法场景下的批量下载方法拆开讲从工具准备到实战脚本再到下完之后的文件整理一条龙说完。1. 先说清楚你手上的“教科书”是哪种数字形态1.1 整本PDF/EPUB型最省事的直接下载这是最理想的形态。出版社或平台把整本书做成一个PDF或者EPUB文件你只需要找到文件地址右键另存为或者用下载工具拉回来就行。这种形态的特点很明显URL末尾一般是.pdf、.epub、.png这样的静态文件后缀服务器响应头里带着Content-Type: application/pdf你在浏览器里打开链接地址栏不会变而且浏览器会直接进入PDF预览页面。遇到这种别用鼠标右键“另存为”一个个点。你可以直接复制文件地址扔给命令行工具批量拉取我后面会在第4节详细演示。整个过程不涉及任何“技巧”你要做的只是把链接列表抓下来。1.2 网页分页型看着像是书其实是一堆图片现在很多在线电子教材平台用这种形态。浏览器打开之后左侧是目录右侧是正文翻页时内容自动刷新但你在页面上点右键“图片另存为”很多平台的代码里做了处理你会发现根本存不下来就算用浏览器自带的保存网页得到的也是一堆网页壳子里面图片全是空的。原因很简单这种电子书不会把整本PDF塞给你而是把每一页渲染成一张图片按页码顺序从服务器加载。你看到的“第12页”本质就是一张page_012.jpg。这形态的好处是防盗版代价是你只能一页页看不能一把梭。对付这种形态思路就得换成“从浏览器网络请求里把图片地址抓出来再按顺序批量下载”。这不是什么黑科技你肉眼看到图片的那一刻这张图已经从服务器传到你电脑里了你要做的只是把它保存下来。1.3 扫描版PDF下载完不等于能用还有一种更常见的形态旧教材扫描版。一堆扫描图片合成了一个PDF里面没有复制粘贴的文字层搜索也搜不到。你辛辛苦苦下载下来打开一看是图片想圈重点还得靠手打。所以这种文件的下游工作往往是OCR识别文字。我后面会提到转PDF和补OCR层虽然它不是“下载”本身但没有这步下载完的教材实用价值会大打折扣。1.4 在动手之前先默背一遍哪些能下、哪些不能碰我把常见的教材数字资源分成三个区批量下载之前先对着看一眼资源类型例子能不能批量下载官方免费公开资源国家中小学智慧教育平台的电子课本、出版社免费开放样章没写明禁止下载的可以建议不过度并发已授权/已购买资源学校统一购买的电子书平台、图书馆数据库、自己买的电子书在服务条款允许范围内可下载通常仅限个人使用付费墙/防盗保护资源需要单独付费逐章解锁、限校内IP使用、带DRM版权保护原则上别碰找合法授权渠道这条分类建议你截图存一下。很多时候批量下载翻车不是技术不够是没想清楚第一类资源下得好好的手一滑把第二类第三类的也下了这就不是技术问题是合规问题了。2. 批量下载前的三个准备动作工具、权限与策略2.1 浏览器开发者工具是你最该练熟的基础功不管你打算用什么高级工具第一步都是同一个把浏览器开发者工具打开看网络请求。快捷键就三个Chrome/Edge是F12Mac上是CommandOptionI。打开后切到Network面板刷新一次页面你会看到一大堆请求刷屏。别慌我们只关心资源本身。在过滤框里输入.jpg或.png或者点Img标签就能看到页面加载了哪些图片。这一步的意义在于确认两件事。第一这个电子书的“书页”到底是不是图片第二图片URL有没有规律比如是不是按page_001.jpg、page_002.jpg这样递增。只有URL有规律你才能用脚本批量拉如果URL是乱的、无规律的一长串哈希值那你还得从页面接口里去找JSON数据那就是另一套玩法了。2.2 选工具三个量级各管一摊根据资源数量和复杂程度我一般把批量下载工具分成三个量级工具适合场景上手难度够用程度浏览器扩展如 DownThemAll几十个文件、链接是显式下载地址很低中等wget / curl 命令行一个网站目录下成百上千个静态文件链接有规律低很高Python 脚本requests BeautifulSoup/Selenium需要登录、需要动态渲染、要处理翻页和防盗链中高最高我的建议是不要一上来就写Python。能用wget解决的绝不多写三行代码。很多批量下载任务本质就是“给一个目录拿一个列表把文件拉下来”wget一条命令就干完了。只有当你发现浏览器里能看到图、但wget下不回来才需要上Python脚本带Cookie、带Referer、处理重试和复杂逻辑。2.3 先把下载清单整理成可执行的目标在写任何脚本之前先花五分钟想清楚你要下一百个文件还是十个文件文件名怎么规划下完之后放哪个目录。比如你负责帮老师整理下学期电子教材那目录结构建议直接按照“年级/科目”来2026春/ 三年级/ 语文_三年级下册.pdf 数学_三年级下册.pdf 四年级/ ...这一步看似多余其实作用巨大。批量下载最不缺的就是文件缺的是秩序。没有目录规划你下载完会发现Desktop里躺了一百多个文件名差不多的PDF分拣半天比手点下载还绝望。3. 从在线阅读器里“取图”分页式电子教材的整本备份3.1 定位图片地址从Network面板里找到“书页”的真实来源我把这个场景单拎出来讲因为它是教科书下载里最常见的卡点。你打开一个在线电子课本翻到第10页页面上显示的确实是一页书但右键保存图片却不行或者保存下来只有一小块图。这时候就要上开发者工具了。操作顺序是这样的打开电子书页面翻到某一页。按F12打开DevTools切到Network面板。在过滤框里输入page或者直接点图片类型过滤。刷新页面或翻一下页观察新增的请求。找到那张看起来像整页书的大图点击它在Headers里看完整URL。绝大多数情况下那个URL长这样https://example.edu.cn/book/ebook123/page_010.jpg?tokenxxx后半段的token不一定有用但核心规律来了page_010.jpg照着序号递增。知道了这个规律整本下载就变成“循环一百次请求”的问题了。3.2 用浏览器Console直接拉全本适合页面少、要求不高的场景偶尔只有十几页的电子教材我懒得开Python会直接在浏览器控制台里用一小段JavaScript把图片一张张“点”下来。思路是这样的先判断图片域名是否允许跨域访问。如果允许用fetch拿回来转成Blob再触发下载如果不确定最保守的方式是动态创建一个带download属性的a标签再把href指向图片地址。// 适用于图片URL有规律、且目录允许跨域访问的情况 const base https://example.edu.cn/book/ebook123/page_; const total 120; const delay 500; function sleep(ms) { return new Promise(resolve setTimeout(resolve, ms)); } async function downloadAll() { for (let i 1; i total; i) { const pageNum String(i).padStart(3, 0); const url ${base}${pageNum}.jpg; try { const resp await fetch(url); const blob await resp.blob(); const objectUrl URL.createObjectURL(blob); const a document.createElement(a); a.href objectUrl; a.download page_${pageNum}.jpg; document.body.appendChild(a); a.click(); a.remove(); URL.revokeObjectURL(objectUrl); console.log(ok: ${pageNum}); } catch (e) { console.error(fail: ${pageNum}, e); } await sleep(delay); } } downloadAll();这段脚本有几个前提你要想清楚。第一如果浏览器控制台报跨域错误那就说明服务器不允许你从当前页面直接抓图片二进制这个脚本跑不通。第二浏览器会询问“允许下载多个文件”你得手动点允许。第三没有进度条途中断了不会自动续传需要重跑。所以它只适合“临时救急”。教科书动辄上百页我强烈建议往下看Python方案。3.3 用Python做整本下载带重试、带防盗链、能断点续传我自己的主力方案是Python脚本。它有几个不可替代的优势可以不启用浏览器、直接模拟请求可以设置Referer和Cookie可以用time.sleep控制请求频率失败之后可以自动重试下载到一半断了可以检测到本地已有文件跳过重复。一个最简但能用的版本长这样import requests import time from pathlib import Path BASE_URL https://example.edu.cn/book/ebook123/page_{page:03d}.jpg HEADERS { Referer: https://example.edu.cn/book/ebook123.html, User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36, # 如果该页面需要登录把浏览器的Cookie完整复制到这里 # Cookie: session_idxxx; tokenyyy } OUT_DIR Path(./ebook123) OUT_DIR.mkdir(exist_okTrue) START, END 1, 120 RETRY_TIMES 3 for page in range(START, END 1): out_file OUT_DIR / fpage_{page:03d}.jpg if out_file.exists() and out_file.stat().st_size 0: print(fskip {page}, already exists) continue url BASE_URL.format(pagepage) for attempt in range(1, RETRY_TIMES 1): try: resp requests.get(url, headersHEADERS, timeout15) if resp.status_code 200: out_file.write_bytes(resp.content) print(fpage {page} ok, size{len(resp.content)}) break else: print(fpage {page} http {resp.status_code}) except Exception as e: print(fpage {page} attempt {attempt} error: {e}) time.sleep(2) time.sleep(0.5) # 绅士爬虫每页间隔0.5秒这里我特意做了三个细节都是平时容易踩的坑。第一个是Referer。很多图片服务器会做防盗链校验直接从脚本发请求没有来源页信息服务器会返回403或一张错误占位图。带上你在浏览器里看到的那个电子书页面地址作为Referer通常就解决了。第二个是重试机制。网络抖动在批量下载里一定会遇到不加重试脚本跑一半挂掉你都不知道断在第几页。第三个是断点续传。通过判断本地文件是否存在来跳过已下载的页面这样脚本跑崩了重新执行一次就行不用从头再来。3.4 页面需要登录怎么办把浏览器里的Cookie喂给脚本有些电子教材平台只允许登录用户阅读。你在浏览器里打开是正常的但requests直接访问会跳转到登录页或者返回一个空的JSON。遇到这种情况别去研究平台登录接口。最省事的方法是你自己在浏览器里登录一次然后从开发者工具的Network面板任选一个请求在Request Headers里找到Cookie字段整串复制出来填到脚本的HEADERS里。这招的关键在于理解Cookie的有效期。有的平台登录态能维持一个月有的几小时就失效。失效了没关系重新登录一次重新复制即可。整个过程完全是“用你已有的合法权限下载你有权看的内容”并没有碰任何技术限制。还有个小技巧如果下载中途发现某个页面的响应大小和其他页差特别多不要急着继续。拿这个URL到浏览器里打开看看十有八九是“当前访问已过期”或“图片已被清除”的提示页。此时停下来重新登录、更新Cookie再跑能省很多无用功。4. 链接列表式教材源一条命令把整站PDF拉回本地4.1 先判断这个站点是不是“允许批量下载的体质”不是所有教材站点都长一个样。有些站点本身就是下载站页面上满满的“点击下载”按钮这种站点往往是整本PDF的直接链接批量下载的思路和“取图”完全不同。判断方法很简单打开目录页看每个资源链接的URL。如果URL以.pdf、.zip、.rar这些文件扩展名结尾或者点击后出现的是文件下载不是在线阅读器那它就是一个“链接列表式”教材源。这种场景用wget效率最高。还有两种信号也可以留意一是目录页的HTML结构是否简单如果每一个教材条目都是一个a href...那么解析链接就是分分钟的事二是站点有没有提供robots.txt。虽然robots.txt不是法律强制但它至少告诉了你站点管理员的爬虫意图。我自己的原则是如果robots.txt里明确写了Disallow: /download/那我就不去碰那个目录这是基本的尊重。4.2 wget镜像命令的正确打开方式递归、层级、等待一个都不能少wget是Linux/macOS自带的下载工具Windows上装了Git Bash或者WSL也能用。很多人只知道wget url这个最基础用法其实它的镜像模式才是为“成批下载”设计的。假设目录页是https://example.org/books/下面有几十个PDF链接全部指向https://example.org/books/files/xxx.pdf你想把这些PDF全部拉回本地wget \ --recursive \ --level1 \ --no-parent \ --acceptpdf \ --wait2 \ --limit-rate200k \ --directory-prefix./textbooks \ https://example.org/books/这几个参数我逐个解释一下。--recursive开启递归下载让wget顺着页面里的链接继续爬--level1限制递归深度为1意思是我只下载这个页面里直接链接到的文件不再顺着那些文件里的链接继续往深处爬——不设这个限制很可能把整个网站都拖下来--no-parent防止它跑到上级目录去--acceptpdf只匹配PDF文件避免下载一堆无关HTML--wait2每次请求间隔2秒给对方服务器留点喘息空间--limit-rate200k限速防止把你学校的出口带宽或者对方的小服务器打爆。如果你需要登录才能下载wget也支持带Cookiewget --headerCookie: session_idxxx --headerReferer: https://example.org/books/ --recursive --level1 --no-parent --acceptpdf https://example.org/books/这里同样是把浏览器里的Cookie复制过来。别觉得“带Cookie就等于破解”不是。你用的是自己的账号自己的权限只是让命令行工具替你跑而已。4.3 文件名乱码和排序难题重命名这一步最好提前做wget下载下来的文件名有时候会有编码问题。常见的有中文变成%E4%B8%AD%E6%96%87这种URL编码文件名带一串无意义的?download1明明是第2册排到第10册前面导致“2,10,11,3,4”这种乱序。排序乱本质是文件名数字位数不齐。解决办法是下载完之后用脚本批量重命名把序号统一补成三位或四位数字。比如原来有第2册.pdf和第10册.pdf单纯按文件名排序会把第10册排在第2册前面因为字符串比较是按首字符“1”和“2”去的。你需要在文件名里生成第002册.pdf这样的格式。一个示例脚本import re from pathlib import Path root Path(./textbooks) for f in root.glob(*.pdf): name f.stem # 去掉.pdf后缀 m re.search(r(\d), name) if m: num int(m.group(1)) new_name f{num:03d}_{name}.pdf new_path f.with_name(new_name) f.rename(new_path) print(f{f.name} - {new_name})这个脚本的目的是先保证排序正确再保证名字可读。你下载完几十个文件排序一乱后面整理目录、核对缺漏都是灾难。处理排序问题的最佳时机就是刚下载完的那一刻别拖。5. 下载不是终点批量改名、转PDF与归档三连5.1 按学科和年级自动建目录的小脚本批量下载完成之后第一件事不是打开看而是把文件归到该去的地方。我自己的目录规则是“学期/年级/科目_册次.pdf”元数据全写进文件名里这样丢到任何网盘、任何电脑里都不会乱。假设你下载了一堆文件文件名是语文_三年级下册.pdf、数学_四年级上册.pdf这种可以用一个很短的Python脚本按年级归类import re import shutil from pathlib import Path source_dir Path(./downloaded) target_dir Path(./2026春) for f in source_dir.glob(*.pdf): # 文件名示例语文_三年级下册.pdf parts f.stem.split(_) if len(parts) ! 2: continue subject, grade parts grade_dir target_dir / grade grade_dir.mkdir(parentsTrue, exist_okTrue) target grade_dir / f.name shutil.move(str(f), str(target)) print(f{f.name} - {target})这只是个起点。如果你手里的文件命名太乱比如3下语文.pdf、S3B-chinese.pdf这种那就得先建一个“旧名→新名”的映射表再用Path.rename()执行。别指望AI能精准猜出所有缩写尤其是跨学科、跨版本的资源。5.2 图片页面转PDFJPEG序列合成标准PDF文件如果你用第3节的方法下载了一本书的120张page_001.jpg到page_120.jpg下一步大概率是合成一个PDF方便在平板、阅读器上翻页。这一步有很多现成工具我用得最多的是img2pdf因为它不会像某些图像处理库那样重新压缩图片生成的PDF体积小、速度快。安装方式pip install img2pdf合并所有页img2pdf page_*.jpg -o textbook.pdf这里有个排序陷阱page_*.jpg的解包顺序在某些shell里是按字典序的也就是page_1.jpg排在page_10.jpg前面。如果你当时下载时已经把文件名补成了page_001.jpg这种三位数格式那没问题没有补零的话合并出来的PDF页序一定是乱的。这就是我前面反复强调“编号要补零”的原因。如果你想在Python里做更多控制也可以用Pillowfrom PIL import Image images [] for i in range(1, 121): img Image.open(fpage_{i:03d}.jpg).convert(RGB) images.append(img) images[0].save(textbook.pdf, save_allTrue, append_imagesimages[1:])Pillow的路径写起来麻烦一点但它允许你在合并前对每一页做裁剪、旋转、增强对比度适合处理扫描质量不高的旧教材。5.3 校验下载完整性页数对不对、图片破没破下完120张图你以为结束了还差一道安检校验完整性。最简单的办法是对比文件数量和页数。如果你知道这本书有118页你却下载了115张图那一定是中间漏了3页。这时候需要找出具体缺哪几页。from pathlib import Path import re expected set(range(1, 119)) # 预期页码 files list(Path(./ebook123).glob(*.jpg)) actual set() for f in files: m re.search(r(\d), f.stem) if m: actual.add(int(m.group(1))) missing sorted(expected - actual) print(缺页:, missing)对于PDF可以用PyMuPDF快速检查页数import fitz # PyMuPDF doc fitz.open(textbook.pdf) print(总页数:, doc.page_count)还有一类“下载成功了但是文件损坏”的情况往往是网络异常导致图片只有几十KB。检查方法是看文件大小分布正常书页扫描图通常有几百KB到几MB突然出现一个几KB的页面多半就是坏图直接删掉重新下载。5.4 归档时顺便补OCR层让教材可以全文搜索这一步严格来说不算下载但对我来说是批量下载的“下半场”。没有OCR的扫描版PDF存在电脑里就是一张张废图翻起来麻烦搜也搜不到。给扫描版补一个文字层就能在PDF阅读器里直接搜索关键词找知识点快得多。工具方面开源免费的我推荐两个OCRmyPDF依赖Tesseract和PaddleOCR。Tesseract对印刷体中文识别的准确率还不错但对手写体和排版复杂的两栏混排会有点力不从心。PaddleOCR的中文模型更准但安装体积也更大。OCRmyPDF最常用的一句命令是这样ocrmypdf --language chi_sim --force-ocr input.pdf output.pdf跑完你会发现PDF文件大了不少因为文字层和图片层都保留了。这个操作是纯本地计算不涉及任何在线服务速度取决于你的CPU和页数。一百页大概需要几分钟到十几分钟不等。给扫描版教科书做OCR是我最推荐的事。你想想批量下载花了一个小时OCR再花二十分钟换来以后每次写作业、复习时都能一秒搜到“电磁感应”出现在哪一页这个投资回报率非常值。6. 批量下载的边界哪些操作会被拦、哪些绝对不能碰6.1 个人学习与再传播这堵墙比技术更难翻每当我分享下载工具和脚本总有人问“能不能顺便把网盘链接发我一份”。这个问题恰恰是所有批量下载操作的终极雷区。你可以为个人学习下载公开课件、免费教材也可以把你自己的购买记录和平台绑定下载到本地备份。但一旦你把这些PDF压缩包传到公开网盘、资源分享群、文库站点性质就变了。哪怕资源原本是免费的“再分发”也可能违反平台规则如果资源本身是付费的那就直接构成侵权。我的建议很简单自用可以传播免谈。整理好的教材文件用私有网盘或移动硬盘备份不给任何人发链接。6.2 绅士爬虫守则别把服务器当成你家的文件夹批量下载的技术含量不高真正考验人的是“克制”。一个教材服务器要服务成千上万的在校学生你的脚本若是并发十几条请求不带任何延时几分钟就可能影响到别人的正常访问。更现实的是对方运维一旦发现异常流量第一反应就是封你这个IP甚至封掉整个校园网出口那就把大家都坑了。我给自己定的纪律是三条单线程下载优先不是万不得已不用多线程每次请求之间至少间隔0.5秒到2秒下载总量到几十个文件之后主动停一下观察有没有被封的迹象。你可能会觉得这样慢但批量下载几十个文件最慢也就十几分钟比被封了之后重新折腾换IP、挂代理要快得多。6.3 账号权限与访问控制权限之外的“灵活处理”一律不做在线教材平台通常区分三种访问等级完全公开、登录可见、订阅/授权可见。前两种你只要有账号就能看能下第三种平台设置了付费墙或DRM保护目的是限制未授权访问。有些教程会教你抓包、改请求参数、拼接URL绕过权限校验这种事我一律不建议做。第一是法律风险绕过访问控制在很多地方是明确违法的第二是技术风险平台反爬不是吃素的轻则封号重则影响你的其他在线服务。你的目标只是拿教材不是和运维打攻防战。你需要下载的教科书如果正好卡在权限区性价比最高的做法是先看学校图书馆有没有采购没有就找出版社买电子版再没有就买纸质书自己扫描。相信我这些正规路径加起来比研究绕过方案更省时间。6.4 一次失败下载的排查顺序从日志里找答案无论你用什么脚本批量下载一定会有失败的时候。我踩过无数次坑之后总结了一个固定的排查顺序分享出来给你参考先看HTTP状态码。403多半是Referer或Cookie问题404说明URL规律猜错了可能是多了加密参数503是服务器负载高可能被限流了。再对比单个文件大小。凡是文件大小明显小于正常范围的别犹豫删了重下。最后看URL里有没有临时token。有些平台的图片地址带有效时间你下载到第50页第一页的token已经过期了重跑时前面的会全部失败。这时需要重新拿一个新的token更新到脚本里再执行。这轮排查下来90%的问题都能解决。剩下的10%大概率是平台本身设置了更加严格的风控那就不是技术问题而是平台明确不想让你批量下载。尊重它改用逐页另存为或者找平台申请批量授权。我的经验是批量下载教科书这件事真正决定体验的从来不是某个脚本有多牛而是你有没有把“合法访问、礼貌请求、清晰归档”这三件事想透。工具到处都是思路清晰的人一条wget命令就能解决别人焦虑一晚上的问题。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询