├── README.md ├── csv-download.png ├── csv-example.png ├── json-download.png ├── page-grab-2.png └── page-grab.png /README.md: -------------------------------------------------------------------------------- 1 | # Hacker News Saved Links Export 2 | 3 | Export your Hacker News saved links to JSON or CSV using only the Chrome console. 4 | 5 | ![](csv-example.png) 6 | 7 | 1. Navigate to your HN Saved page in Google Chrome and press F12 to open the Developer Tools Console. 8 | 9 | 2. Paste the following code into the console and press enter. 10 | 11 | ```javascript 12 | var output = new Array(); 13 | 14 | grabPage = function() { 15 | 16 | if (localStorage.getItem("hn_saved") !== null) { 17 | output = JSON.parse(localStorage.getItem("hn_saved")); 18 | } 19 | 20 | var table = document.getElementsByClassName("itemlist"); 21 | var trArr = table[0].getElementsByTagName('tr'); 22 | 23 | for (i = 0; i < Math.floor(trArr.length/3); i++) { 24 | link_row = trArr[i*3].getElementsByTagName('td'); 25 | details_row = trArr[i*3 + 1].getElementsByTagName('td'); 26 | 27 | record_no = link_row[0].getElementsByTagName("span")[0].innerHTML; 28 | record_no = record_no.replace(/\D/g,''); 29 | 30 | title = link_row[2].getElementsByTagName("a")[0].innerHTML; 31 | page_url = link_row[2].getElementsByTagName("a")[0].href; 32 | 33 | comments_url = details_row[1].getElementsByClassName("age")[0].getElementsByTagName("a")[0].href; 34 | age = details_row[1].getElementsByClassName("age")[0].getElementsByTagName("a")[0].innerHTML; 35 | 36 | output[record_no - 1] = { 37 | "number": record_no, 38 | "title": title, 39 | "page_url": page_url, 40 | "comments_url": comments_url, 41 | "age": age 42 | } 43 | } 44 | 45 | console.log("Output currently contains " + output.length + " items"); 46 | localStorage.setItem("hn_saved", JSON.stringify(output)); 47 | } 48 | 49 | grabPage(); 50 | ``` 51 | 52 | ![](page-grab.png) 53 | 54 | 3. Hit "Next" at the bottom of your saved page. 55 | 56 | 4. Paste `grabPage` code into console again. With each page load you'll need to repaste the entire `grabPage` code snippet since nothing is persisted between the loads. To save the data between page loads a local storage item is created with the key `hn_saved`. Each save item is keyed using it's record number so running the code twice on the same page is not an issue. 57 | 58 | ![](page-grab-2.png) 59 | 60 | Repeat "Next"/`grabPage` process until all pages are done. 61 | 62 | 5. Save the output 63 | 64 | - To save output as a CSV, paste the following code. It will automatically download and save as `hn_saved.csv`. 65 | 66 | ```javascript 67 | saveOutputCSV = function() { 68 | if (localStorage.getItem("hn_saved") !== null) { 69 | output = JSON.parse(localStorage.getItem("hn_saved")); 70 | } 71 | 72 | var content = "data:text/csv;charset=utf-8,"; 73 | 74 | content += "Number,Title,Page URL,Comments URL,Age\n"; 75 | 76 | for (i = 0; i < output.length; i++) { 77 | var row = ''; 78 | var json_row = output[i]; 79 | 80 | var clean_title = json_row["title"].replace(/"/g, '""'); 81 | clean_title = '"' + clean_title + '"'; 82 | 83 | row += json_row["number"] + ","; 84 | row += clean_title + ","; 85 | row += json_row["page_url"] + ","; 86 | row += json_row["comments_url"] + ","; 87 | row += json_row["age"] + ""; 88 | row += "\n"; 89 | 90 | content += row; 91 | } 92 | 93 | var content_url = encodeURI(content); 94 | var shadow_link = document.createElement("a"); 95 | shadow_link.setAttribute("href", content_url); 96 | shadow_link.setAttribute("download", "hn_saved.csv"); 97 | 98 | shadow_link.click(); 99 | } 100 | 101 | saveOutputCSV(); 102 | ``` 103 | 104 | If successful, the file will automatically download. 105 | 106 | ![](csv-download.png) 107 | 108 | - To save output as a JSON, paste the following code. It will automatically download and save as `hn_saved.json`. 109 | 110 | ```javascript 111 | saveOutputJSON = function() { 112 | if (localStorage.getItem("hn_saved") !== null) { 113 | output = JSON.parse(localStorage.getItem("hn_saved")); 114 | } 115 | 116 | var content = "data:text/json;charset=utf-8,"; 117 | content += JSON.stringify(output); 118 | 119 | var content_url = encodeURI(content); 120 | var shadow_link = document.createElement("a"); 121 | shadow_link.setAttribute("href", content_url); 122 | shadow_link.setAttribute("download", "hn_saved.json"); 123 | 124 | shadow_link.click(); 125 | } 126 | 127 | saveOutputJSON(); 128 | ``` 129 | 130 | ![](json-download.png) 131 | -------------------------------------------------------------------------------- /csv-download.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomaskcr/hn-saved-export/f815fbb5684ab7e26e47fc656dc5084b542ac078/csv-download.png -------------------------------------------------------------------------------- /csv-example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomaskcr/hn-saved-export/f815fbb5684ab7e26e47fc656dc5084b542ac078/csv-example.png -------------------------------------------------------------------------------- /json-download.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomaskcr/hn-saved-export/f815fbb5684ab7e26e47fc656dc5084b542ac078/json-download.png -------------------------------------------------------------------------------- /page-grab-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomaskcr/hn-saved-export/f815fbb5684ab7e26e47fc656dc5084b542ac078/page-grab-2.png -------------------------------------------------------------------------------- /page-grab.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomaskcr/hn-saved-export/f815fbb5684ab7e26e47fc656dc5084b542ac078/page-grab.png --------------------------------------------------------------------------------