Greasy Fork is available in English.

监听网页操作

监听网页内的键盘事件和鼠标事件,抓取捕获这些鼠标、键盘消息的网页节点的源代码和坐标。ctrl+shift+F9,启动或停用脚本;ctrl+shift+F10,显示选项菜单;ctrl+shift+F11,显示抓取到的源代码;ctrl+shift+F12获取当前焦点的源代码。

// ==UserScript==
// @name    监听网页操作
// @namespace     
// @version      0.3
// @description    监听网页内的键盘事件和鼠标事件,抓取捕获这些鼠标、键盘消息的网页节点的源代码和坐标。ctrl+shift+F9,启动或停用脚本;ctrl+shift+F10,显示选项菜单;ctrl+shift+F11,显示抓取到的源代码;ctrl+shift+F12获取当前焦点的源代码。
// @author    流水
// @include    *
// @grant       unsafeWindow
// ==/UserScript==


window.setTimeout(function()
{
	 let canUseHotkey = false;
	 let needGetCode = false;
	let manyTimesHandle = false;
	let allNodeCode = false;
	let needGetHotkeyMessage = false;
	let needGetMouseMessage = false;
	let onlyOneNodeCode = false;
	let manyTimesCode = "";
	let observer1 = null;

	if (MutationObserver != null)
	{
	observer1 = new MutationObserver(function(mutationList, observer)
	{
		let str = "";
			for (let mutation of mutationList)
			{
		if (mutation.target.nodeName)
		{
			if (str == mutation.target.outerHTML)
				continue;
			else {
				str = mutation.target.outerHTML;
		GetPartSourceCode(mutation.target, "新增加或内容发生变化的元素");
			}
		}
			}
})
	}


	document.addEventListener("click", function(event)
	{
		if ((needGetMouseMessage === true) || (needGetHotkeyMessage === true))
		GetMessageType(event);
	else
		GetPartSourceCode(event.srcElement, "被点击的元素");
	})


	document.addEventListener("dblclick", function(event)
	{
		if (needGetMouseMessage === true)
		GetMessageType(event);
	})


	document.addEventListener("mousedown", function(event)
	{
		if (needGetMouseMessage === true)
		GetMessageType(event);
	})


	document.addEventListener("mouseout", function(event)
	{
		if (needGetMouseMessage === true)
		GetMessageType(event);
	})


	document.addEventListener("mouseover", function(event)
	{
		if (needGetMouseMessage === true)
		GetMessageType(event);
	})


	document.addEventListener("mouseup", function(event)
	{
		if (needGetMouseMessage === true)
		GetMessageType(event);
	})


	document.addEventListener("mousemove", function(event)
	{
		if (needGetMouseMessage === true)
		GetMessageType(event);
	})


		document.addEventListener("keydown", function(event)
		{
			if (needGetHotkeyMessage === true)
			GetMessageType(event);
			if (window.event.keyCode === 120 && !window.event.altKey && window.event.shiftKey && window.event.ctrlKey)
			{
			if (!canUseHotkey)
				{
					canUseHotkey = true;
				ChooseMode();
				}
				else {
					canUseHotkey = false;
					needGetCode = false;
					manyTimesCode = "";
					if (observer1 != null)
					observer1.disconnect();
					alert("脚本抓取源码的快捷键已禁用");
				}
			}
			if (window.event.keyCode === 121 && !window.event.altKey && window.event.shiftKey && window.event.ctrlKey && canUseHotkey)
			{
				ChooseMode();
			}
if (window.event.keyCode === 123 && !window.event.altKey && window.event.shiftKey && window.event.ctrlKey && canUseHotkey)
	{
		GetPartSourceCode(event.srcElement);
	}
	if (window.event.keyCode === 122 && !window.event.altKey && window.event.shiftKey && window.event.ctrlKey && canUseHotkey)
	{
		CreateSourceCodeTextarea();
	}
		})


		function GetMessageType(event)
		{
			if ((needGetHotkeyMessage === false) && (needGetMouseMessage === false))
				return false;
			let node = event.srcElement;
			let str = "鼠标、键盘消息为:";
			str += event.type;
			str += ("\r\n" + GetPosition(event));
			if (needGetHotkeyMessage)
				str += GetKeyCode(event);
			str += "\r\n";
			manyTimesCode += str;
			GetPartSourceCode(node);
		}


		function GetPosition(event)
		{
			let str = "";
			if (event.screenX && event.screenY)
			str += ("屏幕坐标为:" + "x:" + event.screenX + "," + "y:" + event.screenY + "\r\n");
			if (event.clientX && event.clientY)
			str += ("客户区坐标位置为:" + "x:" + event.clientX + "," + "y:" + event.clientY + "\r\n");
			if (event.pageX && event.pageY)
			str += ("页面坐标位置为:" + "x:" + event.pageX + "," + "y:" + event.pageY + "\r\n");
			return str;
		}


		function GetKeyCode(event)
		{
			let str = "";
			if (!needGetHotkeyMessage || !window.event.keyCode)
				return str;
			str += "快捷键为:";
			if (window.event.altKey)
			str += "alt+";
		if (window.event.shiftKey)
			str += "shift+";
		if (window.event.ctrlKey)
			str += "ctrl+";
		str += (window.event.keyCode + "\r\n");
			return str;
		}


		function GetPartSourceCode(node, headStr = "")
		{
			if (needGetCode === false)
			return;
			if (!node)
			return;
		let str = "";
		let index = 0;
		while ((node.nodeName != null) && (node.nodeName != "HTML"))
		{
			if (index === 0)
				if (headStr === "")
		str += ("被操作的元素node" + index + "的名称为" + node.nodeName + "\r\n");
	else
		str += (headStr + "node" + index + "的名称为" + node.nodeName + "\r\n");
		else
		str += ("node" + (index - 1) + "的父元素node" + index + "的名称为" + node.nodeName + "\r\n");
		let attributes = node.attributes;
		if (attributes != null)
		{
			if (index === 0)
		str += "node" + index + "的属性为:\r\n";
		else
		str += "node" + index + "的属性为:\r\n";
		for(let element of attributes)
		{
		if (element != null)
			str += (element.name + " = " + element.value + "\r\n");
		}
	}
	else {
		if (index === 0)
		str += "node" + index + "的属性为空\r\n";
		else
		str += "node" + index + "的属性为空\r\n";
	}
	if (node.innerHTML != "")
	{
		if (index === 0)
		str += ("node" + index + "的内容为" + node.innerHTML + "\r\n\r\n");
		if ((index === 1) || (allNodeCode === true && index > 1))
		str += ("node" + index + "的内容为" + node.innerHTML + "\r\n\r\n");
	}
		else {
			if (index === 0)
		str += ("node" + index + "的内容为空" + "\r\n\r\n");
		else
		str += ("node" + index + "的内容为空" + "\r\n\r\n");
		}
	str += "\r\n";
	if (onlyOneNodeCode === true)
		break;
	++index;
	node = node.parentNode;
}
manyTimesCode += str;
if (!manyTimesHandle)
needGetCode = false;
PrintCode();
		}


		function CreateSourceCodeTextarea()
		{
			needGetCode = false;
			needGetHotkeyMessage = false;
			needGetMouseMessage = false;
			if (observer1 != null)
			observer1.disconnect();
			let sourceCodeTextarea = document.getElementById("sourceCodeTextarea");
			if (!sourceCodeTextarea)
			{
				sourceCodeTextarea = document.createElement('textarea');
			sourceCodeTextarea.setAttribute("id", "sourceCodeTextarea");
			sourceCodeTextarea.setAttribute("title", "网页源代码");
			sourceCodeTextarea.setAttribute("readonly", "readonly");
			document.getElementsByTagName('body')[0].appendChild(sourceCodeTextarea);
		sourceCodeTextarea.onblur = function()
			{
				document.getElementsByTagName('body')[0].removeChild(this);
			}
			}
			sourceCodeTextarea.innerHTML = manyTimesCode;
		sourceCodeTextarea.focus();
		}


		function ChooseMode()
		{
			manyTimesCode = "";
			if (observer1 != null)
			observer1.disconnect();
		let selectNode = document.getElementsByName("selectForCHooseMode");
			if (!selectNode[0])
			{
				selectNode = document.createElement("select");
			selectNode.setAttribute("name", "selectForCHooseMode");
			selectNode.innerHTML = ("<option value=\"-1\">请选择</option>"
			+ "<option value=\"0\">获取一次被点击元素的源码(只获取前两层元素的完整源代码)</option>"
			+ "<option value=\"1\">连续获取被点击元素的源码(只获取前两层元素的完整源代码)</option>"
			+ "<option value=\"2\">获取一次被点击元素的源码(获取直到根节点的完整源代码)</option>"
			+ "<option value=\"3\">连续获取被点击元素的源码(获取直到根节点的完整源代码)</option>"
			+ "<option value=\"4\">获取完整网页源代码</option>"
			+ "<option value=\"5\">侦听鼠标、键盘消息</option>"
			+ "<option value=\"6\">只侦听鼠标消息</option>"
			+ "<option value=\"7\">只侦听键盘消息</option>"
			+ "<option value=\"8\">只侦听鼠标消息并只获取第一层节点的内容</option>"
			+ "<option value=\"9\">只侦听键盘消息并只获取第一层节点的内容</option>"
			+ "<option value=\"10\">侦听鼠标、键盘消息并只获取第一层节点的内容</option>"
			+ "<option value=\"11\">获取新增节点内容</option>"
			+ "<option value=\"12\">获取新增节点内容,并只获取第一层节点</option>"
			+ "<option value=\"13\">获取新增节点及被改变文本的内容</option>"
			+ "<option value=\"14\">获取新增节点及被改变文本的内容,并只获取第一层节点</option>");
			document.getElementsByTagName('body')[0].appendChild(selectNode);
			selectNode.focus();
			selectNode.onblur = function()
			{
									manyTimesCode = "";
									needGetCode = true;
									needGetHotkeyMessage = false;
									needGetMouseMessage = false;
									onlyOneNodeCode = false;
				let value = this.value;
				document.getElementsByTagName('body')[0].removeChild(this);
				if (value == 0)
				{
					manyTimesHandle = false;
					allNodeCode = false;
				}
				if (value == 1)
				{
					manyTimesHandle = true;
					allNodeCode = false;
				}
				if (value == 2)
				{
					manyTimesHandle = false;
					allNodeCode = true;
				}
			if (value == 3)
				{
					manyTimesHandle = true;
					allNodeCode = true;
				}
				if (value == 4)
				{
		let htmlString = document.getElementsByTagName('html')[0].innerHTML.replace(/\n/g, '\r\n');
		htmlString += ("\r\n\r\n" + window.location.href);
		manyTimesCode += htmlString;
		PrintCode();
	}
	if (value == 5)
				{
					needGetHotkeyMessage = true;
					needGetMouseMessage = true;
					manyTimesHandle = true;
					allNodeCode = false;
				}
				if (value == 6)
				{
					needGetMouseMessage = true;
					manyTimesHandle = true;
					allNodeCode = false;
				}
				if (value == 7)
				{
					needGetHotkeyMessage = true;
					manyTimesHandle = true;
					allNodeCode = false;
				}
				if (value == 8)
				{
					needGetMouseMessage = true;
					manyTimesHandle = true;
					allNodeCode = false;
					onlyOneNodeCode = true;
				}
				if (value == 9)
				{
					needGetHotkeyMessage = true;
					manyTimesHandle = true;
					allNodeCode = false;
					onlyOneNodeCode = true;
				}
				if (value == 10)
				{
					needGetHotkeyMessage = true;
					needGetMouseMessage = true;
					manyTimesHandle = true;
					allNodeCode = false;
					onlyOneNodeCode = true;
				}
				if (value == 11)
				{
					if (observer1 != null)
observer1.observe(document.body, {childList:true, subtree:true});
					manyTimesHandle = true;
					allNodeCode = false;
					onlyOneNodeCode = false;
				}
				if (value == 12)
				{
					if (observer1 != null)
observer1.observe(document.body, {childList:true, subtree:true});
					manyTimesHandle = true;
					allNodeCode = false;
					onlyOneNodeCode = true;
				}
				if (value == 13)
				{
					if (observer1 != null)
observer1.observe(document.body, {attributes:true, childList:true, subtree:true, characterData:true});
					manyTimesHandle = true;
					allNodeCode = false;
					onlyOneNodeCode = false;
				}
				if (value == 14)
				{
					if (observer1 != null)
observer1.observe(document.body, {attributes:true, childList:true, subtree:true, characterData:true});
					manyTimesHandle = true;
					allNodeCode = false;
					onlyOneNodeCode = true;
				}
			}
			}
	}


	function PrintCode()
	{
		if (window.location.href.search(/^http:\/\/.+/i) == -1)
		{
			navigator.clipboard.writeText(manyTimesCode);
			if ((needGetHotkeyMessage === false) && (needGetMouseMessage === false))
		window.setTimeout(function()
		{
			alert("源代码已复制");
		}, 1000)
		}
		else {
			if (!manyTimesHandle)
				window.setTimeout(function()
				{
					CreateSourceCodeTextarea();
				},1000)
		}
	}

}, 0)