05/29
2015
本文中的js有两段,都是用来批量下载p站图片的。模式一是从某一张图开始一直下载到画师最后一张图,模式二是在列表页中下载本页中所有的图。
第一个模式的使用场景很好理解,第二个模式在下载按tag筛选后的列表时特别有用,也可以用来单独下载画师作品列表中某一页的图片。
所有作品的所有大图都可以下载到,包括图集中的每一张图。动态图将会下载压缩包。
原理是使用iframe依次加载每个图片详情页,并获取大图下载下来。每个详情页完全加载完成之后(因为使用的是onload方法)才会下载图片,然后加载另一张图片的详情页。下载完所需要的时间会视每个人的网络情况而有所不同。
请务必使用chrome浏览器执行。IE和FF不支持a标签的download属性,所以无法使用本代码中的方法建立下载。
熟悉了下window对象的使用,在对窗口直接设置属性和添加事件时使用窗口的变量名,在使用窗口的document元素时需要使用窗口的name。
很多人反映说下载建立之后都任务失败,经过测试,发现和chrome版本有关。我以前用的是V39,没升级,代码可以用。昨天升到44就不能用了。于是跑到虚拟机里测试,用低版本chrome可以成功。
低版本chrome:
高版本:
具体原因不太明确,有一点猜测。不升级浏览器是不太现实的,不过可以用OX163网络图片下载器下载。
下面是模式一的代码,正确使用姿势是打开画师第一张图片的详情页面,然后在控制台执行以下代码。
//创建iframe function createIframe () { newFrame=document.createElement("iframe"); newFrame.name="myNewFrame"; newFrame.id="myNewFrame"; newFrame.width=0; newFrame.height=0; document.body.appendChild(newFrame); } createIframe(); //创建iframe2,这个用来打开图集页面 function createIframe2 () { newFrame2=document.createElement("iframe"); newFrame2.name="myNewFrame2"; newFrame2.id="myNewFrame2"; newFrame2.width=0; newFrame2.height=0; document.body.appendChild(newFrame2); } createIframe2(); //创建顶级窗口中的单图下载链接 function getBigPic () { bigPicHrefLink=document.createElement("a"); bigPicHrefLink.href=bigPicHref; bigPicHrefLink.download=null; document.body.appendChild(bigPicHrefLink); bigPicHrefLink.click(); } //创建iframe里面的单图下载链接 function getBigPic2 () { bigPicHrefLink=document.createElement("a"); bigPicHrefLink.href=bigPicHref; bigPicHrefLink.download=null; window.myNewFrame.document.body.appendChild(bigPicHrefLink); bigPicHrefLink.click(); } //获取下一张图片 function getNextPic () { clearInterval(t); //如果iframe里面还有下一张图片 if (!!window.myNewFrame.document.getElementsByClassName("after")[0].getElementsByTagName("a")[0]) { newFrame.src=window.myNewFrame.document.getElementsByClassName("after")[0].getElementsByTagName("a")[0].href; newFrame.onload=function () { if (!!window.myNewFrame.document.getElementsByClassName("original-image")[0]) {//如果是单图 bigPicHref=window.myNewFrame.document.getElementsByClassName("original-image")[0].getAttribute("data-src");//获取大图url getBigPic2(); }else if (!!window.myNewFrame.document.getElementsByClassName("works_display")[0]) { //如果是多图 if (!!window.myNewFrame.document.getElementsByTagName("canvas")[0]) {//如果是动图 bigPicHref=window.myNewFrame.pixiv.context.ugokuIllustFullscreenData.src; getBigPic2(); }else{//如果是多图,在第二个iframe中打开图集的详情页 newFrame2.src=window.myNewFrame.document.getElementsByClassName("works_display")[0].getElementsByTagName("a")[0].href; newFrame2.onload=function () { tujiUrl=[];//存储图集中每个图的url for (ii = 0; ii < window.myNewFrame2.document.getElementsByClassName("ui-scroll-view").length; ii++) { tujiUrl[ii]=window.myNewFrame2.document.getElementsByClassName("ui-scroll-view")[ii].getAttribute("data-src"); bigPicHrefLink3=window.myNewFrame2.document.createElement("a"); bigPicHrefLink3.href=tujiUrl[ii]; bigPicHrefLink3.download=null; window.myNewFrame2.document.body.appendChild(bigPicHrefLink3); bigPicHrefLink3.click(); }; } } }; t=setInterval(getNextPic, 500); } if (!window.myNewFrame.document.getElementsByClassName("after")[0].getElementsByTagName("a")[0]) {//如果没有下一张则取消 clearInterval(t); return; }; }; } //获取当前图片,在顶层窗口中 if (!!document.getElementsByClassName("original-image")[0]) {//如果是单图 bigPicHref=document.getElementsByClassName("original-image")[0].getAttribute("data-src");//获取大图url getBigPic(); }else if(!!document.getElementsByClassName("works_display")[0]){ //如果是多图 if (!!document.getElementsByTagName("canvas")[0]) {//如果是动图 bigPicHref=pixiv.context.ugokuIllustFullscreenData.src; getBigPic(); }else{//如果是多图,在第二个iframe中打开图集的详情页 newFrame2.src=document.getElementsByClassName("works_display")[0].getElementsByTagName("a")[0].href; newFrame2.onload=function () { tujiUrl=[];//存储图集中每个图的url for (ii = 0; ii < window.myNewFrame2.document.getElementsByClassName("ui-scroll-view").length; ii++) { tujiUrl[ii]=window.myNewFrame2.document.getElementsByClassName("ui-scroll-view")[ii].getAttribute("data-src"); bigPicHrefLink3=document.createElement("a"); bigPicHrefLink3.href=tujiUrl[ii]; bigPicHrefLink3.download=null; window.myNewFrame2.document.body.appendChild(bigPicHrefLink3); bigPicHrefLink3.click(); }; } } }; //如果顶层窗口存在下一张图,则 if (document.getElementsByClassName("after")[0].getElementsByTagName("a")[0]) { newFrame.src=document.getElementsByClassName("after")[0].getElementsByTagName("a")[0].href; newFrame.onload=function () { if (!!window.myNewFrame.document.getElementsByClassName("original-image")[0]) {//如果是单图 bigPicHref=window.myNewFrame.document.getElementsByClassName("original-image")[0].getAttribute("data-src");//获取大图url getBigPic2(); }else if(!!window.myNewFrame.document.getElementsByClassName("works_display")[0]){ //如果是多图 if (!!window.myNewFrame.document.getElementsByTagName("canvas")[0]) {//如果是动图 bigPicHref=window.myNewFrame.pixiv.context.ugokuIllustFullscreenData.src; getBigPic2(); }else{//如果是多图,在第二个iframe中打开图集的详情页 newFrame2.src=window.myNewFrame.document.getElementsByClassName("works_display")[0].getElementsByTagName("a")[0].href; newFrame2.onload=function () { tujiUrl=[];//存储图集中每个图的url for (ii = 0; ii < window.myNewFrame2.document.getElementsByClassName("ui-scroll-view").length; ii++) { tujiUrl[ii]=window.myNewFrame2.document.getElementsByClassName("ui-scroll-view")[ii].getAttribute("data-src"); bigPicHrefLink3=window.myNewFrame2.document.createElement("a"); bigPicHrefLink3.href=tujiUrl[ii]; bigPicHrefLink3.download=null; window.myNewFrame2.document.body.appendChild(bigPicHrefLink3); bigPicHrefLink3.click(); }; } } }; t=setInterval(getNextPic, 500);//开启定时器一定要写在这个onload里面,否则下一步的判断会报错 if (!window.myNewFrame.document.getElementsByClassName("after")[0].getElementsByTagName("a")[0]) {//如果没有下一张则取消 clearInterval(t); alert("最后一张图片正在下载中,下载即将完成。"); return; }; } };
下面是模式二的代码。这是在列表页使用的,每个列表页都需要执行一次。
//创建iframe1,打开作品页面 newFrame1=document.createElement("iframe"); newFrame1.name="mynewFrame1"; newFrame1.id="mynewFrame1"; newFrame1.width=0; newFrame1.height=0; document.body.appendChild(newFrame1); //创建iframe2,用来打开图集页面 newFrame2=document.createElement("iframe"); newFrame2.name="mynewFrame2"; newFrame2.id="mynewFrame2"; newFrame2.width=0; newFrame2.height=0; document.body.appendChild(newFrame2); //获取列表中作品的数量 var listNum=document.getElementsByClassName("_image-items")[0].getElementsByClassName("image-item"); //存储所有作品页面的url var listUrl=new Array(); for (var i = 0; i < listNum.length; i++) { listUrl[i]=listNum[i].getElementsByClassName("work")[0].href; }; //在iframe1中打开作品 function getPic () { clearInterval(t);//清除定时器 window.newFrame1.src=listUrl.shift();//输出并删除数组中的第一项 window.newFrame1.onload=function () { if (!!window.mynewFrame1.document.getElementsByClassName("original-image")[0]) {//如果是单图 //获取大图url bigPicHref=window.mynewFrame1.document.getElementsByClassName("original-image")[0].getAttribute("data-src"); //建立单图的下载链接并下载 bigPicHrefLink1=document.createElement("a"); bigPicHrefLink1.href=bigPicHref; bigPicHrefLink1.download=null; window.mynewFrame1.document.body.appendChild(bigPicHrefLink1); bigPicHrefLink1.click(); }else if(!!window.mynewFrame1.document.getElementsByClassName("works_display")[0]){//如果是多图或者动图 if (!!window.mynewFrame1.document.getElementsByTagName("canvas")[0]) {//如果是动图 //建立动图的下载链接并下载 bigPicHrefLink1=document.createElement("a"); bigPicHrefLink1.href=window.mynewFrame1.pixiv.context.ugokuIllustFullscreenData.src; bigPicHrefLink1.download=null; window.mynewFrame1.document.body.appendChild(bigPicHrefLink1); bigPicHrefLink1.click(); }else{//如果是多图,在第二个iframe中打开图集的详情页 window.newFrame2.src=window.mynewFrame1.document.getElementsByClassName("works_display")[0].getElementsByTagName("a")[0].href; window.newFrame2.onload=function () { //建立图集中每个图片的下载链接并下载 for (ii = 0; ii < window.mynewFrame2.document.getElementsByClassName("ui-scroll-view").length; ii++) { bigPicHrefLink2=window.mynewFrame2.document.createElement("a"); bigPicHrefLink2.href=window.mynewFrame2.document.getElementsByClassName("ui-scroll-view")[ii].getAttribute("data-src"); bigPicHrefLink2.download=null; window.mynewFrame2.document.body.appendChild(bigPicHrefLink2); bigPicHrefLink2.click(); }; } } }; t=setInterval(getPic, 500);//开启定时器一定要写在这个onload里面,否则下一步的判断会报错 if (listUrl.length==0) {//如果已经全部下载完成 clearInterval(t);//取消定时器 alert("最后一张图片正在下载中,下载即将完成。"); return; }; } } t=setInterval(getPic, 500);//开启下载图片的定时器