You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何编写Tampermonkey脚本并定位moat.com品牌数据库

Hey there! Let's walk through how to tackle this problem—first finding that elusive brand JSON database, then setting up a local image matching system if needed.

Step 1: Hunting for the Brand JSON Database

Most modern sites load dynamic data like brand lists via API calls or embedded scripts. Here's how to dig it up:

  • Use Browser DevTools Network Panel

    1. Open Chrome/Firefox DevTools (F12 or Ctrl+Shift+I) and go to the Network tab.
    2. Filter requests by XHR/Fetch (this narrows down API calls that often return JSON).
    3. Type a test brand name into Moat's search bar and watch for new requests. Look for endpoints with keywords like brand, search, autocomplete, or catalog.
    4. Click on each request to check the Response tab—if you see a list of brand objects (with names, image URLs, etc.), that's your target JSON.
  • Check for Embedded Page State
    Some sites embed initial data directly in the HTML as a JavaScript object. Search the page source (Ctrl+U) for patterns like:

    window.__BRAND_DATA__ = {...};
    // or
    var brandDatabase = [...];
    

    You can also use the DevTools Sources tab to search for JSON.parse or specific brand names to trace where data is being parsed.

  • Decipher Obfuscated JS
    If the site's JS is minified/obfuscated, use the DevTools Pretty Print button ({} in the Sources tab) to make it readable. Search for strings like "brand" or "search" to find functions that fetch or process the brand data.

Step 2: Building a Local Image Search Tampermonkey Script

If you can't directly download the full JSON, or want to use local images for matching, here's a framework to implement:

1. First: Collect Brand Data (Legally!)

Before building the search, you'll need a local database of brands and their image signatures. Write a simple Tampermonkey script to scrape (with respect to Moat's terms of service) brand info as you browse:

// ==UserScript==
// @name         Moat Brand Data Collector
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  Collect brand names and image URLs
// @author       You
// @match        https://moat.com/*
// @grant        GM_setValue
// @grant        GM_getValue
// ==/UserScript==

(function() {
    'use strict';

    // Adjust selectors based on Moat's actual HTML structure
    const brandElements = document.querySelectorAll('.brand-item');
    const brandData = GM_getValue('moatBrands', []);

    brandElements.forEach(el => {
        const brandName = el.querySelector('.brand-name').textContent.trim();
        const brandImage = el.querySelector('.brand-image').src;
        if (!brandData.find(b => b.name === brandName)) {
            brandData.push({name: brandName, imageUrl: brandImage});
        }
    });

    GM_setValue('moatBrands', brandData);
    console.log('Updated brand database:', brandData);
})();

2. Implement Image Matching Logic

For local image search, use Perceptual Hashing (pHash) to compare image similarity. Here's a simplified pHash implementation you can use:

function getImageHash(img) {
    // Resize image to 8x8 grayscale
    const canvas = document.createElement('canvas');
    const ctx = canvas.getContext('2d');
    canvas.width = 8;
    canvas.height = 8;
    ctx.drawImage(img, 0, 0, 8, 8);

    // Convert to grayscale
    const data = ctx.getImageData(0, 0, 8, 8).data;
    const grayscale = [];
    for (let i = 0; i < data.length; i += 4) {
        const gray = (data[i] + data[i+1] + data[i+2]) / 3;
        grayscale.push(gray);
    }

    // Calculate average brightness
    const avg = grayscale.reduce((a, b) => a + b, 0) / grayscale.length;

    // Generate hash string
    let hash = '';
    grayscale.forEach(pixel => {
        hash += pixel >= avg ? '1' : '0';
    });
    return hash;
}

// Calculate Hamming distance (lower = more similar)
function hammingDistance(hash1, hash2) {
    let distance = 0;
    for (let i = 0; i < hash1.length; i++) {
        if (hash1[i] !== hash2[i]) distance++;
    }
    return distance;
}

Replace Moat's default search with your local image matching:

// ==UserScript==
// @name         Moat Local Image Search
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  Use local images to search Moat brands
// @author       You
// @match        https://moat.com/*
// @grant        GM_getValue
// ==/UserScript==

(function() {
    'use strict';

    // Add a file input for local images
    const fileInput = document.createElement('input');
    fileInput.type = 'file';
    fileInput.accept = 'image/*';
    fileInput.style.cssText = 'position:fixed; top:20px; right:20px; z-index:9999;';
    document.body.appendChild(fileInput);

    // Load local brand database
    const brandData = GM_getValue('moatBrands', []);
    const brandHashes = [];

    // Precompute hashes for brand images
    brandData.forEach(brand => {
        const img = new Image();
        img.crossOrigin = 'anonymous';
        img.onload = () => {
            brandHashes.push({name: brand.name, hash: getImageHash(img)});
        };
        img.src = brand.imageUrl;
    });

    // Handle local image upload
    fileInput.addEventListener('change', (e) => {
        const file = e.target.files[0];
        const img = new Image();
        img.src = URL.createObjectURL(file);
        img.onload = () => {
            const localHash = getImageHash(img);
            let bestMatch = null;
            let minDistance = Infinity;

            // Find most similar brand
            brandHashes.forEach(brand => {
                const distance = hammingDistance(localHash, brand.hash);
                if (distance < minDistance) {
                    minDistance = distance;
                    bestMatch = brand;
                }
            });

            if (bestMatch) {
                const similarity = Math.round(100 - (minDistance / 64) * 100);
                alert(`Best match: ${bestMatch.name}\nSimilarity: ${similarity}%`);
                // Auto-fill Moat's search bar with the match
                const searchInput = document.querySelector('#search-input');
                if (searchInput) searchInput.value = bestMatch.name;
            } else {
                alert('No matching brand found');
            }
        };
    });

    // Include getImageHash and hammingDistance functions here
})();

Important Notes

  • Respect Terms of Service: Make sure scraping or modifying Moat's functionality doesn't violate their terms. Always check their legal pages first.
  • CORS Issues: If loading brand images from Moat's domain causes errors, download images locally or use a proxy to avoid cross-origin restrictions.
  • Performance: For large databases, precompute and store hashes locally (using GM_setValue) instead of calculating them every time.

内容的提问来源于stack exchange,提问作者joeyr2

火山引擎 最新活动