Tweeter Dumper

Fetch tweet, author, and media urls and save to json file

目前为 2023-09-07 提交的版本。查看 最新版本

  1. // ==UserScript==
  2. // @name Tweeter Dumper
  3. // @namespace http://tampermonkey.net/
  4. // @version 0.1
  5. // @description Fetch tweet, author, and media urls and save to json file
  6. // @author krystianmoras@gmail.com
  7. // @require http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js
  8. // @match https://twitter.com/*
  9. // @icon https://www.google.com/s2/favicons?sz=64&domain=twitter.com
  10. // @grant GM_addStyle
  11. // @license GPL
  12. // ==/UserScript==
  13.  
  14. (function () {
  15. ////////////////////////////////////////////////////////////
  16. // taken from https://gist.githubusercontent.com/raw/2625891/waitForKeyElements.js
  17. /*--- waitForKeyElements(): A utility function, for Greasemonkey scripts,
  18. that detects and handles AJAXed content.
  19.  
  20. Usage example:
  21.  
  22. waitForKeyElements (
  23. "div.comments"
  24. , commentCallbackFunction
  25. );
  26.  
  27. //--- Page-specific function to do what we want when the node is found.
  28. function commentCallbackFunction (jNode) {
  29. jNode.text ("This comment changed by waitForKeyElements().");
  30. }
  31.  
  32. IMPORTANT: This function requires your script to have loaded jQuery.
  33. */
  34. function waitForKeyElements(
  35. selectorTxt, /* Required: The jQuery selector string that
  36. specifies the desired element(s).
  37. */
  38. actionFunction, /* Required: The code to run when elements are
  39. found. It is passed a jNode to the matched
  40. element.
  41. */
  42. bWaitOnce, /* Optional: If false, will continue to scan for
  43. new elements even after the first match is
  44. found.
  45. */
  46. iframeSelector /* Optional: If set, identifies the iframe to
  47. search.
  48. */
  49. ) {
  50. var targetNodes, btargetsFound;
  51.  
  52. if (typeof iframeSelector == "undefined")
  53. targetNodes = $(selectorTxt);
  54. else
  55. targetNodes = $(iframeSelector).contents()
  56. .find(selectorTxt);
  57.  
  58. if (targetNodes && targetNodes.length > 0) {
  59. btargetsFound = true;
  60. /*--- Found target node(s). Go through each and act if they
  61. are new.
  62. */
  63. targetNodes.each(function () {
  64. var jThis = $(this);
  65. var alreadyFound = jThis.data('alreadyFound') || false;
  66.  
  67. if (!alreadyFound) {
  68. //--- Call the payload function.
  69. var cancelFound = actionFunction(jThis);
  70. if (cancelFound)
  71. btargetsFound = false;
  72. else
  73. jThis.data('alreadyFound', true);
  74. }
  75. });
  76. }
  77. else {
  78. btargetsFound = false;
  79. }
  80.  
  81. //--- Get the timer-control variable for this selector.
  82. var controlObj = waitForKeyElements.controlObj || {};
  83. var controlKey = selectorTxt.replace(/[^\w]/g, "_");
  84. var timeControl = controlObj[controlKey];
  85.  
  86. //--- Now set or clear the timer as appropriate.
  87. if (btargetsFound && bWaitOnce && timeControl) {
  88. //--- The only condition where we need to clear the timer.
  89. clearInterval(timeControl);
  90. delete controlObj[controlKey]
  91. }
  92. else {
  93. //--- Set a timer, if needed.
  94. if (!timeControl) {
  95. timeControl = setInterval(function () {
  96. waitForKeyElements(selectorTxt,
  97. actionFunction,
  98. bWaitOnce,
  99. iframeSelector
  100. );
  101. },
  102. 300
  103. );
  104. controlObj[controlKey] = timeControl;
  105. }
  106. }
  107. waitForKeyElements.controlObj = controlObj;
  108. }
  109. ///////////////////////////////////////////////////////////////////
  110. waitForKeyElements("article", actionFunction);
  111.  
  112.  
  113. function actionFunction(jNode) {
  114. setTimeout(function () {
  115.  
  116. var button = document.createElement("button");
  117. button.innerHTML = "Save";
  118. button.onclick = function () {
  119.  
  120. // get author name
  121. // inside data-testid="User-Name"
  122. var author = jNode.find("div[data-testid='User-Name']").text();
  123. console.log(author);
  124.  
  125.  
  126. // get date
  127. var date = jNode.find("time").attr("datetime");
  128. console.log(date);
  129.  
  130. // get text
  131. var text = jNode.find("div[lang='en']").text();
  132. console.log(text);
  133.  
  134. // get all images
  135. var images = jNode.find("img");
  136. var image = "";
  137. for (var i = 1; i < images.length; i++) {
  138. image += images[i].src + "\n";
  139. }
  140. console.log(image);
  141.  
  142. // get video
  143. var video = jNode.find("video").attr("src");
  144. console.log(video);
  145.  
  146. // create blob
  147. var json = {
  148. "author": author,
  149. "date": date,
  150. "text": text,
  151. "image": image,
  152. "video": video
  153. };
  154. var blob = new Blob([JSON.stringify(json)], { type: "text/plain;charset=utf-8" });
  155.  
  156.  
  157. // create file name
  158. var file_name = author + "_" + date + ".tweeter_dumper.json";
  159.  
  160. // download without popup
  161. var link = document.createElement("a");
  162. link.href = window.URL.createObjectURL(blob);
  163. link.download = file_name;
  164. link.click();
  165.  
  166.  
  167.  
  168. };
  169. var share_button = jNode.find("div[data-testid='caret']").parent();
  170. share_button.append(button);
  171. }, 1000);
  172.  
  173. }
  174.  
  175.  
  176. })();