';
let stopInfiniteScroll = false;
if(GM_getValue('DisableInfiniteScroll') == undefined) {
GM_setValue('DisableInfiniteScroll', false);
}
if(GM_getValue('DisableInfiniteScroll') == true) {
stopInfiniteScroll = true;
}
function getQueryVariable(variable) {
let query = window.location.search.substring(1);
let vars = query.split('&');
for (let i = 0; i < vars.length; i++) {
let pair = vars[i].split('=');
if (decodeURIComponent(pair[0]) == variable) {
return decodeURIComponent(pair[1]);
}
}
console.log('Query variable %s not found', variable);
}
/* generate a download */
function s2ab(s) {
let buf = new ArrayBuffer(s.length);
let view = new Uint8Array(buf);
for (let i=0; i!=s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF;
return buf;
}
function downloadUrlExcelFile(data) {
// EXCEL
/* this line is only needed if you are not adding a script tag reference */
if(typeof XLSX == 'undefined') XLSX = require('xlsx');
/* make the workbook */
let wb = XLSX.utils.book_new();
for (let j = 0; j < data.length; j++) {
/* make the worksheet */
let ws = XLSX.utils.json_to_sheet( data[j].values, {skipHeader: 1});
XLSX.utils.book_append_sheet(wb, ws, data[j].name);
}
/* write workbook (use type 'binary') */
let wbout = XLSX.write(wb, {bookType:'xlsx', type:'binary'});
let searchTerm = getQueryVariable('q');
saveAs(new Blob([s2ab(wbout)],{type:"application/octet-stream"}), searchTerm + "-google.xlsx");
}
function getListOfText(texts) {
let values = [];
let length = texts.snapshotLength;
let j = 0;
// all this nonsense is because xpath doesn't concat the text of sub elements. We have to look for spaces and concat ourselves
//
test test test
// Looking at the text content of the div would return 3 results, "test ", "test", and " test"
// so we concat by hand looking for the spaces
while (j < length) {
let string = texts.snapshotItem(j).textContent;
let lastChar = string.slice(-1);
while (lastChar == ' ' || ((j + 1) < length && texts.snapshotItem(j + 1).textContent.charAt(0) == ' ')) {
if(lastChar == ' ' ) {
j++;
string = string + texts.snapshotItem(j).textContent;
} else if ((j + 1) < length && texts.snapshotItem(j + 1).textContent.charAt(0) == ' ') {
j++;
string = string + texts.snapshotItem(j).textContent;
}
lastChar = string.slice(-1);
}
values.push(string);
j++;
}
return values;
}
function getListOfCleanHrefsFromAnchorElements(elements) {
let hrefs = [];
for (let j = 0; j < elements.snapshotLength; j++) {
let href = elements.snapshotItem(j).getAttribute('href');
if(href == null) {
continue;
}
if (href.indexOf('//') === 0) {
href = "https:" + href;
}
if (href.indexOf('.googleusercontent.com') != -1) {
continue;
}
if (href.indexOf('.google.com') != -1 && href.indexOf('.googleadservices.com') == -1) {
continue;
}
if (href.indexOf('http') != 0) {
continue;
}
hrefs.push(href);
}
return hrefs;
}
let moreResultsButtonsPushedCount = 0;
let maxMoreResultsClicks = 20;
let googleOrganicCount = 0;
let googleCategories = [
{
'xPath': "//h3[text()='Top stories']/../../../../..//div//a",
'name': "Top Stories",
'listType': 'ul',
},
{
'xPath': "//div[@id='tads']//li[@class='ads-ad']//div[@class='ad_cclk']/a[not(@style)]",
'name': "Top Ads",
'listType': 'ul',
},
{
'xPath': "//h3[text()='Videos']/../..//a",
'name': "Videos",
'listType': 'ul',
},
{
'xPath': "//h2[text()='People also ask']/../..//div[contains(@class, 'match-mod-horizontal-padding')]/text()",
'name': "People Also Ask",
'listType': 'ul',
'type': 'text',
},
{
'xPath': "//div[@class='g mnr-c g-blk' and .//a[normalize-space(text())='About Featured Snippets']]//div[@class='r']/a",
'name': "Snippet",
'listType': 'ul',
},
{
'xPath': "//div/h1[text()='Complementary Results']/..//a",
'name': "Right Side Box",
'listType': 'ul',
},
{
'xPath': "//h2[text()='Local Results']/..//div[text()='Website']/../..",
'name': "Map",
'listType': 'ul',
},
{
'xPath': "//div[(@id='search' or @id='botstuff')]//div[contains(@class, 'g')]/div//div/div//a",
'name': "Organic Results",
'listType': 'ol',
},
{
'xPath': "//div[@id='bottomads']//li[@class='ads-ad']//div[@class='ad_cclk']/a[not(contains(@style,'display:none'))]",
'name': "Bottom Ads",
'listType': 'ul',
},
{
'xPath': "//span[text()='Related searches']/../../div//a//text()",
'name': "Related Search",
'listType': 'ul',
'type': 'text',
},
{
'xPath': "//div[@id='bres']//div[@class='VLkRKc']//text()",
'name': "Other Topics",
'listType': 'ul',
'type': 'text',
'subValueXPath': "//div[@class='VLkRKc' and text()='{{text}}']/../../..//a[@title]/@title"
},
{
'xPath': "//div[@class='brs_col']//a//text()",
'name': "Searches Related To",
'listType': 'ul',
'type': 'text',
},
];
function handleGoogle() {
let exportData = [];
//console.log("in handleGoogle");
setTimeout(function () {
//console.log("in handleGoogle and looking for a button");
let button = document.evaluate("//*[text()='More results']", document, null,XPathResult.FIRST_ORDERED_NODE_TYPE, null);
if(button.singleNodeValue && !stopInfiniteScroll) {
//console.log("I see a button!");
button.singleNodeValue.click();
document.getElementById('timesClicked').innerHTML = ++timesClicked;
}
//console.log(button);
/*
// This triggers a page load which is kind of annoying. I am commenting this out for now
// look for omitted results too
button = document.evaluate("//*[text()='repeat the search with the omitted results included']", document, null,XPathResult.FIRST_ORDERED_NODE_TYPE, null);
if(button.singleNodeValue && !stopInfiniteScroll) {
button.singleNodeValue.click();
}
*/
//console.log("finished handleGoogle");
}, 1500)
for (let a = 0; a < googleCategories.length; a++) {
let tags = document.evaluate(googleCategories[a].xPath, document, null,XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
if (tags.snapshotLength == 0) {
continue;
}
if (googleCategories[a].name == 'Organic Results') {
googleOrganicCount = tags.snapshotLength;
}
let values = [];
if(googleCategories[a].type == 'text') {
values = getListOfText(tags);
} else {
values = getListOfCleanHrefsFromAnchorElements(tags);
}
if (googleCategories[a].subValueXPath !== undefined) {
for (let j = 0; j < tags.snapshotLength; j++) {
let topic = tags.snapshotItem(j).textContent;
let xPath = googleCategories[a].subValueXPath.replace("{{text}}", topic);
let subTags = document.evaluate(xPath, document, null,XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
values = getListOfText(subTags);
let data = {
name: "Topic - " + topic,
listType: googleCategories[a].listType,
values: [],
};
for (let i = 0; i < values.length; i++) {
data.values.push({value: values[i]});
}
exportData.push(data);
}
} else {
let data = {
name: googleCategories[a].name,
listType: googleCategories[a].listType,
values: [],
};
for (let i = 0; i < values.length; i++) {
data.values.push({value: values[i]});
}
exportData.push(data);
}
}
let html = '';
let urls = [];
for (let x = 0; x < exportData.length; x++) {
html += '
' + exportData[x].name + '
';
html += '<' + exportData[x].listType + '>';
let style = '';
if (exportData[x].listType == 'ol') {
style = 'style="list-style:decimal"';
}
for (let i = 0; i < exportData[x].values.length; i++) {
let url = exportData[x].values[i].value;
// remove everything after a # in the url
url = url.split('#')[0];
if (url.startsWith("http")) {
urls.push(url);
}
}
urls = [...new Set(urls)]; // uniques array
for (let i = 0; i < urls.length; i++) {
html += '
';
if(urls[i].startsWith("http")) {
html += "" + urls[i] + "";
} else {
html += urls[i];
}
html += '
';
}
html += '' + exportData[x].listType + '>';
}
document.getElementById('googleSERPResults').innerHTML = html;
document.getElementById('copyToClipboard').addEventListener('click', function(){
navigator.clipboard.writeText(urls.join("\n"));
});
document.getElementById('downloadUrlExcelFile').addEventListener('click', function(){
downloadUrlExcelFile(exportData)
});
}
var callCount = 0;
function callHandleGoogle() {
//console.log("call count: " + callCount);
if (callCount < maxMoreResultsClicks) {
callCount++;
handleGoogle();
setTimeout(callHandleGoogle, Math.floor(Math.random() * (4000 - 3000 + 1)) + 3000); // 3-4 seconds delay
}
}
if (location.href.indexOf('google.com/search') != -1 && location.href.indexOf('tbm=') == -1 ) {
let div = '";
div += '
';
if(GM_getValue('DisableInfiniteScroll') == true) {
div += ' ';
} else {
div += '';
div += ' ';
}
div += "Times 'More results' Clicked: 0/" + maxMoreResultsClicks + " ";
div += ' ';
div += ' ';
document.getElementById('center_col').innerHTML += div;
callHandleGoogle();
if(GM_getValue('DisableInfiniteScroll') == true) {
document.getElementById('enableInfiniteScroll').addEventListener('click', function(){
GM_setValue('DisableInfiniteScroll', false);
stopInfiniteScroll = false;
startObserver();
handleGoogle();
// change button text
document.getElementById('disableInfiniteScroll').innerHTML = "Auto-clicking enabled";
});
} else {
document.getElementById('stopInfiniteScroll').addEventListener('click', function(){
stopInfiniteScroll = true;
observer.disconnect();
// delete pause button
let element = document.getElementById("stopInfiniteScroll");
element.parentNode.removeChild(element);
});
document.getElementById('disableInfiniteScroll').addEventListener('click', function(){
GM_setValue('DisableInfiniteScroll', true);
observer.disconnect();
stopInfiniteScroll = true;
// change button text
document.getElementById('disableInfiniteScroll').innerHTML = "Auto-clicking disabled";
// disable button
document.getElementById('disableInfiniteScroll').disabled = true;
// delete pause button
let element = document.getElementById("stopInfiniteScroll");
element.parentNode.removeChild(element);
});
}
}
if ( location.href.indexOf('yahoo.com/search') != -1 ) {
let items = document.querySelectorAll('.algo-sr h3 a');
let div = "
" + IMNText + "";
for (let i=0; i < items.length; i++ ) {
let url = items[i].href;
div += "
';
document.getElementById('web').innerHTML += div;
}
if ( location.href.indexOf('ask.com/web') != -1 ) {
let listItems = document.getElementsByClassName('result-link');
let href = "";
let div = '
' + IMNText + '';
for ( let i=0, len=listItems.length; i" + url + ""
}
div += '
';
document.getElementsByClassName('BottomAdsPartial')[0].innerHTML += div;
}
if ( location.href.indexOf('bing.com/') != -1 ) {
let Bresults = document.getElementById('b_results');
let BlistItems = Bresults.getElementsByClassName('scs_c');
let text = "
" + IMNText + "";
for ( let i=0, len=BlistItems.length; i" + resultUrl + "";
}
text += '