// ==UserScript==
// @name 搜索增强
// @namespace
// @version 0.3
// @description 使视障人士更方便的使用百度搜索和网页内搜索,更容易的获取所搜索到的网页的内容,并能快速判断网页的有用程度。
// @author 流水
// @include http*
// @grant GM_xmlhttpRequest
// ==/UserScript==
window.setTimeout(function()
{
var hotKey = true, nodeIndexForward = 0, dataForSearch = [], resultForKeyword = [], h3FromBaidu = '', intervalForFocus = null, keywordIndex = -1, beSetTabindexArray = [], keywordFromThis = [], accessToken = '', audioList = [], ttsFirst = false;
var lsMessageObject = {origin:'', dataFromBaidu:'', load:false, name:'lsMessage'};
window.addEventListener('keydown', function(event)
{
if (!window.event.shiftKey && !window.event.ctrlKey && window.event.altKey && hotKey && window.event.keyCode == 49)
{
if (window.location.href.search(/^https:\/\/www\.baidu\.com.+/i) != -1)
{
var links = document.getElementsByTagName('a');
var length = links.length, index = 0;
if (links[length - 4].innerHTML.indexOf('下一页') != -1)
{
var lastH3 = h3FromBaidu;
links[length - 4].click();
}
else {
ShowMessage('未找到下一页链接!');
return false;
}
intervalForFocus = window.setInterval(function()
{
++index;
if (index > 20)
clearInterval(intervalForFocus);
var tempH3 = document.querySelector('h3');
if (!tempH3)
return false;
else {
tempH3 = tempH3.innerHTML;
if (tempH3 === lastH3)
return false;
else {
document.querySelector('h3 a').focus();
clearInterval(intervalForFocus);
}
}
}, 500);
}
else {
SearchKeywordFromHTML();
if (keywordFromThis.length < 1)
return false;
(keywordIndex < keywordFromThis.length - 1) ? (++keywordIndex) : (keywordIndex = -1);
ClearFocus();
(keywordIndex != -1) ? ShowMessage(keywordFromThis[keywordIndex]) : ShowMessage(keywordFromThis);
}
}
if (window.event.shiftKey && !window.event.ctrlKey && window.event.altKey && hotKey && window.event.keyCode == 49)
{
if (window.location.href.search(/^https:\/\/www\.baidu\.com.+/i) != -1)
return false;
SearchKeywordFromHTML();
if (keywordFromThis.length < 1)
return false;
(keywordIndex === -1) ? (keywordIndex = keywordFromThis.length - 1) : (--keywordIndex);
ClearFocus();
(keywordIndex != -1) ? ShowMessage(keywordFromThis[keywordIndex]) : ShowMessage(keywordFromThis);
}
if (!window.event.ctrlKey && !window.event.shiftKey && window.event.altKey && hotKey && window.event.keyCode == 53)
{
if (!ttsFirst)
{
InitForTTS();
ttsFirst = true;
window.setTimeout(function()
{
ShowMessage('开始使用百度语音');
}, 200);
}
else {
ShowMessage('百度语音使用完毕');
ttsFirst = false;
window.setTimeout(function()
{
var audio = document.querySelector('audio.ls-audio-notice');
if (audio)
audio.parentNode.removeChild(audio);
}, 1000);
}
}
if (!window.event.ctrlKey && !window.event.shiftKey && !window.event.altKey && hotKey && window.event.keyCode == 27)
{
var audio = document.querySelector('audio.ls-audio-notice');
if (!audio || !audio.getAttribute('src') || audio.ended)
return false;
audio.pause();
}
if (!window.event.ctrlKey && !window.event.shiftKey && window.event.altKey && hotKey && window.event.keyCode == 50)
{
GetResultForKeyword();
if (keywordFromThis.length < 1)
return false;
var noticeString = '', noticeKeyword = '', htmlText = document.getElementsByTagName('body')[0].innerHTML;
if (keywordIndex === -1)
{
for (var i = 0; i < keywordFromThis.length; ++i)
{
noticeKeyword += keywordFromThis[i] + ',';
}
}
for (var i = 0; i < resultForKeyword.length; ++i)
{
var start = resultForKeyword[i].index + resultForKeyword[i][0].length;
var tempResult = resultForKeyword[i][0];
if (tempResult.indexOf('>') != -1)
{
tempResult = tempResult.slice(tempResult.indexOf('>') + 1);
tempResult += htmlText.slice(start, htmlText.indexOf('<', start));
}
else {
var singleQuote = /(\=\s*\')([^']*)$/;
var doubleQuote = /(\=\s*\")([^"]*$)/;
singleQuote = singleQuote.exec(tempResult);
doubleQuote = doubleQuote.exec(tempResult);
if (singleQuote && !doubleQuote)
{
tempResult = singleQuote[2];
tempResult += htmlText.slice(start, htmlText.indexOf("\'", start));
}
if (!singleQuote && doubleQuote)
{
tempResult = doubleQuote[2];
tempResult += htmlText.slice(start, htmlText.indexOf('\"', start));
}
if (!singleQuote && !doubleQuote)
{
tempResult = '';
}
if (singleQuote && doubleQuote)
{
if (singleQuote.index < doubleQuote.index)
{
tempResult = doubleQuote[2];
tempResult += htmlText.slice(start, htmlText.indexOf('\"', start));
}
else {
tempResult = singleQuote[2];
tempResult += htmlText.slice(start, htmlText.indexOf("\'", start));
}
}
}
tempResult = tempResult.replace(/ /gi, ' ');
tempResult += '\r\n';
if (noticeString.indexOf(tempResult) === -1)
noticeString += tempResult;
}
if (keywordIndex === -1)
{
(noticeString.length === 0) ? ShowMessage('网页出现了关键词' + noticeKeyword + '没有搜索到与之相关的内容') : ShowMessage('网页出现了关键词' + noticeKeyword + '下面是与之相关的内容:' + noticeString);
}
else {
(noticeString.length === 0) ? ShowMessage('没有与' + keywordFromThis[keywordIndex] + '相关的内容') : ShowMessage('与' + keywordFromThis[keywordIndex] + '相关的内容为:' + noticeString);
}
}
if (!window.event.shiftKey && !window.event.ctrlKey && window.event.altKey && window.event.keyCode == 48)
{
if (hotKey)
{
hotKey = false;
ShowMessage('快捷键已禁用!');
}
else {
hotKey = true;
ShowMessage('快捷键已启用!');
}
}
if (!window.event.shiftKey && !window.event.ctrlKey && window.event.altKey && hotKey && window.event.keyCode == 51)
{
if (window.location.href.search(/^https:\/\/www\.baidu\.com.+/i) != -1)
{
ReviseBaiduTo();
}
else {
if ((nodeIndexForward === 0) && !document.querySelector('.lsUselessButton0'))
{
GetResultForKeyword();
if (keywordFromThis.length < 1)
return false;
var htmlText = document.getElementsByTagName('body')[0].innerHTML;
var myClass = /lsUselessButton-?\d*/;
var needlessTabindexNode = ['a', 'area', 'label', 'select', 'button', 'textarea'];
var useParentNode = ['br', 'b', 'i', 'span'];
var length = resultForKeyword.length, nodeIndex = 0;
for (var i = 0; i < resultForKeyword.length; ++i)
{
var hasSlash = true, beSetTabindex = true, needlessTabindex = false;
var keyword = resultForKeyword[length - 1 - i][2];
(keyword.indexOf('/') === -1) ? (hasSlash = false) : (keyword = keyword.replace('/', ''));
var reg = new RegExp('(<)' + keyword + '(\\s|>|\/\\s*>)', 'gim');
reg.compile(reg);
var index = 0, i2 = 0, i3 = 0;
while ((i2 != -1) && (i3 - 1 < resultForKeyword[length - 1 - i].index))
{
if (i3 === 0)
{
i2 = htmlText.search(reg);
}
if (i3 > 0)
{
i2 = htmlText.slice(i3).search(reg);
}
if (i2 != -1)
{
++index;
}
i3 += (i2 + 1);
}
var node = (hasSlash) ? (document.getElementsByTagName(keyword)[index - 1].parentNode) : (document.getElementsByTagName(keyword)[index - 1]);
for (var i5 = 0; i5 < useParentNode.length; ++i5)
{
if ( node && (useParentNode[i5] === node.tagName.toLowerCase()))
{
if (node.parentNode.tagName.toLowerCase() != 'body')
{
node = node.parentNode;
}
break;
}
}
if (!node || document.querySelector('.lsUselessButton' + (0 - nodeIndex)) || (node.innerHTML.search(myClass) != -1))
continue;
if (node.getAttribute('class'))
{
if (node.getAttribute('class').search(myClass) != -1)
continue;
}
for (var i4 = 0; i4 < needlessTabindexNode.length; ++i4)
{
if (needlessTabindexNode[i4] === node.tagName.toLowerCase())
{
needlessTabindex = true;
break;
}
}
if (!needlessTabindex)
{
(node.getAttribute('tabindex') == null) ? node.setAttribute('tabindex', '-1') : beSetTabindex = false;
}
node.classList.add('lsUselessButton' + (0 - nodeIndex));
beSetTabindexArray[nodeIndex] = beSetTabindex;
++nodeIndex;
}
}
var nodeObject = document.querySelector('.lsUselessButton' + (nodeIndexForward - (beSetTabindexArray.length - 1)));
if (nodeObject)
{
nodeObject.focus();
++nodeIndexForward;
}
else{
ShowMessage('已到最后一项。');
}
}
}
if (window.event.shiftKey && !window.event.ctrlKey && window.event.altKey && hotKey && window.event.keyCode == 51)
{
if (dataForSearch.length < 1)
{
ShowMessage('没有获取到关键词,无法进行下一步操作。');
return false;
}
(nodeIndexForward <= 0) ? ShowMessage('已到第一项。') : --nodeIndexForward;
var nodeObject = document.querySelector('.lsUselessButton' + (nodeIndexForward - (beSetTabindexArray.length - 1)))
if (nodeObject)
{
nodeObject.focus();
}
}
if (!window.event.ctrlKey && !window.event.shiftKey && window.event.altKey && hotKey && window.event.keyCode == 52)
{
ClearFocus();
keywordIndex = -1;
var data = prompt('请输入要搜索的关键词,中间用空格或竖杠分开');
(data != null && data != '') ? SetDataForSearch(data) : ShowMessage('没有获取到正确的输入');
}
})
window.addEventListener('load', function()
{
lsMessageObject.origin = self.location.protocol + '\/\/' + self.location.hostname;
lsMessageObject.load = true;
if (window.opener)
{
window.opener.postMessage(lsMessageObject, '*');
}
if (ttsFirst)
{
InitForTTS();
}
RemoveIframes();
})
window.addEventListener('message', function(event)
{
if (event.data.name === 'lsMessage')
{
if (event.data.dataFromBaidu && !lsMessageObject.dataFromBaidu)
{
lsMessageObject.dataFromBaidu = event.data.dataFromBaidu;
SetDataForSearch();
}
if (!event.data.dataFromBaidu && lsMessageObject.dataFromBaidu)
{
event.source.postMessage(lsMessageObject, '*');
}
}
})
function ReviseBaiduTo()
{
if (window.location.href.search(/^https:\/\/www\.baidu\.com.+/i) == -1)
return false;
var title = document.querySelector('head title').text;
if (lsMessageObject.dataFromBaidu != title)
{
lsMessageObject.dataFromBaidu = title;
}
var linksForBaidu = document.querySelectorAll('h3 a');
for (var i = 0; i < linksForBaidu.length; ++i)
{
linksForBaidu[i].onclick = function()
{
var windowFromBaidu = window.open(this.getAttribute('href'));
setTimeout(function()
{
windowFromBaidu.postMessage(lsMessageObject, '*');
}, 3000);
return false;
}
}
linksForBaidu = null;
}
function GetResultForKeyword()
{
SearchKeywordFromHTML();
if (keywordFromThis.length < 1)
return false;
var needlessNode = ['input', 'script'];
var htmlText = document.getElementsByTagName('body')[0].innerHTML;
resultForKeyword = [];
var index = 0, keyword = [];
(keywordIndex === -1) ? (keyword = keywordFromThis) : (keyword[0] = keywordFromThis[keywordIndex]);
for (var i = 0; i < keyword.length; ++i)
{
var reg = new RegExp('(<)(\/?\\w+)(\\s|>|\/\\s*>)([^<]*)(?=' + keyword[i] + ')', 'gim');
reg.compile(reg);
var tempResult = reg.exec(htmlText);
while (tempResult != null)
{
var repeated = false, isNeedlessNode = false;
for (var i2 = 0; i2 < needlessNode.length; ++i2)
{
if (tempResult[2].toLowerCase().indexOf(needlessNode[i2]) != -1)
{
isNeedlessNode = true;
break;
}
}
for (var i2 = 0; i2 < resultForKeyword.length; ++i2)
{
if (tempResult.index === resultForKeyword[i2].index)
{
repeated = true;
break;
}
}
if (!repeated && !isNeedlessNode)
{
resultForKeyword[index] = tempResult;
++index;
}
tempResult = reg.exec(htmlText);
}
reg = null;
}
resultForKeyword.sort(function(a, b)
{
return a.index - b.index;
});
}
function RemoveIframes()
{
var urlArray = [/https:\/\/pos\.baidu\.com/i, /https:\/\/g\.fastapi\.net/i];
var needLessFrames = [], index = 0;
for (var i = 0; i < urlArray.length; ++i)
{
var framesObject = document.getElementsByTagName('iframe');
for (var i2 = 0; i2 < framesObject.length; ++i2)
{
if (!framesObject[i2])
continue;
var src = framesObject[i2].getAttribute('src');
if (src && (src.search(urlArray[i]) != -1))
{
needLessFrames[index] = framesObject[i2];
++index;
}
}
}
for (var i = 0; i < needLessFrames.length; ++i)
{
needLessFrames[i].parentNode.removeChild(needLessFrames[i]);
}
}
function ClearFocus()
{
for (var i = 0; i < beSetTabindexArray.length; ++i)
{
var node = document.querySelector('.lsUselessButton' + (i - (beSetTabindexArray.length - 1)));
if (node && node.getAttribute('tabindex') && beSetTabindexArray[beSetTabindexArray.length - 1 - i])
{
node.removeAttribute('tabindex');
}
if (node && node.getAttribute('class'))
{
node.classList.remove('lsUselessButton' + (i - (beSetTabindexArray.length - 1)));
}
}
nodeIndexForward = 0;
beSetTabindexArray = [];
}
function SetDataForSearch(data)
{
dataForSearch = [];
if (!lsMessageObject.dataFromBaidu && !arguments[0])
return false;
var cut_off = '', cut_offArray = ['|', ' '];
var end = lsMessageObject.dataFromBaidu.indexOf('_百度搜索');
data = (arguments[0] ? arguments[0] : lsMessageObject.dataFromBaidu.slice(0, end));
for (var i = 0; i < cut_offArray.length; ++i)
{
if (data.indexOf(cut_offArray[i]) != -1)
{
cut_off = cut_offArray[i];
break;
}
}
if (!cut_off)
{
dataForSearch[0] = data;
}
else {
var reg = new RegExp('([^' + cut_off + ']+)', 'gim');
var needSpace = /[a-zA-Z\d]/;
var keyword = [], index = 0, keywordCount = 0, tempResult = '';
tempResult = reg.exec(data);
while (tempResult)
{
keyword[index] = tempResult[1];
++index;
tempResult = reg.exec(data);
}
keywordCount = index;
for (var i = 0; i < keywordCount; ++i)
{
dataForSearch[i] = keyword[i];
}
if (keywordCount > 1)
{
for (var i =0; i < keywordCount - 1; ++i)
{
for (var i2 = i + 1; i2 < keywordCount; ++i2)
{
dataForSearch[index] = (needSpace.test(keyword[i].slice(keyword[i].length - 1, keyword[i].length)) && needSpace.test(keyword[i2].slice(0, 1))) ? (keyword[i] + ' ' + keyword[i2]) : (keyword[i] + keyword[i2]);
++index;
dataForSearch[index] = (needSpace.test(keyword[i2].slice(keyword[i2].length - 1, keyword[i2].length)) && needSpace.test(keyword[i].slice(0, 1))) ? (keyword[i2] + ' ' + keyword[i]) : (keyword[i2] + keyword[i]);
++index;
}
}
}
if (keywordCount > 2)
{
for (var i = 0; i < keywordCount; ++i)
{
if (i ===0)
{
dataForSearch[index] = '';
}
var length = dataForSearch[index].length;
((length > 0) && needSpace.test(dataForSearch[index].slice(length - 1, length)) && needSpace.test(keyword[i].slice(0, 1))) ? (dataForSearch[index] += ' ' + keyword[i]) : (dataForSearch[index] += keyword[i]);
}
}
}
PlaySound();
}
function SearchKeywordFromHTML()
{
keywordFromThis = [];
if (dataForSearch.length < 1)
{
ShowMessage('没有获取到关键词,无法进行下一步操作。');
return false;
}
var index = 0, htmlText = document.getElementsByTagName('body')[0].innerHTML;
for (var i = 0; i < dataForSearch.length; ++i)
{
if (htmlText.indexOf(dataForSearch[i]) != -1)
{
keywordFromThis[index] = dataForSearch[i];
++index;
}
}
if (index < 1)
UseTTS('没有在网页中搜索到任何关键词');
}
function PlaySound()
{
var audioContext = new AudioContext();
var oscillator = audioContext.createOscillator();
var gainNode = audioContext.createGain();
oscillator.connect(gainNode);
gainNode.connect(audioContext.destination);
oscillator.type = 'sine';
oscillator.frequency.value = 400.00;
gainNode.gain.setValueAtTime(0, audioContext.currentTime);
gainNode.gain.linearRampToValueAtTime(1, audioContext.currentTime + 0.01);
oscillator.start(audioContext.currentTime);
gainNode.gain.exponentialRampToValueAtTime(0.001, audioContext.currentTime + 1);
oscillator.stop(audioContext.currentTime + 1);
}
window.setTimeout(function()
{
if (window.location.href.search(/^https:\/\/www\.baidu\.com.+/i) != -1)
{
window.setInterval(function()
{
var tempH3 = document.querySelector('h3');
if (!tempH3)
{
h3FromBaidu = '';
return false;
}
else {
var text = tempH3.innerHTML;
if (text == h3FromBaidu)
return false;
else {
h3FromBaidu = text;
ReviseBaiduTo();
}
}
}, 1000);
}
}, 3000)
function ShowMessage(data)
{
if (!data)
return false;
if (ttsFirst)
{
var audio = document.querySelector('audio.ls-audio-notice');
if (!audio)
return false;
var dataArray = [];
if (data.length <= 512)
{
dataArray[0] = data;
}
else {
var start = end = index = 0, length = data.length;
cut_off = [/.。/, /.,/, /.;/, /\D\.\D/, /\D,\D/, /.;/];
while (start < length)
{
if (length > start + 400)
{
for (var i = 0; i < cut_off.length; ++i)
{
end = (length > start + 512) ? data.slice(start + 400, start + 512).search(cut_off[i]) : data.slice(start + 400, length).search(cut_off[i]);
if (end != -1)
{
end += (start + 400 + 2);
dataArray[index] = data.slice(start, end);
break;
}
}
if (end === -1)
{
end = (length > start + 512) ? (start + 512) : (length);
dataArray[index] = data.slice(start, end);
}
start = end;
}
else {
dataArray[index] = data.slice(start, length);
start = length;
}
++index;
}
dataArray.reverse();
}
if (!audio.ended && audio.getAttribute('src'))
{
audio.removeEventListener('ended', PlayList);
audio.pause();
}
UseTTS(dataArray.pop());
if (dataArray.length > 0)
{
audioList = dataArray;
audio.addEventListener('ended', PlayList);
}
}
else {
alert(data);
}
}
function PlayList()
{
(audioList.length > 0) ? UseTTS(audioList.pop()) : audio.removeEventListener('ended', PlayList);
}
function InitForTTS()
{
if (!accessToken)
{
GM_xmlhttpRequest({
method: "GET",
headers: { "Accept": "Content-Type:application/json" },
url: "https://openapi.baidu.com/oauth/2.0/token?grant_type=client_credentials&client_id=DmRzeWmTGgwPuPrFyHPhxLFH&client_secret=iYUz9bmANfuDBhlpacObRCq4qutDHfSe",
onload: function (response)
{
var data = response.responseText;
var datas = JSON.parse(data);
accessToken = datas.access_token;
}
});
}
var audio = document.querySelector('audio.ls-audio-notice');
if (audio)
return false;
audio = document.createElement('audio');
audio.className = 'ls-audio-notice';
audio.src = "";
audio.volume = 0.6;
document.body.appendChild(audio);
}
function UseTTS(TTStext)
{
var audio = document.querySelector('audio.ls-audio-notice');
if (!audio || !accessToken)
return false;
var zhText = encodeURI(TTStext);
var parameter = "&vol=9&per=0&spd=9&pit=4";
var voicebbUrl = "https://tsn.baidu.com/text2audio?lan=zh&ctp=1&cuid=xiaobo&tok=" + accessToken + "&tex=" + zhText + parameter;
audio.src = voicebbUrl;
audio.playbackRate = 1.7;
audio.play();
}
}, 0)