115网盘一键转存脚本实战:用户脚本实现浏览器自动化

发布时间:2026/9/8 4:24:49
115网盘一键转存脚本实战:用户脚本实现浏览器自动化 简介面向经常使用115网盘、需要批量整理或分享文件的个人与办公用户这份资源是一个基于油猴Tampermonkey扩展运行的JavaScript辅助脚本用于解决115网盘中手动逐个创建分享链接、获取下载地址时操作繁琐、效率低下的问题。压缩包体积仅9KB包含1个js脚本文件安装后在115网盘页面即可激活使用支持一键创建链接、快速获取下载链接、批量处理大量文件部分逻辑还可实现自动化转存减少重复劳动。脚本轻量、上手门槛低适合日常需要频繁流转云盘文件的内容收集者、办公人员及网盘管理爱好者。已有11414人学习下载可见其需求广泛使用时建议从可靠渠道获取脚本并留意115网盘接口更新及时维护以保证功能稳定。整体来看这份资源为高频网盘操作提供了实用便捷的加速方案。 上周帮家里长辈整理一批学习资料对方一口气甩过来16个115网盘分享链接。我坐在电脑前打开第一个登录、输入提取码、等页面加载完再点“存至网盘”选目录确认……到第5个的时候我已经开始计算这波重复劳动到底要吃多少时间成本。当晚我翻出网上的115一键转存脚本花了几小时把原理和写法彻底捋了一遍16个链接最后几乎是喝口水的功夫就全部归位。这篇文章就是那次折腾的完整复盘。我会从“为什么需要一键转存”讲起拆解这类脚本的工作方式提供一个能自己改、能跑通的UserScript骨架再把实装过程中最容易翻车的几个坑列出来。适合两类人看一类是经常接收115分享文件、不想再做机械点击的普通用户另一类是刚接触浏览器用户脚本、想拿真实场景练手的前端/自动化入门者。1. 每天被115分享链接淹没一键转存到底解决了什么1.1 一个真实且常见的尴尬场景先还原一下手动转存的完整动作拿到分享链接打开浏览器若没登录还得先登录有提取码的要输一次提取码页面渲染出来之后找到“转存”或“保存到网盘”按钮接着弹出一个目录选择框有时默认停在根目录有时停在你上次选过的目录稍不注意就存错地方最后点确认等它转存完成。这套动作单次执行还好一旦变成10个、20个链接就完全是另一回事了。我自己测试过状态最好的时候一个链接最快也要25秒状态不好遇到验证码或加载慢一个链接拖到2分钟也不奇怪。光是转存这一件事16个链接就花掉20多分钟而且全程不能分心——点错目录、漏填提取码、中途手滑关掉页面都得从头再来。1.2 现有转存方式的效率对比在写脚本之前我把能想到的替代方案都过了一遍大概有这几种方案成本学习门槛稳定性可定制性手动浏览器操作零成本但费时间无无无115官方客户端批量功能客户端免费部分批量能力受账号等级限制低高低第三方网盘管理工具免费或小付费中中依赖逆向接口中浏览器用户脚本油猴脚本零成本Tampermonkey免费中中高随页面改版需维护高官方客户端的思路其实更正规但它的批量操作主要发生在“你网盘里已有的文件”之间解决不了“别人发来一堆分享链接要一个个收进来”的场景。第三方工具我试过几个效率确实高可用一段时间就担心两个问题一是接口字段变动导致工具失效二是我只知道它帮我转存了却不知道它到底往服务端发了什么参数心里没底。1.3 为什么我最终选择了浏览器用户脚本最后选定浏览器用户脚本逻辑其实很简单不装额外软件浏览器本身就能跑跨平台脚本代码开放每一步做了什么都能看明白也能自己改只要你的浏览器还带着登录态脚本就复用这份会话不需要单独维护凭证。用户脚本本质上是一段运行在特定网页里的JavaScript由Tampermonkey这类扩展管理器注入。115分享页是一个网页那在网页上做自动化就是顺理成章的事。比起黑盒工具我更愿意把一个流程控制在自己手里哪怕它需要我花点时间维护。2. 转存脚本的工作原理从“点击按钮”到“自动搬运”2.1 转存的本质是什么先说个容易被忽略的事实115网盘的“转存”并不是真的把文件数据从A账号复制到B账号。分享者在服务器上开启了一个“读取权限”转存动作的本质是在你自己的网盘目录里新增一条指向这些文件的记录。它更像是图书馆里你获准阅读一本书后把书名抄进了自己的藏书清单。理解这一点很重要因为它决定了脚本的边界转存的前提是你对这个分享有访问权限。有提取码就填提取码有登录限制就按登录限制来。脚本能做的只是把“人工输入、点击、确认”这些动作自动化它不应该也没有能力去绕过授权。这也是我在开发过程中给自己划的一条底线——只处理自己有权访问的分享内容并且注意遵守网站的服务条款。2.2 两条实现路线的取舍模拟点击 vs 直接调用接口实现一键转存业界基本走两条路。第一条是“模拟点击”。脚本像真人一样等页面渲染完成后找到提取码输入框填进去再找到“转存”按钮触发点击最后处理弹出的目录选择对话框。这条路的好处是技术门槛低不需要了解后端接口细节只要熟悉DOM操作就行。坏处是每一次页面结构改版选择器和按钮识别逻辑就可能失效而且目录选择框的树形控件交互复杂自动化起来很脆。第二条是“接口调用”。利用浏览器开发者工具在手动转存时观察Network面板找出真正提交转存请求的URL、请求方法、参数和Cookie然后用脚本里的GM_xmlhttpRequest直接发同款请求。这条路速度快适合批量坏处是接口字段经常变化需要一定的逆向分析能力同时还要处理好跨域和请求头。实际用得最多的是第三条“混合路线”从分享链接或页面DOM里提取出分享标识参数然后用接口去执行转存。页面只负责“读取信息”真正干活的还是接口。这个方法兼顾了稳定性和执行效率也是我要在下面代码骨架里演示的方案。2.3 分享链接里藏着哪些关键参数115的分享链接通常是这种格式https://115.com/s/swabc123?passwordxxxx#xxxx这里有几个关键信息/s/后面那串字符比如swabc123是分享标识ID脚本要靠它才知道要把哪份分享转进来password参数是提取码对应页面里的密码输入框#后面的内容某些页面版本会作为辅助校验参数出现。如果你打开开发者工具在一个分享页面里手动执行一次转存会在Network面板里看到类似share_id、share_key、user_id、pwd这类的请求参数。不同页面版本参数名不一样但思路一致把页面里已有的信息提取出来组装成一次符合服务端预期的请求。所以无论页面怎么改抓包这个基本功一定要会这也是脚本失效后你能自救的唯一方法。3. 代码骨架搭一个能自动填码、自动点击转存的UserScript3.1 准备运行时环境动手前先装好Tampermonkey。Chrome、Edge都可以直接去扩展商店装Firefox也有对应版本。装好之后浏览器工具栏会出现扩展图标点进去选择“创建新脚本”即可。脚本运行期间浏览器需要保持115网盘的登录状态这是所有转存操作的基础。你可以在新开的普通标签页里登录一次脚本运行时复用这份Cookie和登录会话。3.2 先写脚本的“身份证”UserScript元信息每段用户脚本开头都是一段由UserScript包裹的元信息块它决定了脚本在哪些页面上生效、能申请哪些权限// UserScript // name 115 一键转存助手 // namespace https://your-blog.example/ // version 0.1 // description 自动识别115分享链接自动填写提取码并点击转存 // author your-name // match https://115.com/* // match https://*.115.com/* // grant GM_xmlhttpRequest // run-at document-idle // /UserScript几个关键点match声明脚本只在哪些域名下运行。115的分享页主域名是115.com但有些资源来自子域所以我建议把*.115.com也加进来。grant GM_xmlhttpRequest是跨域请求的通行证。普通页面脚本直接调fetch会被CORS拦死GM_xmlhttpRequest是脚本管理器提供的跨域API绕过页面同源限制。run-at document-idle表示等页面基本加载完成后再执行避免DOM还没渲染完就去抓元素。3.3 核心流程代码拆解元信息之后就是主逻辑。下面这段是一个最小可用的骨架我从分享链接里解析出分享标识和提取码再自动填表、自动点按钮(function () { use strict; function parseShareUrl(url) { const match url.match(/\/s\/([a-zA-Z0-9])/); const shareId match ? match[1] : ; const password new URL(url).searchParams.get(password) || ; return { shareId, password }; } function fillPassword(input, pwd) { if (!input || input.value pwd) return; const setter Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, value).set; setter.call(input, pwd); input.dispatchEvent(new Event(input, { bubbles: true })); } function findButton(texts) { return Array.from(document.querySelectorAll(button, a, span, div)) .find(el texts.some(t el.textContent.trim().includes(t)) el.offsetParent ! null); } function clickTransferButton() { const btn findButton([转存, 存至网盘]); if (!btn) return false; btn.dispatchEvent(new MouseEvent(click, { bubbles: true, cancelable: true })); return true; } function waitFor(fn, timeout 10000) { return new Promise((resolve, reject) { const start Date.now(); const timer setInterval(() { const result fn(); if (result) { clearInterval(timer); resolve(result); } else if (Date.now() - start timeout) { clearInterval(timer); reject(new Error(waitFor timeout)); } }, 300); }); } async function main() { const { shareId, password } parseShareUrl(location.href); if (!shareId) return; await waitFor(() document.querySelector(input[typepassword]) ! null); fillPassword(document.querySelector(input[typepassword]), password); await waitFor(clickTransferButton); } main(); })();这个骨架做了四件事解析链接、等页面出现提取码输入框、填入密码、等待并点击转存按钮。如果页面没有密码框——比如分享人没设提取码——waitFor会在超时后报错但主流程不会崩溃这属于可接受的健壮性下限。3.4 让脚本“等页面”而不是“抢页面”很多新手写自动化脚本最常犯的毛病是“抢跑”。脚本注入时页面才加载到一半提取码输入框还没出现在DOM里选择器当然找不到。waitFor函数的思路就是轮询等待每隔300毫秒检查一次目标元素是否出现最多等10秒超时才放弃。还有个容易被忽略的细节是fillPassword里那段setter.call。现代前端框架Vue、React之类对输入框的值做了拦截你直接input.value xxx框架的响应式系统可能感知不到表单永远认为是空密码。通过HTMLInputElement原型上的原生value setter去赋值再手动派发一个input事件才能骗过框架的监听器。这个技巧我最初是从一个老前辈的代码里学来的后来在好几个网站上都验证过可以说是处理富交互页面必备的常识。4. 实测中的翻车现场登录态、跨域与风控4.1 现象一脚本没反应控制台报跨域错误我第一次用fetch直接提交转存请求时控制台里冒出一行大红字——CORS。浏览器出于安全考虑不允许一个网站的脚本随意访问另一个域名下的接口。这个问题有两个解法第一种是改用GM_xmlhttpRequest它由脚本管理器直接发起请求不走页面上下文天然绕开CORS限制第二种是让请求保持同源也就是把脚本运行在115自己的域名下再请求115自己的接口。大多数情况下先用GM_xmlhttpRequest因为它更省事。如果你看到的是GM_xmlhttpRequest is not defined那说明grant没写对。脚本管理器在沙箱模式下不会把GM_开头的API暴露给页面上下文必须在元信息里声明你需要的API否则它就是不存在的。4.2 现象二按钮找到了也点了但没有任何转存发生这类问题排查起来最磨人。元素选择器能找到转存按钮脚本也确实执行了.click()但页面纹丝不动。原因通常有两种。第一种是那个可点击元素其实是个包裹用的容器真正的点击处理逻辑挂在子元素或父组件上你需要换一个更精确的选择器或者对元素派发一个原生冒泡事件而不是简单的.click()。第二种是按钮的click事件监听器是动态绑定的在脚本运行那一刻还没绑上点击事件就像打在棉花上。我的处理习惯是先用dispatchEvent(new MouseEvent(click, { bubbles: true, cancelable: true }))如果还不行就在控制台手动执行getEventListeners(btn).click看看监听器到底在不在。把事件监听器找出来比瞎试选择器快得多。4.3 现象三脚本在分享页生效但批量操作被拦截单次转存明明成功批量循环一跑转存几个后接口开始返回异常偶尔还会跳验证码。这就是我踩过的第三个坑频率触发风控。解决思路很朴素控制并发度加入随机延迟。两个请求之间至少间隔2到3秒延迟时间带一点随机性不要每次固定2.5秒——固定节奏反而容易被识别成机器行为。如果某个请求失败不要立刻重试用指数退避第一次等3秒第二次等6秒第三次12秒给服务端一个喘息空间。这里要特别提醒一句写脚本可以提高效率但不能变成骚扰服务端的工具。你手上如果是几十个链接分批跑没问题如果涉及上千个链接的大规模操作应该先确认服务条款是否允许再考虑要不要这么做。效率和安全合规从来不是对立面而是分寸问题。4.4 排查这类问题的通用路径踩坑踩多了我总结出一条特别管用的排查链路关闭脚本在页面上手动执行一次完整转存同时开着DevTools的Network面板把正常请求记录下来打开脚本再次执行转存对比脚本发出的请求和刚才手动操作的请求看URL、参数、Cookie、Referer、Content-Type有没有差异如果脚本压根没发起请求问题多半出在DOM定位或事件绑定上回控制台打印DOM结构继续查如果请求发出了但返回失败优先核对参数完整性和登录态不要先怀疑服务端。这套链路看起来基础但能覆盖绝大多数翻车场景。尤其是第二步脚本请求和正常请求一对比缺什么参数一眼就能看出来。5. 把一次性脚本养成长期工具维护与进阶5.1 页面改版后脚本失效怎么办用户脚本最大的敌人不是Bug而是页面改版。115换过一次分享页的按钮文案我用了半年的选择器一夜作废点击转存按钮的代码彻底失效。那时候我才意识到把业务规则写死在代码里有多痛苦。后来我把可能变动的部分全部抽到脚本顶部的配置对象里按钮文案、超时时间、批量间隔、请求地址都放一起。页面改版后第一件事不是改逻辑而是打开控制台看新页面的DOM结构更新配置和选择器。维护成本从“重写半个脚本”降到了“改三五处配置”。const CONFIG { transferButtonTexts: [转存, 存至网盘], pwdInputSelector: input[typepassword], batchDelayMin: 2000, batchDelayMax: 3500 };5.2 整理目录、失败重试与日志脚本稳定跑通之后我开始给它加更贴近自己使用习惯的功能。早期版本只负责“把文件转存到根目录”但我的资料是按项目分类的转完还得手动搬文件夹效率等于没提升多少。后来我在脚本里加了自动目录逻辑转存前先调用目录创建接口把分享的内容直接放进以当天日期命名的文件夹里。这一步依赖具体接口开发时还是走抓包的老路子找到手动创建目录请求的参数再仿照着发。另外两个小而实用的功能是失败重试和日志。失败重试我用简单的计数器实现连续失败3次就跳过并记录下来不让单个坏链接堵死整个队列。日志则直接输出到控制台每次转存成功与否、耗时多少都打一条。跑完一批链接后回控制台一眼就能看出哪些需要人工处理。5.3 脚本的边界和我的使用原则说到最后还是想给脚本的边界划个线。浏览器用户脚本解决的是“重复劳动自动化”的问题它的价值在于把机械操作交还给程序让人腾出时间做整理、归类、消费资源这些真正有意义的动作。它不应该被用来绕过付费墙、破解提取码、抓取他人未授权资源也不应该去做超出个人合理使用范围的批量操作。我在自己的使用原则里永远有一条我能用脚本提高自己的效率但我不会用脚本去做任何会让分享者为难、让平台风控追着跑的事。对普通用户来说保持“够用就好”的心态比把脚本升级成全套自动化平台更重要。最后再分享一点个人体会这类脚本工具做得越贴近自己的流程越顺手越追求通用反而越容易坏。别想着一次写成完美的工具先用最小骨架跑通再在真实使用中逐步加功能。它就像你桌面上的一把螺丝刀不是每次都用得上但真到了需要的时候自己动手拧比到处找人借趁手得多。本文还有配套的精品资源点击获取