Google 新闻过滤筛选

可自行设定指定的新闻报社显示或隐藏。

  1. // ==UserScript==
  2. // @name Google: News Filter
  3. // @name:zh-TW Google 新聞過濾篩選
  4. // @name:zh-CN Google 新闻过滤筛选
  5. // @name:ja Googleニュースフィルター
  6. // @name:ko Google 뉴스 필터
  7. // @name:ru Новостной фильтр Google
  8. // @version 1.0.6
  9. // @description Show or Hide news whatever you want.
  10. // @description:zh-TW 可自行設定指定的新聞報社顯示或隱藏。
  11. // @description:zh-CN 可自行设定指定的新闻报社显示或隐藏。
  12. // @description:ja 好きなようにニュースを表示または非表示にします。
  13. // @description:ko 원하는 뉴스를 표시하거나 숨 깁니다.
  14. // @description:ru Показать или скрыть новости, что вы хотите.
  15. // @author Hayao-Gai
  16. // @namespace https://github.com/HayaoGai
  17. // @icon https://i.imgur.com/zHU2Zt3.png
  18. // @match https://news.google.com/*
  19. // @grant GM_setValue
  20. // @grant GM_getValue
  21. // ==/UserScript==
  22.  
  23. /* jshint esversion: 6 */
  24.  
  25. (function() {
  26. 'use strict';
  27.  
  28. // icon made by https://www.flaticon.com/authors/freepik
  29. const svg = `<svg width="15px" height="15px" viewBox="0 0 192.701 192.701" fill="#5f6368"><path d="M20.746,104.169l75.61-74.528l75.61,74.54c4.74,4.704,12.439,4.704,17.179,0s4.74-12.319,0-17.011l-84.2-82.997 c-4.559-4.511-12.608-4.535-17.191,0l-84.2,83.009c-4.74,4.692-4.74,12.319,0,17.011C8.307,108.873,16.006,108.873,20.746,104.169 z"/><path d="M104.946,88.373c-4.559-4.511-12.608-4.535-17.191,0l-84.2,82.997c-4.74,4.704-4.74,12.319,0,17.011 c4.74,4.704,12.439,4.704,17.179,0l75.622-74.528l75.61,74.54c4.74,4.704,12.439,4.704,17.179,0s4.74-12.319,0-17.011 L104.946,88.373z"/></svg>`;
  30. const css =
  31. `.article {
  32. max-height: 100px;
  33. overflow: hidden;
  34. transition: all 0.3s;
  35. }
  36. .hide {
  37. max-height: 0px;
  38. padding: 0px !important;
  39. }
  40. .panel {
  41. border: 1px solid #dadce0;
  42. border-radius: 8px;
  43. padding: 8px;
  44. margin-right: 10px;
  45. }
  46. .title {
  47. font-size: 1rem;
  48. font-weight: 500;
  49. font-family: 'Google Sans', sans-serif;
  50. display: flex;
  51. }
  52. .hover {
  53. position: fixed;
  54. width: 450px;
  55. max-height: 1000px;
  56. right: 8px;
  57. top: 60px;
  58. border: 1px solid #dadce0;
  59. border-radius: 8px;
  60. z-index: 999;
  61. background: white;
  62. overflow: hidden;
  63. transition: max-height 0.3s;
  64. }
  65. .collapse1 {
  66. max-height: 0px;
  67. }
  68. .collapse2 {
  69. border: 0px;
  70. }
  71. .arrow {
  72. margin-left: 15px;
  73. padding-top: 3px;
  74. cursor: pointer;
  75. transform: rotate(0deg);
  76. transition: all 0.3s ease-in-out;
  77. }
  78. .rotateArrow {
  79. transform: rotate(180deg);
  80. }
  81. .pressed {
  82. background-color: #498ce4 !important;
  83. color: white !important;
  84. }`;
  85. let scrolling = false;
  86.  
  87. CSS();
  88. locationChange();
  89. window.addEventListener("load", init);
  90. window.addEventListener("scroll", update);
  91.  
  92. function init(retry = 0) {
  93. // get all news title
  94. const titles = document.querySelectorAll("a.wEwyrc");
  95. // check
  96. if (!titles.length && retry < 5) {
  97. setTimeout(() => init(retry + 1), 500);
  98. return;
  99. }
  100. // title text
  101. const text = [...titles].map(title => title.innerText);
  102. const news = [...new Set(text)].sort();
  103. addMenu(news);
  104. }
  105.  
  106. function addMenu(news) {
  107. // remove exist
  108. const exist1 = document.querySelector(".panel");
  109. const exist2 = document.querySelector(".hover");
  110. if (exist1) {
  111. exist2.firstElementChild.remove();
  112. addOption(exist2, news);
  113. return;
  114. }
  115. // get dynamic class.
  116. let dynamicClass = "";
  117. document.querySelector("[ng-non-bindable][data-ogsr-up]").classList.forEach(eachClass => {
  118. dynamicClass += `.${eachClass}`;
  119. });
  120. const parent = document.querySelector(dynamicClass);
  121. // create
  122. const panel = document.createElement("div");
  123. panel.className = "panel";
  124. parent.insertBefore(panel, parent.firstElementChild);
  125. const title = document.createElement("h2");
  126. title.className = "title";
  127.  
  128. switch(document.querySelector("html").lang) {
  129. case "zh":
  130. title.innerText = "Google 新聞過濾篩選";
  131. break;
  132. case "ja":
  133. title.innerText = "Googleニュースフィルター";
  134. break;
  135. case "ko":
  136. title.innerText = "Google 뉴스 필터";
  137. break;
  138. case "ru":
  139. title.innerText = "Новостной фильтр Google";
  140. break;
  141. default:
  142. title.innerText = "Google News Filter";
  143. }
  144.  
  145. panel.appendChild(title);
  146. const icon = document.createElement("div");
  147. icon.className = "arrow rotateArrow";
  148. icon.innerHTML = svg;
  149. icon.addEventListener("click", () => {
  150. const toggle = hover.classList.toggle("collapse1");
  151. setTimeout(() => hover.classList.toggle("collapse2"), toggle ? 300 : 0);
  152. icon.classList.toggle("rotateArrow");
  153. });
  154. title.appendChild(icon);
  155. const hover = document.createElement("div");
  156. hover.className = "hover collapse1 collapse2";
  157. document.body.appendChild(hover);
  158. // option
  159. addOption(hover, news);
  160. }
  161.  
  162. function addOption(parent, news) {
  163. // create
  164. const div = document.createElement("div");
  165. div.className = "ndSf3d ttg1Pb j7vNaf Pz9Pcd a8arzf";
  166. // append
  167. parent.appendChild(div);
  168. // news
  169. news.forEach(text => singleOption(div, text));
  170. }
  171.  
  172. function singleOption(div, text) {
  173. // create
  174. const div1 = document.createElement("div");
  175. div1.className = "To2ZZb u9jkpc hpDt6e DbQnIe rrijPb R7GTQ keNKEd";
  176. div1.style.cursor = "pointer";
  177. div1.addEventListener("click", () => setOption(div1, text));
  178. getOption(div1, text);
  179. const div2 = document.createElement("div");
  180. div2.className = "K9tMQ";
  181. const div3 = document.createElement("div");
  182. div3.className = "VgnMrb";
  183. const span1 = document.createElement("span");
  184. span1.className = "Ix4NZd";
  185. const span2 = document.createElement("span");
  186. span2.className = "pPbimc ljLXBd";
  187. span2.innerText = text;
  188. // append
  189. div.appendChild(div1);
  190. div1.appendChild(div2);
  191. div2.appendChild(div3);
  192. div3.appendChild(span1);
  193. span1.appendChild(span2);
  194. }
  195.  
  196. function getOption(div, text) {
  197. // change color
  198. const isCollapse = GM_getValue(text, false);
  199. if (isCollapse) {
  200. div.classList.add("pressed");
  201. }
  202. // collapse or expand
  203. execution(isCollapse, text);
  204. }
  205.  
  206. function setOption(div, text) {
  207. // change color and record
  208. const isCollapse = div.classList.toggle("pressed");
  209. GM_setValue(text, isCollapse);
  210. // collapse or expand
  211. execution(isCollapse, text);
  212. }
  213.  
  214. function execution(isCollapse, text) {
  215. // add article class
  216. document.querySelectorAll("article:not(.article)").forEach(article => article.classList.add("article"));
  217. // collapse
  218. if (isCollapse) {
  219. document.querySelectorAll("article.article:not(.hide)").forEach(article => {
  220. const title = article.querySelector("a.wEwyrc").innerText;
  221. if (title.includes(text)) {
  222. article.classList.add("hide");
  223. }
  224. });
  225. }
  226. // expand
  227. else {
  228. document.querySelectorAll("article.article.hide").forEach(article => {
  229. const title = article.querySelector("a.wEwyrc").innerText;
  230. if (title.includes(text)) {
  231. article.classList.remove("hide");
  232. }
  233. });
  234. }
  235. }
  236.  
  237. function update() {
  238. if (scrolling) return;
  239. scrolling = true;
  240. if (document.querySelectorAll("article:not(.article)").length) init();
  241. setTimeout(() => { scrolling = false; }, 1000);
  242. }
  243.  
  244. function CSS() {
  245. const style = document.createElement("style");
  246. style.type = "text/css";
  247. style.innerHTML = css;
  248. document.head.appendChild(style);
  249. }
  250.  
  251. function locationChange() {
  252. window.addEventListener('locationchange', init);
  253. // situation 1
  254. history.pushState = (f => function pushState(){
  255. var ret = f.apply(this, arguments);
  256. window.dispatchEvent(new Event('pushState'));
  257. window.dispatchEvent(new Event('locationchange'));
  258. return ret;
  259. })(history.pushState);
  260. // situation 2
  261. history.replaceState = (f => function replaceState(){
  262. var ret = f.apply(this, arguments);
  263. window.dispatchEvent(new Event('replaceState'));
  264. window.dispatchEvent(new Event('locationchange'));
  265. return ret;
  266. })(history.replaceState);
  267. // situation 3
  268. window.addEventListener('popstate', () => {
  269. window.dispatchEvent(new Event('locationchange'));
  270. });
  271. }
  272.  
  273. })();

QingJ © 2025

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