Saber 酱的抱枕

Fly me to the moon

05/29
2015
学习

写了个批量下载P站图片的js

本文中的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);//开启下载图片的定时器

写了个批量下载P站图片的js