
    AHj&              
          d Z ddlZddlZddlZddlmZ ddlmZ ddlm	Z	 ddl
mZ ddlmZ ddlmZ dd	lmZ d
dlmZmZ d
dlmZ  ej.                  d      Z eedd       Zej;                   ed      D  ci c]$  }  ej>                   e |             d   dk(  s"| d& c}       Z! ed      d1dedede"de#fd       Z$de%e   dede%e   fdZ&d2dedede%e   fdZ'd2dedede%e   fd Z(d3dedede)fd!Z* ed"      d#edede%e   fd$       Z+ G d% d&      Z,d'edefd(Z-d)\  Z.Z/Z0Z1 G d* d+      Z2 e2e      Z3d,eddfd-Z4d.ed/ede#fd0Z5yc c} w )4z>Code parts dedicated to duplicate removal and text similarity.    N)SequenceMatcher)	lru_cache)blake2b)add)RLock)Any)_Element   )LRU_SIZE	Extractor)trimz\.[^/?#]{2,63}$	bit_countc                 6    t        |       j                  d      S )N1)bincount)xs    Q/root/tools/cai/cai_env/lib/python3.12/site-packages/trafilatura/deduplication.py<lambda>r      s    SV\\#5F     i P i   )maxsize	reference
new_string	thresholdreturnc                     t         j                  d|       } t         j                  d|      }t        d| |      j                         |k\  S )zIReturn the similarity ratio between two short strings, here domain names. N)STRIP_EXTENSIONsubr   ratio)r   r   r   s      r   is_similar_domainr#      sE      ##B	2I $$R4J4J7==?9LLr   tokenstarget_lengthc                     g }t        ddd      D ]5  }| D cg c]  }t        |      |kD  s| }}t        |      |dz  k\  s3|c S  |S c c}w )zCHelper function to get a sample of tokens based on length criteria.      )rangelen)r$   r%   sampleits        r   _get_sample_by_lengthr/   !   s^    F1b" #2s1vz!22v;-!++M M 3s
   A
A
inputstringlengthc                     | j                  t              }|j                         D cg c]  }|j                         s| }}t	        ||      S c c}w )u   
    This fallback implementation is used when the primary sample_tokens function
    generates an empty token list. This is mostly relevant for languages like
    mandarin where none latin-based punctuation is used e.g.: 。
    )	translate	PUNCT_TBLsplitisalnumr/   )r0   r1   
clean_textr.   r$   s        r   sample_tokens_fallbackr8   +   sJ     &&y1J#))+;Aqyy{a;F; 00 <s
   AAc                    g }| j                         D ]C  }|j                  t        j                        }|j	                         s3|j                  |       E t        ||      }t        |      dk(  rt        | |      S |S )zbSplit input into list of tokens and adjust length threshold to make sure
    there is enough data.r   )	r5   stripstringpunctuationr6   appendr/   r+   r8   )r0   r1   r$   tokenr,   s        r   sample_tokensr?   7   sv     F""$ !F../==?MM% !
 #662F
6{a%k6::Mr   c                     dj                  t        |             j                         }t        |j	                         |      j                         S )z=Create a bag of words and generate a hash for a given string.r   digest_size)joinr?   r:   r   encodedigest)r0   r1   
teststrings      r   generate_bow_hashrG   H   s=    -45;;=J:$$&F;BBDDr   i @  r>   c                     t         j                  t        | j                         d      j	                         d      }t        |      D cg c]  }|d|z  z  rdnd c}S c c}w )zFToken's contribution to a Simhash vector, cached across all instances.   rA   bigr
   r(   )int
from_bytesr   rD   rE   r*   )r>   r1   
token_hashr-   s       r   _vector_to_addrN   O   sS     A F M M OQVWJ8=fF1qAv&AB.FFFs   A!c            	           e Zd ZdZddgZ	 	 	 ddedededz  ddfdZdedefd	Zdefd
Z	dededz  fdZ
deez  dz  dedz  fdZdd defdZdd defdZy)SimhashzAImplement a basic Charikar hashing approach of string similarity.hashr1   Nr0   existing_hashr   c                 d    || _         | j                  |      xs | j                  |      | _        y)z&Store length and existing or new hash.N)r1   validatecreate_hashrQ   )selfr0   r1   rR   s       r   __init__zSimhash.__init__[   s+     MM-0QD4D4D[4Q	r   c                    dg| j                   z  t        || j                         D ]0  }t        t        t        t        || j                                     2 t        fdt        | j                         D              S )zCalculates a Charikar simhash. References used:
        https://github.com/vilda/shash/
        https://github.com/sean-public/python-hashes/blob/master/hashes/simhash.py
        Optimized for Python by @adbar.
        r   c              3   :   K   | ]  }|   d k\  sd|z    yw)r   r
   N ).0r-   vectors     r   	<genexpr>z&Simhash.create_hash.<locals>.<genexpr>p   s     Haa16Hs   
)r1   r?   listmapr   rN   sumr*   )rV   r0   r>   r\   s      @r   rU   zSimhash.create_hashe   sk     t{{"";< 	PE#c6>%+MNOF	P H5#5HHHr   c                 2    t        | j                        dd S )z3Convert the numerical hash to a hexadecimal string.r)   N)hexrQ   rV   s    r   to_hexzSimhash.to_hexr   s    499~ab!!r   	inputhashc                 F    	 t        |d      S # t        t        f$ r Y yw xY w)z2Convert the hexadecimal hash to a numerical value.   N)rK   	TypeError
ValueErrorrV   re   s     r   _hash_to_intzSimhash._hash_to_intv   s+    	y"%%:& 		s      c                    t        |t              r dt        t        |            cxk  rdk  r|S  t        |t              rA|j	                         r dt        |      cxk  rdk  rt        |      S  | j                  |      S y)z9Validate the input hash and return it, or None otherwise.      N)
isinstancerK   r+   strisdigitrk   rj   s     r   rT   zSimhash.validate}   sy    i%"C	N0C*Ir*I +Ji%  "rS^'Ar'A9~% (B $$Y//r   
other_hashc                 F    t        | j                  |j                  z        S )zJReturn distance between two hashes of equal length using the XOR operator.)BIN_COUNT_FUNCrQ   rV   rr   s     r   hamming_distancezSimhash.hamming_distance   s    dii*//9::r   c                 X    | j                   | j                  |      z
  | j                   z  S )zjCalculate how similar this hash is from another simhash.
        Returns a float from 0.0 to 1.0.
        )r1   rv   ru   s     r   
similarityzSimhash.similarity   s'     d33J??4;;NNr   )r   @   N)__name__
__module____qualname____doc__	__slots__rp   rK   rW   rU   rd   rk   rT   rv   floatrx   rZ   r   r   rP   rP   V   s    G"I $(	RR R Tz	R
 
RIs Is I" "c cDj 	#)d"2 	sTz 	;9 ; ;OY O5 Or   rP   contentc                 4    t        |       j                         S )zACalculate a simhash hex value for meaningful bits of the content.)rP   rd   )r   s    r   content_fingerprintr      s    7""$$r   )r   r
   r)      c                   ^    e Zd ZdZddeddfdZdedefdZdedefd	Zde	d
eddfdZ
ddZy)LRUCachea  
    Pure-Python Least Recently Used (LRU) cache using a circular doubly linked list
    Adapted from CPython functools.py lru_cache decorator implementation
    https://github.com/python/cpython/blob/3.9/Lib/functools.py#L524
    First adapted by https://github.com/vbarbaresi
    r   r   Nc                     t               | _        || _        i | _        g | _        | j                  | j                  d d g| j                  d d  d| _        y )NF)r   lockr   cacherootfull)rV   r   s     r   rW   zLRUCache.__init__   sE    G	+-
!			499dD9		!	r   linkc                     |\  }}}}||c|t         <   |t        <   | j                  t           }|x|t         <   | j                  t        <   ||t        <   | j                  |t         <   |S )N)NEXTPREVr   )rV   r   	link_prev	link_next_keyresultlasts          r   
_move_linkzLRUCache._move_link   sb    -1*	9dF+4i(	$4yy'++T
TYYt_T
YYT
r   keyc                     | j                   5  | j                  j                  |      }|r| j                  |      cddd       S 	 ddd       y# 1 sw Y   yxY w)zgTests if the key that is asked for is in the cache
        and retrieve its value from the linked list.Nr(   )r   r   getr   )rV   r   r   s      r   r   zLRUCache.get   sS     YY 	-::>>#&Dt,	- 	-	- 		- s   .AAvaluec                    | j                   5  | j                  j                  |      }|r)| j                  |       || j                  |   t        <   n| j
                  r| j                  }||c|t        <   |t        <   |t           | _        | j                  t           }dx| j                  t        <   | j                  t        <   | j                  |= || j                  |<   nu| j                  t           }|| j                  ||g}|x|t        <   x| j                  t        <   | j                  |<   t        | j                        | j                  k\  | _        ddd       y# 1 sw Y   yxY w)z Stores a given key in the cache.N)r   r   r   r   RESULTr   r   KEYr   r   r+   r   )rV   r   r   r   oldrootoldkeyr   s          r   putzLRUCache.put   s*    YY  	@::>>#&D%*/

3'99"iiG471GCL'&/ !(DI!YYs^F9==DIIcNTYYv%6

6* '.DJJsO  99T?D $))S%8DEIIDJI44::c? !$DJJ4<< ?DIA 	@  	@  	@s   EE!!E*c                     | j                   5  | j                  j                          | j                  | j                  ddg| j                  dd d| _        ddd       y# 1 sw Y   yxY w)zDelete all cache content.NF)r   r   clearr   r   rc   s    r   r   zLRUCache.clear   sS    YY 	JJ IItyy$=DIIaLDI	 	 	s   A	AA()   )r   N)rz   r{   r|   r}   rK   rW   r   r   r   rp   r   r   rZ   r   r   r   r      sd    	 	d 	s s s s #@s #@3 #@4 #@Jr   r   rF   c                 r    t         j                  |       }|dk7  r|dz   nd}t         j                  | |       y)zImplement LRU cache.r(   r
   N)LRU_TESTr   r   )rF   cachevalr   s      r   put_in_cacher      s/    ||J'H$NHqLELLU#r   elementoptionsc                    t        dj                  | j                                     }t        |      |j                  kD  r>t
        j                  |      }||j                  kD  rt
        j                  ||dz          yt        |       y)z(Check for duplicate text with LRU cache.r   r
   TF)
r   rC   itertextr+   min_duplcheck_sizer   r   max_repetitionsr   r   )r   r   rF   r   s       r   duplicate_testr      sl    chhw//123J
:333<<
+g---LLX\2r   )g      ?)ry   )   )6r}   rer;   unicodedatadifflibr   	functoolsr   hashlibr   operatorr   	threadingr   typingr   
lxml.etreer	   settingsr   r   utilsr   compiler    getattrrK   rt   rp   	maketransr*   categorychrr4   r   boolr#   r^   r/   r8   r?   bytesrG   rN   rP   r   r   r   r   r   r   r   r   r   )r-   s   0r   <module>r      s   @ 	   #       ) "**/0k+FGMM5?ea>Rk>R>RSVWXSY>Z[\>]ad>d1c6ef	 4M M# M% MRV M M$s) C DI 	1 	1S 	1$s) 	1s C c "E3 E EU E 5G# Gs GtCy G G:O :Oz% % %
 % dCP Pf H%$S $T $H y T G fs   9#EE