Car Listing Filter

Hide specific car makes/models from listing results

当前为 2025-02-06 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Car Listing Filter
  3. // @namespace http://tampermonkey.net/
  4. // @version v0.0.3
  5. // @description Hide specific car makes/models from listing results
  6. // @author shipit@zerofux.dev
  7. // @match *://www.autotrader.com/*
  8. // @match *://www.carfax.com/*
  9. // @match *://www.cargurus.com/*
  10. // @match *://www.carmax.com/*
  11. // @match *://www.cars.com/*
  12. // @match *://www.carvana.com/*
  13. // @grant none
  14. // ==/UserScript==
  15.  
  16. (function() {
  17. 'use strict';
  18.  
  19. // Enable or disable detailed logging
  20. const verboseLogging = true; // Set to false to disable logging
  21.  
  22. function log(...args) {
  23. if (verboseLogging) {
  24. console.log(...args);
  25. }
  26. }
  27.  
  28. // Add or modify models you want to block in this array (case-insensitive)
  29. const blockedModels = [
  30. 'buick encore',
  31. 'dodge journey',
  32. 'ford ecosport',
  33. 'hyundai',
  34. 'jeep',
  35. 'kia',
  36. 'mitsubishi outlander',
  37. 'nissan',
  38. 'trax'
  39. ];
  40.  
  41. // Site-specific configuration
  42. const siteConfig = {
  43. 'www.autotrader.com': {
  44. container: '.inventory-listing',
  45. textElement: '[data-cmp="subheading"]',
  46. },
  47. 'www.carfax.com': {
  48. container: '.srp-list-item',
  49. textElement: '.srp-list-item__header'
  50. },
  51. 'www.cargurus.com': {
  52. container: '[data-testid="srp-listing-tile"]',
  53. textElement: '[data-testid="srp-tile-listing-title"] h4',
  54. additionalTextElements: ['dl dd']
  55. },
  56. 'www.carmax.com': {
  57. container: 'article.car-tile',
  58. textElement: 'div.scct--make-model-container a.scct--make-model-info-link'
  59. },
  60. 'www.cars.com': {
  61. container: '.vehicle-card',
  62. textElement: '.vehicle-card-link'
  63. },
  64. 'www.carvana.com': {
  65. container: '[data-qa="result-tile"]',
  66. textElement: '[data-qa="make-model"]'
  67. }
  68. };
  69.  
  70. function hideBlockedModels() {
  71. const host = window.location.hostname;
  72. const config = siteConfig[host];
  73. if (!config) {
  74. log("No configuration found for host:", host);
  75. return;
  76. }
  77. log("Blocking with the following settings");
  78. log("Host:", host);
  79. log("Config:", config);
  80.  
  81. document.querySelectorAll(config.container).forEach(card => {
  82. let shouldHide = false;
  83. log("Checking card:", card);
  84.  
  85. // Check primary element
  86. const titleElement = card.querySelector(config.textElement);
  87. if (titleElement) {
  88. const titleText = titleElement.textContent.toLowerCase();
  89. log("Found title text:", titleText);
  90. shouldHide = blockedModels.some(model => titleText.includes(model.toLowerCase()));
  91. if (shouldHide) {
  92. log("Title matched blocked model:", titleText);
  93. }
  94. } else {
  95. log("Title element not found for card");
  96. }
  97.  
  98. // Additional check for model specification in details
  99. if (!shouldHide && config.additionalTextElements) {
  100. shouldHide = config.additionalTextElements.some(selector => {
  101. const el = card.querySelector(selector);
  102. if (el) {
  103. const elText = el.textContent.toLowerCase();
  104. log("Checking additional text element:", elText);
  105. const match = blockedModels.some(model => elText.includes(model.toLowerCase()));
  106. if (match) {
  107. log("Additional text matched blocked model:", elText);
  108. return true;
  109. }
  110. }
  111. return false;
  112. });
  113. }
  114.  
  115. if (shouldHide) {
  116. log("Hiding element:", card);
  117. card.style.setProperty('display', 'none', 'important');
  118. // Alternative
  119. // card.remove();
  120. }
  121. });
  122. }
  123.  
  124. hideBlockedModels();
  125.  
  126. // Observer for dynamic content
  127. const observer = new MutationObserver(hideBlockedModels);
  128. observer.observe(document.body, {
  129. childList: true,
  130. subtree: true
  131. });
  132. })();