您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Downloading the queries csv export for free subscription users
// ==UserScript== // @name Dune Csv Export // @namespace http://tampermonkey.net/ // @version 0.2.6 // @description Downloading the queries csv export for free subscription users // @author lulu // @match https://dune.com/queries* // @icon https://www.google.com/s2/favicons?sz=64&domain=dune.com // @grant none // @require https://ajax.googleapis.com/ajax/libs/jquery/3.4.0/jquery.min.js // ==/UserScript== function getElementByXpath(path){ return document.evaluate(path, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue; } function getNextButton(){ let path0 = '//*[@id="results"]/div/div[2]/div/div[2]/ul/li[5]/button'; let path1 = '//*[@id="results"]/div/div[2]/div/div[2]/ul/li[6]/button'; let btn = getElementByXpath(path0); if (btn === null){ btn = getElementByXpath(path1); } // console.log("BTN:", btn) return btn; } function getHeaders(table){ const headers = []; $.each($(table).find("thead").find("tr").find("th"), function (key, val2) { headers[key] = $(val2).text(); //$(val2).find("div").text(); }); return headers; } async function getCurrentTableValues(){ const maxAttempts = 100; // Adjust as needed - determines maximum wait time. 50 attempts * 100ms = 5 seconds let attempt = 0; let table = null; const values = []; while (attempt < maxAttempts) { table = getElementByXpath('//*[@id="results"]/div/div[2]/div/div[1]/table'); if (table !== null && table !== undefined ) { // check for both null and undefined break; } // console.log("Table is Null, Waiting and Trying again.., attemp: ", attempt); // Object is null or undefined, wait and retry await new Promise(resolve => setTimeout(resolve, 100)); attempt++; } if (table === null || table === undefined ) { // check for both null and undefined console.log("Table Did not collected after 100 attempts, Returning Empty!"); return values; } $.each($(table).find("tbody tr"), function(rowIndex, rowElement) { const row = []; $.each($(rowElement).find("td"), function(cellIndex, cellElement) { const cellValue = $(cellElement).find("div").first().text(); row.push(cellValue.trim()); }); values.push(row); }); // console.log("VALUES:", values); return values; } async function collect_pages(){ let table = getElementByXpath('//*[@id="results"]/div/div[2]/div/div[1]/table'); let custom_limit = document.getElementById("customRowLimit").value; const limit = (str => str.trim() === '' ? null : parseInt(str))(custom_limit); let hasNextPage = true; let collectedData = []; do { const currValues = await getCurrentTableValues(); collectedData.push(...currValues); const nextButton = getNextButton(); hasNextPage = Boolean( nextButton && !$(nextButton).is(":disabled") && !nextButton.disabled ); if (!$(nextButton).is(":disabled") && nextButton != null){ $(nextButton).trigger("click"); await new Promise(resolve => setTimeout(resolve, 20)); } if (limit != null && collectedData.length >= limit) { break } } while (hasNextPage) const headers = getHeaders(table); download_csv(headers, collectedData); } function escapeCsvValue(value) { if (typeof value !== 'string') value = String(value); value = value.replace(/"/g, '""'); return `"${value}"`; } function download_csv(headers, rows) { let csvHeaders = headers.join(",") + "\n"; // let csvRows = rows.map(row => row.join(",")).join("\n"); let csvRows = rows.map(row => row.map(escapeCsvValue).join(",")).join("\n"); let csvButton = getElementByXpath('//*[@id="results"]/div/div[1]/div[1]/div/button'); let custom_name = document.getElementById("customNameCsvFileFree").value; var downloadBtn = document.createElement("a"); downloadBtn.href = "data:text/csv;charset=utf-8,"+encodeURI(csvHeaders+csvRows); downloadBtn.target = "_blank"; if (custom_name.length > 1) { downloadBtn.download = custom_name+".csv"; } else { let url = window.location.href; downloadBtn.download = "query_"+url.split("queries/")[1].replace("/", "_")+".csv" } downloadBtn.click(); csvButton.disabled = false; } async function collectCsv() { let csvButton = getElementByXpath('//*[@id="results"]/div/div[1]/div[1]/div/button'); csvButton.disabled = "disabled"; let nextButton = getNextButton(); //getElementByXpath('//*[@id="results"]/div/div[2]/div/div[2]/ul/li[5]/button'); if (nextButton == null){ // console.log("Butt not exists"); await collect_pages(); } else { // go to first let firstPageBtn = getElementByXpath('//*[@id="results"]/div/div[2]/div/div[2]/ul/li[3]/button'); if (firstPageBtn != null && !$(firstPageBtn).is(":disabled")){ $(firstPageBtn).trigger("click"); await new Promise(resolve => setTimeout(resolve, 5)); await collect_pages(); } else { await collect_pages(); } } } function changeCsvButton(){ // console.log("Running Dune Script"); let csvButton = getElementByXpath('//*[@id="results"]/div/div[1]/div[1]/div/button'); if (csvButton != null){ csvButton.disabled = false; csvButton.onclick = collectCsv; // adding a input for custom csv file name var inp_element = document.createElement('input'); inp_element.className = "IconButton_iconButton___v3YQ buttonThemes_button__jfRFC buttonThemes_theme-tertiary__v7VoN IconButton_size-M__FIXfN"; inp_element.id = "customNameCsvFileFree"; inp_element.placeholder = "Custom filename"; var limit_inp_element = document.createElement('input'); limit_inp_element.className = "IconButton_iconButton___v3YQ buttonThemes_button__jfRFC buttonThemes_theme-tertiary__v7VoN IconButton_size-M__FIXfN"; limit_inp_element.id = "customRowLimit"; limit_inp_element.placeholder = "Limit Csv Rows"; limit_inp_element.type = 'number'; limit_inp_element.min = '0'; getElementByXpath('//*[@id="results"]/div/div[1]/div[1]').appendChild(inp_element); getElementByXpath('//*[@id="results"]/div/div[1]/div[1]').appendChild(limit_inp_element); // console.log("BTN CREATED"); } else { setTimeout(()=>{ changeCsvButton(); }, 1000) } } (function() { 'use strict'; $(document).ready ( function(){ changeCsvButton(); // for (let i = 0; i < 10; i++) {} }); })();