Pixiv Direct Links

Turns thumbnail titles into direct or mode=manga links, adds direct image links on mode=manga pages, replaces the medium thumbnail on mode=medium pages with the full size, and disables lazy-loading images.

Fra 27.08.2014. Se den seneste versjonen.

// ==UserScript==
// @name           Pixiv Direct Links
// @namespace      https://greasyfork.dpdns.org/users/3412
// @description    Turns thumbnail titles into direct or mode=manga links, adds direct image links on mode=manga pages, replaces the medium thumbnail on mode=medium pages with the full size, and disables lazy-loading images.
// @include        http://www.pixiv.net*
// @grant          GM_xmlhttpRequest
// @version        2014.08.26
// ==/UserScript==

//Turn thumbnail titles into direct links (single images) or mode=manga links.  If GM_xmlhttpRequest() is available, this only requires a single pixiv API query per page.  Without GM_xmlhttpRequest(), the images must be queried individually.  Title links are disabled by default when GM_xmlhttpRequest() isn't available but can be enabled anyway by changing this setting to just "true".
var directTitles = ( typeof(GM_xmlhttpRequest) != "undefined" );

//Append direct links below images on mode=manga pages
var directManga = true;

//Replace the medium thumbnail on mode=medium pages with the full size
var fullSizeMedium = true;

//Disable lazy loading images.  These appear on mode=manga pages, rankings, and the "Recommended" section of the bookmarks page.
var dontSayLazy = true;

//----------------------------------------------------------------//

if( location.search.indexOf("mode=manga_big") > 0 )
{
	//Make the 'manga_big' image link to itself instead of closing the window
	var page = document.querySelector("img[src*='_p']");
	if( page )
	{
		var link = document.createElement("a");
		link.href = page.src;
		link.appendChild( document.createElement("img") ).src = page.src;
		document.body.innerHTML = "";
		document.body.appendChild( link );
	}
}
else if( location.search.indexOf("mode=manga") > 0 )
{
	var container = document.getElementsByClassName("full-size-container");
	if( directManga && container.length )
	{
		//Check the mode=manga_big page for the first page to determine if the "_big_p" size exists.
		var req = new XMLHttpRequest();
		req.open( "GET", location.href.replace('mode=manga','mode=manga_big&page=0'), true );
		req.onload = function()
		{
			var firstImage = req.responseXML.querySelector("img[src*='_p0.']").src;
			for( var i = 0; i < container.length; i++ )
			{
				//Add direct link below each page
				var link = document.createElement("a");
				link.textContent = "direct link";
				link.style.display = "block";
				link.href = firstImage.replace( "_p0.", "_p"+i+"." );
				container[i].parentNode.appendChild( link );
			}
		}
		req.responseType = "document";
		req.send(null);
	}
}
else if( window == window.top )//not inside iframe
{
	if( directTitles )
	{
		//Link dem titles.
		linkThumbTitles([document]);
		new MutationObserver( function(mutationSet)
		{
			mutationSet.forEach( function(mutation){ linkThumbTitles( mutation.addedNodes ); } );
		}).observe( document.body, { childList:true, subtree:true } );
	}
	
	//Full size image on mode=medium page:
	var mediumLink = location.search.indexOf("mode=medium") > 0 && document.querySelector(".works_display a[href*='mode=']");
	if( mediumLink )
	{
		//Make link open in same window
		mediumLink.removeAttribute('target');
		
		//If not manga, replace the thumbnail with the full size and point the link directly to the image instead of the mode=big page
		var mainImage = fullSizeMedium && mediumLink.querySelector("a[href*='mode=big'] img[src*='_m.']");
		if( mainImage )
		{
			mainImage.setAttribute("style", "max-width: 740px; height: auto; width: auto;");
			mediumLink.href = mainImage.src = mainImage.src.replace( "_m.", "." );
		}
	}
}

if( dontSayLazy && unlazyImage() && window == window.top )
{
	//Initial page has lazy images; listen for more images added later
	new MutationObserver( function(mutationSet)
	{
		mutationSet.forEach( function(mutation)
		{
			for( var i = 0; i < mutation.addedNodes; i++ )
				unlazyImage( mutation.addedNodes[i] );
		} );
	}).observe( document.body, { childList:true, subtree:true } );
}

//----------------------------------------------------------------//

function unlazyImage(target)
{
	var images = ( target || document ).querySelectorAll("img[data-src]");
	for( var i = 0; i < images.length; i++ )
		images[i].src = images[i].getAttribute("data-src");
	return images.length;
}

function linkThumbTitles(targets)
{
	var image = [], titleList = [];
	for( var i = 0; i < targets.length; i++ )
		image = image.concat( Array.prototype.slice.call( targets[i].querySelectorAll("li a[href*='mode=medium&illust_id='] img") || [] ) );
	
	for( var i = 0; i < image.length; i++ )
	{
		var page, title;
		for( page = image[i].parentNode; page.tagName != "A"; page = page.parentNode );
		
		//The prev/next thumbnails on mode=medium pages have text before/after the image.  Text also follows the image on image responses listings.
		if( !(title = page.getElementsByClassName("title")[0]) && (title = page.lastChild).nodeName != '#text' && (title = page.firstChild).nodeName != '#text' )
			continue;//Can't find title element
		if( !/&illust_id=\d+/.test( page.href ) )
			continue;//No illustration ID (unexpected)
		if( image[i].parentNode.classList.contains("ugoku-illust") )
			continue;//Ugoira animation
		
		//Start title link at mode=medium and change later.
		var titleLink = document.createElement("a");
		titleLink.href = page.href;
		titleLink.style.color = "#333333";//Style used on some pages
		
		//Move the title out of the thumbnail link
		page.removeChild(title);
		titleLink.appendChild(title);
		page.parentNode.insertBefore( titleLink, page.nextSibling );
		
		titleList.push({ id: page.href.match(/&illust_id=(\d+)/)[1], link: titleLink });
	}
	
	if( !titleList.length )
		return;
	if( typeof(GM_xmlhttpRequest) == "undefined" )
		return directLinkSingles( titleList );
	
	var query = "http://spapi.pixiv.net/iphone/illust.php?illust_id="+titleList[0].id;
	for( var i = 1; i < titleList.length; i++ )
		query += ","+titleList[i].id;
	
	//Session ID is needed for R-18 images
	var sessionID = document.cookie.match(/PHPSESSID=[^;]+/)[0];
	if( sessionID )
		query += "&"+sessionID;
	
	GM_xmlhttpRequest(
	{
		method: "GET",
		url: query,
		onload: function(responseDetails)
		{
			var result = [], quote = false;
			
			//Strip quotes and commas inside of quotes, for easier parsing later
			for( var i = 0; i < responseDetails.responseText.length; i++ )
			{
				if( responseDetails.responseText[i] == '"' )
					quote = !quote;
				else if( !quote || responseDetails.responseText[i] != ',' )
					result.push( responseDetails.responseText[i] );
			}
			result = result.join("").split("\n");
			
			for( var i = 0; i < result.length && result[i].length; i++ )
			{
				var matcher, parr = result[i].split(",");
				for( var j = 0; j < titleList.length; j++ )
					if( parr[0] == titleList[j].id )
					{
						//[ 0]: illust_id
						//[ 2]: extension
						//[ 9]: http://i2.pixiv.net/img04/img/aenobas/mobile/30095810_480mw.jpg?1348946035 (always jpg)
						//[19]: # pages (empty if not manga)
						if( /^\d+$/.test(parr[19]) )
						{
							titleList[j].link.href = titleList[j].link.href.replace("mode=medium","mode=manga");
							
							//Append the page count to the title attribute
							( titleList[j].link.firstChild.nodeName == '#text' ? titleList[j].link : titleList[j].link.firstChild ).title += " ("+parr[19]+"p)";
						}
						else if( (matcher = parr[9].match( /(.*\/img\d+\/img\/[^\/]+\/)mobile\/[^?]+(.*)/ )) != null )
						{
							titleList[j].link.href = matcher[1]+parr[0]+"."+parr[2]+matcher[2];//baseURL + illustID + "." + extension + revision
						}
						
						//Remove title from list
						titleList.splice( j, 1 );
						break;
					}
			}
			
			//Individually query whatever didn't get matched above (e.g. R-18 images when no session ID)
			directLinkSingles( titleList );
		}
	});
}

//Fallback method to query each image's mode=medium page.
function directLinkSingles(titleList)
{
	for( var i = 0; i < titleList.length; i++ )
		(function( title )
		{
			var req = new XMLHttpRequest();
			req.open( "GET", "http://www.pixiv.net/member_illust.php?mode=medium&illust_id="+title.id, true );
			req.onload = function()
			{
				var modeLink = req.responseXML.querySelector(".works_display a[href*='mode=']");
				if( modeLink.href.indexOf("mode=manga") > 0 )
					title.link.href = modeLink.href;
				else if( modeLink.href.indexOf("mode=big") > 0 )
					title.link.href = modeLink.querySelector("img[src*='_m.']").src.replace("_m.",".");
			}
			req.responseType = "document";
			req.send(null);
		})( titleList[i] );
}
长期地址
遇到问题?请前往 GitHub 提 Issues,或加Q群1031348184

赞助商

Fishcpy

广告

Rainyun

注册一下就行

Rainyun

一年攒够 12 元