SimHashPHP

repository·master·Indexed 40 days ago

https://github.com/tgalopin/simhashphp

A PHP port of the SimHash algorithm used to efficiently compute similarity indices between pieces of text to detect duplicate or near-duplicate content. It provides tools for feature extraction via SimpleTextExtractor and HtmlExtractor, fingerprint generation with support for 32, 64, and 128-bit sizes, and similarity comparison using the GaussianComparator.

Tokens
3.7K
Snippets
13
Records
16
Agent score
99%

What's inside SimHashPHP

  1. How to use SimHashPHP to compare text similarity

    master

    To compute a similarity index between two texts, you need to follow three main steps:

    1. Extract features: Use an extractor (like SimpleTextExtractor) to process the raw text.
    2. Generate hashes: Use the SimHash class to generate a fingerprint (hash) from the extracted features. You can specify the hash size, such as \Tga\SimHash\SimHash::SIMHASH_64.
    3. Compare fingerprints: Use a comparator (like GaussianComparator) to calculate the similarity index between two fingerprints. The result is typically a value between 0 and 1.

    Ensure you include vendor/autoload.php to load the library classes.

    <?php
    
    require 'vendor/autoload.php';
    
    $text1 = "Some text content...";
    $text2 = "Some similar text content...";
    
    $simhash = new \Tga\SimHash\SimHash();
    $extractor = new \Tga\SimHash\Extractor\SimpleTextExtractor();
    $comparator = new Tga\SimHash\Comparator\GaussianComparator(3);
    
    // 1. Extract and Hash
    $fp1 = $simhash->hash($extractor->extract($text1), \Tga\SimHash\SimHash::SIMHASH_64);
    $fp2 = $simhash->hash($extractor->extract($text2), \Tga\SimHash\SimHash::SIMHASH_64);
    
    // 2. View binary representation
    var_dump($fp1->getBinary());
    var_dump($fp2->getBinary());
    
    // 3. Compare (returns index between 0 and 1)
    var_dump($comparator->compare($fp1, $fp2));
  2. Compute SimHash fingerprints using the SimHash class

    master

    The Tga\SimHash\SimHash class is the primary entry point for generating similarity hashes (fingerprints). You can compute hashes from raw HTML, plain text, or pre-processed elements.

    Available Hash Sizes

    You can specify the bit size of the fingerprint using the following constants:

    • SimHash::SIMHASH_32 (32 bits)
    • SimHash::SIMHASH_64 (64 bits - default)
    • SimHash::SIMHASH_128 (128 bits)

    Methods

    hashHtml(string $html, int $size = self::SIMHASH_64): Fingerprint

    Extracts text from an HTML document using HtmlExtractor and computes the hash.

    hashText(string $text, int $size = self::SIMHASH_64): Fingerprint

    Extracts text from a plain string using SimpleTextExtractor and computes the hash.

    hash(array $elements, int $size = self::SIMHASH_64): Fingerprint

    Computes a hash from an array of elements (e.g., tokens or strings) by tokenizing them and applying a vectorizer.

    use Tga\SimHash\SimHash;
    
    $simhash = new SimHash();
    
    // Hash HTML content
    $fingerprintHtml = $simhash->hashHtml('<html><body><h1>Hello</h1></body></html>', SimHash::SIMHASH_64);
    
    // Hash plain text
    $fingerprintText = $simhash->hashText('This is a sample text for simhash.', SimHash::SIMHASH_64);
    
    // Hash an array of elements
    $fingerprintElements = $simhash->hash(['element1', 'element2'], SimHash::SIMHASH_32);
  3. Extract text from HTML using HtmlExtractor

    master

    The HtmlExtractor class is used to extract meaningful text content from HTML documents to prepare it for SimHash processing. It attempts to parse the HTML using DOMDocument to specifically extract the <title> and the <body> content.

    If the HTML is malformed and cannot be parsed by DOMDocument, the extractor falls back to using strip_tags() on the raw HTML string to ensure some text is still returned.

    During body parsing, it performs a specific transformation: it replaces <img> tags with a <span> containing the extracted source attribute of the image. This helps preserve some level of structural information (image sources) in the text stream.

    use Tga\SimHash\Extractor\HtmlExtractor;
    
    $extractor = new HtmlExtractor();
    $html = '<html><head><title>Example Page</title></head><body>Hello World<img src="image.jpg"></body></html>';
    $textArray = $extractor->extract($html);
    
    // $textArray contains the processed text segments
  4. Use SimpleTextExtractor to extract words from text

    master

    The SimpleTextExtractor class implements ExtractorInterface and provides a simple way to split a string into an array of words. It works by slugifying the input text (converting it to a URL-friendly format) and then splitting the resulting string by the hyphen (-) character. This is useful for preparing plain text for similarity hash computation.

    use Tga\SimHash\Extractor\SimpleTextExtractor;
    
    $extractor = new SimpleTextExtractor();
    $words = $extractor->extract("Hello World! This is a test.");
    // Result will be an array of slugified words: ['hello', 'world', 'this', 'is', 'a', 'test']
  5. Use String64Tokenizer to generate 64-bit tokens

    master

    The String64Tokenizer is an implementation of TokenizerInterface designed to process strings into 64-bit tokens. It uses the CRC64 algorithm to generate a hash and returns the result as a 64-character binary string (padded with zeros) representing the bit sequence.

    This tokenizer is suitable when your SimHash implementation requires fixed-size 64-bit tokens derived from string elements.

    use Tga\SimHash\Tokenizer\String64Tokenizer;
    
    $tokenizer = new String64Tokenizer();
    $token = $tokenizer->tokenize("your string here");
    // $token is a 64-character string of '0's and '1's
  6. Retrieve Fingerprint values in binary, decimal, or hex formats

    master

    The Fingerprint class provides methods to export the hash into different formats:

    • getBinary(): Returns the binary representation as a string, padded with leading zeros to match the specified $size.
    • getDecimal(): Returns the fingerprint as a float.
    • getHexa(): Returns the hexadecimal representation as a string.
    • __toString(): Automatically returns the binary string representation when the object is cast to a string.
  7. Use GaussianComparator to compare fingerprints

    master

    The GaussianComparator implements the ComparatorInterface and calculates a similarity index between 0 and 1 based on a Gaussian distribution. It measures how many bits differ between two fingerprints and maps that difference to a probability density.

    Usage

    1. Instantiate the comparator with a $deviation (default is 4). The deviation controls the sensitivity of the similarity score.
    2. Call compare(Fingerprint $fp1, Fingerprint $fp2).

    Constraints

    • Both Fingerprint objects must have the same size. If they differ, a \LogicException is thrown.
    use Tga\SimHash\Comparator\GaussianComparator;
    
    // Initialize with a deviation of 4 (default)
    $comparator = new GaussianComparator(4);
    
    // Compare two fingerprints to get a similarity index between 0 and 1
    $similarity = $comparator->compare($fingerprint1, $fingerprint2);
  8. Customize SimHash with custom Tokenizers and Vectorizers

    master

    The SimHash class allows you to extend its behavior by providing your own implementations of the TokenizerInterface and VectorizerInterface.

    • Tokenizers: Use addTokenizer(Tokenizer\TokenizerInterface $tokenizer) to add a new tokenizer to the internal stack. The class iterates through tokenizers and selects the first one that satisfies supportsElement($element) and supportsSize($size).
    • Vectorizer: Use setVectorizer(Vectorizer\VectorizerInterface $vectorizer) to replace the default vectorizer with your own implementation.
    use Tga\SimHash\SimHash;
    use Tga\SimHash\Tokenizer\TokenizerInterface;
    use Tga\SimHash\Vectorizer\VectorizerInterface;
    
    $simhash = new SimHash();
    
    // Inject a custom tokenizer
    $simhash->addTokenizer($myCustomTokenizer);
    
    // Inject a custom vectorizer
    $simhash->setVectorizer($myCustomVectorizer);
  9. Use DefaultVectorizer to vectorize tokens

    master

    The DefaultVectorizer is the standard implementation of the VectorizerInterface. It converts an array of tokens into a numerical vector of a specified size.

    It works by:

    1. Calculating weights for each token based on their frequency in the input array (more frequent tokens have higher weights).
    2. Iterating through the weighted tokens and updating a vector of length $size.
    3. For each bit in a token: if the bit is '1', the weight is added to the vector at that index; if the bit is '0', the weight is subtracted.

    This produces a weighted vector suitable for SimHash calculations.

    use Tga\SimHash\Vectorizer\DefaultVectorizer;
    
    $vectorizer = new DefaultVectorizer();
    $tokens = ['1010', '1100', '1010'];
    $size = 4;
    
    $vector = $vectorizer->vectorize($tokens, $size);
  10. Use String32Tokenizer for 32-bit token generation

    master

    The String32Tokenizer is an implementation of TokenizerInterface designed to process strings into 32-bit tokens. It uses the crc32b hash algorithm and returns a 32-character hexadecimal string (padded with leading zeros).

    Use this tokenizer when your SimHash implementation requires fixed-size 32-bit tokens derived from string elements.

    use Tga\
    SimHash\
    Tokenizer\
    String32Tokenizer;
    
    $tokenizer = new String32Tokenizer();
    $token = $tokenizer->tokenize("your string here");
    // Returns a 32-character hex string