search broadcast for douban

search user braodcast

  1. // ==UserScript==
  2. // @name search broadcast for douban
  3. // @namespace harryhare.github.io
  4. // @version 0.2.3
  5. // @description search user braodcast
  6. // @author harryhare
  7. // @license GPL 3.0
  8. // @icon https://raw.githubusercontent.com/harryhare/userscript/master/index.png
  9. // @match https://www.douban.com/people/*/statuses**
  10. // @match https://www.douban.com
  11. // @match https://www.douban.com/?p=*
  12. // @grant GM_getValue
  13. // @grant GM_setValue
  14. // ==/UserScript==
  15.  
  16. const gm_key="douban_user_status";
  17. const interval=2000;
  18.  
  19. var stop_signal=false;
  20.  
  21. var search_text;
  22. var search_page;
  23. var max_page;
  24. var user_name;
  25. var old_data;
  26. var cached_status;
  27. var cached_ids_set;
  28. var latest_cached_id="";
  29. var latest_cached_time="";
  30.  
  31. var result_container;
  32. var status_container;
  33. var search_button;
  34. var stop_button;
  35.  
  36.  
  37. var page=1;
  38. var statuses=[];
  39.  
  40. function getContent(response){
  41. var target_string=search_text.value;
  42. var target_exp=new RegExp(target_string,"i");
  43. var parser=new window.DOMParser();
  44. var xmlDoc=parser.parseFromString(response,"text/html");
  45. //xmlDoc.getElementsByTagName('textarea')[0].innerHTML;
  46. var statuse_nodes=xmlDoc.querySelectorAll("div.stream-items div.new-status.status-wrapper");
  47. user_name = get_user_id();
  48. //console.log(statuses);
  49. for (var i=0;i<statuse_nodes.length;i++){
  50. var status= statuse_nodes[i];
  51. var create_time=status.querySelector("div.status-item div.mod div.bd div.actions span.created_at");
  52. var status_id=status.getAttribute('data-sid');
  53. //console.log("new status id: ",status_id);
  54. if(cached_ids_set.has(status_id)){
  55. //search in cached data
  56. cached_status=GM_getValue(gm_key)[user_name];
  57. for(let data of cached_status){
  58. var status=parser.parseFromString(data,"text/html").body.firstChild;
  59. var text=status.innerHTML;
  60. if(text.search(target_exp)!=-1){
  61. result_container.append(status);
  62. }
  63. }
  64.  
  65. //merge
  66. console.log("new statuses: ");
  67. console.log(statuses.length);
  68. console.log("cached status: ");
  69. console.log(cached_status.length);
  70. statuses.push(...cached_status)
  71.  
  72. console.log("merged status: ");
  73. console.log(statuses.length);
  74. return true;
  75. }
  76. //change time until now to post time
  77. if(create_time){
  78. var create_time_a=create_time.querySelector("a");
  79. if(create_time_a){
  80. create_time_a.innerHTML=create_time.getAttribute('title');
  81. statuses.push(status.outerHTML);
  82. }
  83. }
  84.  
  85. var text=status.innerHTML;
  86. if(text.search(target_exp)!=-1){
  87. result_container.append(status);
  88. }
  89. }
  90. return statuse_nodes.length==0;
  91. }
  92.  
  93.  
  94. function visit(){
  95. var xhr=new XMLHttpRequest();
  96. var url=get_base_url()+"?p="+page;
  97. console.log('visit',url);
  98. status_container.innerHTML="正在搜索第"+page+"页...";
  99. xhr.open("GET",url,true);
  100. xhr.onreadystatechange = function (){
  101. if(xhr.readyState != 4 || xhr.status != 200 ){
  102. return;
  103. }
  104. console.log("recv:",url);
  105. //console.warn(xhr.responseText);
  106. let reach_end=getContent(xhr.responseText);
  107. if(page<max_page && reach_end==false && stop_signal==false){
  108. page++;
  109. var interval_id = window.setInterval(()=>{
  110. window.clearInterval(interval_id);
  111. visit();
  112. },interval);
  113. }else{
  114. finish();
  115. }
  116. };
  117. xhr.send();
  118. }
  119.  
  120. var mode=""
  121.  
  122. function finish(){
  123. //save
  124. user_name=get_user_id();
  125. old_data[user_name]=statuses;
  126. GM_setValue(gm_key,old_data);
  127.  
  128.  
  129. //show finish
  130. console.log("done");
  131. search_button.disabled=false;
  132. stop_button.disabled=true;
  133. status_container.innerHTML="搜索完成";
  134. }
  135.  
  136.  
  137. function on_search(){
  138. console.log("do search");
  139. console.log("search text: ",search_text.value);
  140. console.log("max page: ",search_page.value);
  141. console.log("target user name: ",user_name);
  142. old_data=GM_getValue(gm_key);
  143. //console.log(old_data);
  144. if(!old_data){
  145. old_data=new Map();
  146. }
  147.  
  148. //find the latest status id in old_data
  149. cached_status=[];
  150. cached_ids_set=new Set();
  151. if(old_data[user_name] && old_data[user_name].length>0){
  152. cached_status=old_data[user_name];
  153. var parser=new window.DOMParser();
  154. //var node=parser.parseFromString(old_data[user_name][0],"text/html").body.firstChild;
  155. //latest_cached_id=node.getAttribute('data-sid');
  156. //var create_time_node=node.querySelector("div.status-item div.mod div.bd div.actions span.created_at");
  157. //latest_cached_time=node.getAttribute('title');
  158. //console.log("last cached status id: ",latest_cached_id);
  159. for(let data of cached_status){
  160. var node=parser.parseFromString(data,"text/html").body.firstChild;
  161. var id=node.getAttribute('data-sid');
  162. cached_ids_set.add(id);
  163. }
  164. }
  165.  
  166. //limit cache pages
  167. max_page=parseInt(search_page.value);
  168. if(!max_page||max_page<=1){
  169. max_page=20;
  170. }
  171.  
  172. //disable search button and show progress
  173. result_container.innerHTML="";
  174. search_button.disabled=true;
  175. stop_button.disabled=false;
  176. stop_signal=false;
  177.  
  178. //start visit
  179. page=1;
  180. statuses=[];
  181. visit();
  182. }
  183.  
  184.  
  185. function on_clean(){
  186. console.log("clean cache data");
  187. GM_setValue(gm_key,{});
  188. }
  189.  
  190.  
  191. function on_stop(){
  192. stop_signal=true;
  193. }
  194.  
  195.  
  196. function test(){
  197. console.log(search_text.value);
  198. console.log(search_page.value);
  199. console.log(user_name);
  200. }
  201.  
  202. function get_base_url(){
  203. var reg=/https?:\/\/www.douban.com\/people\/([^\/]+)\/statuses.*/g;
  204. var result=reg.exec(window.location);
  205. if(result && result.length==2){
  206. return "/people/"+user_name+"/statuses";
  207. }
  208. var reg2=/https?:\/\/www.douban.com/g;
  209. var result2=reg.exec(window.location);
  210. if(result && result.length==1){
  211. return "/";
  212. }
  213. return "";
  214. }
  215.  
  216. function get_user_id(){
  217. var reg=/https?:\/\/www.douban.com\/people\/([^\/]+)\/statuses.*/g;
  218. var result=reg.exec(window.location);
  219. if(result && result.length==2){
  220. return result[1];
  221. }
  222. var reg2=/https?:\/\/www.douban.com.*/g;
  223. var result2=reg2.exec(window.location);
  224. if(result2 && result2.length==1){
  225. return "$$self_feed$$";
  226. }
  227. return "";
  228. }
  229.  
  230. (function() {
  231. 'use strict';
  232.  
  233. user_name=get_user_id();
  234. if(user_name===""){
  235. console.warn("error url");
  236. return;
  237. }
  238.  
  239. var p_node=document.querySelector("body div#wrapper div#content div.clearfix div.aside");
  240.  
  241. var container=document.createElement('div');
  242. container.style='background-color:#eeeeee;display: -webkit-flex; display: flex; flex-direction: column;';
  243. p_node.append(container);
  244.  
  245. var title=document.createElement('div');
  246. title.innerHTML="搜索广播";
  247. container.append(title);
  248.  
  249. //inputs
  250. var search_container=document.createElement('div');
  251. search_container.style='display: -webkit-flex; display: flex; flex-direction: row; justify-content: space-between ;';
  252. container.append(search_container);
  253.  
  254. var text1=document.createElement('div');
  255. text1.innerHTML="关键字:";
  256. search_container.append(text1);
  257.  
  258. search_text=document.createElement('input');
  259. search_text.style="width:220px;flex:0 1 auto;";
  260. search_container.append(search_text);
  261.  
  262. var page_container=document.createElement('div');
  263. page_container.style='display: -webkit-flex; display: flex; flex-direction: row; justify-content: space-between ;';
  264. container.append(page_container);
  265.  
  266. var text2=document.createElement('div');
  267. text2.innerHTML="最大页数:";
  268. page_container.append(text2);
  269.  
  270. search_page=document.createElement('input');
  271. search_page.style="width:220px;flex:0 1 auto;";
  272. page_container.append(search_page);
  273. search_page.value='10';
  274.  
  275. //buttons
  276. var button_container=document.createElement('div');
  277. button_container.style='display: -webkit-flex; display: flex; flex-direction: row; justify-content: space-around ;';
  278. container.append(button_container);
  279.  
  280. search_button=document.createElement('button');
  281. search_button.innerHTML="search";
  282. search_button.onclick=on_search;
  283. search_button.id="search";
  284. button_container.append(search_button);
  285.  
  286. stop_button=document.createElement('button');
  287. stop_button.innerHTML="stop searching";
  288. stop_button.onclick=on_stop;
  289. stop_button.id="stop";
  290. stop_button.disabled=true;
  291. button_container.append(stop_button);
  292.  
  293. var clean_button=document.createElement('button');
  294. clean_button.innerHTML="clean cache";
  295. clean_button.onclick=on_clean;
  296. clean_button.id="clean";
  297. button_container.append(clean_button);
  298.  
  299. //var test_button=document.createElement('button');
  300. //test_button.innerHTML="test";
  301. //test_button.onclick=test;
  302. //test_button.id="test";
  303. //button_container.append(test_button);
  304.  
  305. //results
  306. status_container=document.createElement('div');
  307. container.append(status_container);
  308. result_container=document.createElement('div');
  309. container.append(result_container);
  310. })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址