Created
July 25, 2020 11:24
-
-
Save Nydhal/65a6750151c3bb56c2fed611208a8efa to your computer and use it in GitHub Desktop.
Scrape all your HN upvoted links and Export to CSV or HTML (from your browser).
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Search HN upvoted from your browser and Export to CSV or HTML. | |
1. Navigate your browser to https://news.ycombinator.com/user?id=YOUR_USER_ID | |
2. Copy code to the browser console and run. | |
4. Look for the popup window in the upper-left corner of your browser. | |
*/ | |
(function () { | |
const popup = createPopup('HN upvoted'); | |
const base = 'news.ycombinator.com'; | |
if (location.host != base || !(location.pathname == '/user' || location.pathname == '/upvoted')) { | |
popup.innerHTML = 'ERROR: Unknown URL, Go to HN user page and try again.'; | |
return; | |
} | |
const id = location.search.split('=')[1]; | |
const types = { | |
csv: { | |
header: 'Title,Link', | |
filename: id + "_HN_upvoted", | |
totype: a => toCSV(a.title, a.link) | |
}, | |
html: { | |
header: '<title>' + id + " HN upvoted</title><h1>" + id + " HN upvoted</h1>", | |
filename: id + "-HN-upvoted", | |
totype: a => `<p><a href="${a.link}" target="_blank" rel="noopener">${a.title}</a>` | |
} | |
}; | |
const upvoted = []; | |
popup.innerHTML = | |
'<button id=exportToCsv data-filetype=csv>Export to CSV</button><br><br>' + | |
'<button id=exportToHtml data-filetype=html>Export to HTML</button><br><br>' + | |
'<input id=query> <button id=search>Search</button><br><br>' + | |
'<div id=results></div>'; | |
exportToCsv.onclick = exportToHtml.onclick = async function () { | |
const filetype = this.dataset.filetype; | |
await getupvoted(); | |
downloadFile(types[filetype].header, upvoted.map(types[filetype].totype), types[filetype].filename, filetype); | |
results.innerHTML = 'Finished exporting.'; | |
}; | |
search.onclick = async function () { | |
const re = new RegExp(query.value, 'i'); | |
await getupvoted(); | |
const found = upvoted.map(types.html.totype).filter(f => f.match(re)); | |
if (found.length == 0) { | |
results.innerHTML = 'not found'; | |
} else { | |
results.innerHTML = found.join(''); | |
} | |
}; | |
async function getupvoted() { | |
if (upvoted.length > 0) return; | |
const url = `https://${base}/upvoted?id=${id}&p=`; | |
for (var p = 1; true; p++) { | |
results.innerHTML = 'Fetching page #' + p + '<br><br>'; | |
const response = await fetch(url + p); | |
const html = await response.text(); | |
const parser = new DOMParser(); | |
const doc = parser.parseFromString(html, "text/html"); | |
doc.querySelectorAll('a.storylink').forEach(a => upvoted.push({title: a.innerText, link: a.href})); | |
if (doc.querySelector('a.morelink') == null) break; | |
} | |
} | |
function createPopup(title) { | |
const div = document.body.appendChild(document.createElement("div")); | |
div.innerHTML = title + " <a onclick='document.body.removeChild(this.parentNode)' style='cursor: pointer; padding: 4px'>X</a><br><br>"; | |
div.style.position = "absolute"; | |
div.style.zIndex = "1000"; | |
div.style.left = "8px"; | |
div.style.top = "8px"; | |
div.style.backgroundColor = "white"; | |
return div.appendChild(document.createElement("div")); | |
} | |
function toCSV(...fields) { | |
return fields.map(field => `"${field == undefined ? "" : field.toString().replace(/"/g, '""')}"`).join(','); | |
} | |
function downloadFile(header, lines, filename, filetype) { | |
const a = document.body.appendChild(document.createElement('a')); | |
a.href = URL.createObjectURL(new Blob([header + "\n" + lines.join("\n")], {type: 'text/' + filetype})); | |
const date = (new Date()).toISOString().replace(/[T:]/g, "-").substr(0, 19); | |
a.download = `${filename}-${date}.${filetype}`; | |
a.click(); | |
} | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Credit goes to Gabriel Sroka at https://gabrielsroka.github.io/