
    IZj'<                        d Z ddlZddlmZ ddlmZmZ ddlmZm	Z	m
Z
mZmZmZ ddlmZ ddlmZ dd	lmZmZmZmZmZ dd
lmZmZmZ ddlmZmZ  ej        e           Z!ddddddddddddZ"d e"#                                D             Z$h dZ%g dZ&dededefdZ'dYdede(defdZ)dZdede*e
         de+defd Z,d!e*e         de-e.e.e.e*e(         f         fd"Z/dZd#ed$e(d%e+de-e+e*e(         f         fd&Z0d#ede+fd'Z1	 	 d[d(ed)e(d*e+d%e+def
d+Z2	 	 d\d-eded.e+d/e+dedz  f
d0Z3d-edededz  fd1Z4d-eddfd2Z5d-eddfd3Z6d$e(dz  de+fd4Z7d-eddfd5Z8d-eddfd6Z9d-eddfd7Z:d-eddfd8Z;i d9e5d:e5d;e5d<e8d=e8d>e8d?e8d@e8dAe8dBe9dCe9dDe6dEe6dFe6dGe:dHe:dIe:dJe;iZ<d-edKe(dz  ddfdLZ=d]dededMe(dz  defdNZ>d;dOdEdDdP dBdQdRdS dT	Z?dedefdUZ@dZdVedWe+de(fdXZAdS )^z*
Functions to process nodes in HTML code.
    N)deepcopy)fix_relative_urlsget_base_url)Element
SubElementXPath_Element
strip_tagstostring)HtmlElement   )duplicate_test)CUT_EMPTY_ELEMSMANUALLY_CLEANEDMANUALLY_STRIPPEDDocument	Extractor)is_image_element
textfiltertrim)META_ATTRIBUTESdelete_element#iz#bz#uz#tz#subz#sup)emibstrongukbdsampttvarsubsupc                     i | ]\  }}||	S  r&   ).0kvs      f/Users/jameslopez/projects/MentorCore/.venv/lib/python3.11/site-packages/trafilatura/htmlprocessing.py
<dictcomp>r+   (   s    >>>TQAq>>>    >   figuresourcepicture){z("z('z
    treeoptionsreturnc                    t          j                    t          j                    }}|j        s|                    g d           n|                     d          D ]	}d|_        
|j        r!d |D             }|                    d           t          | |           |j
        dk    rh|                     d          St          |           }|D ])}|                     |          D ]}t          |           *|                     d          |} n,|D ])}|                     |          D ]}t          |           *t          | |j
                  S )z/Prune the tree by discarding unwanted elements.)tabletdthtrz.//figure[descendant::table]divc                 $    g | ]}|t           v|S r&   )PRESERVE_IMG_CLEANINGr'   es     r*   
<listcomp>z!tree_cleaning.<locals>.<listcomp>;   s#    TTTqQ>S5S5S5S5S5Sr,   imgrecallz.//p)r   copyr   tablesextendxpathtagimagesremover
   focusfindr   iterr   
prune_html)r1   r2   cleaning_liststripping_listelemtcopy
expressionelements           r*   tree_cleaningrR   /   s    %5$9$;$;=N=S=U=U>M> 8889999 JJ=>> 	 	DDHH~ %TTMTTTe$$$ t^$$$ }  TYYv%6%6%B' 	( 	(J99Z00 ( (w''''(99V$D ( 	( 	(J99Z00 ( (w''''( dGM***r,   balancedrH   c                     |dk    }|                      d          D ]!}|j        t          v rt          ||           "| S )zADelete selected empty elements to save space and processing time.	precisionz-.//processing-instruction()|.//*[not(node())])	keep_tail)rD   rE   r   r   )r1   rH   tailsrQ   s       r*   rK   rK   R   sN    [ E::MNN 5 5;/))7e4444Kr,   Fnodelistwith_backupc                    |r0t          |                                           }t          |           }|D ]} ||           D ]}t          |            |r.t          |                                           }||dz  k    r| n|S | S )z2Prune the HTML tree by removing unwanted sections.   )lentext_contentr   r   )r1   rX   rY   old_lenbackuprP   subtreenew_lens           r*   prune_unwanted_nodesrb   \   s      d''))**$ $ $
!z$'' 	$ 	$G 7####		$  9d''))**1,,tt&8Kr,   links_xpathc                     d d | D             D             }t          t          t          |                    }t          d |D                       }t          |          t          |          ||fS )zCollect heuristics on link textc                     g | ]}||S r&   r&   r<   s     r*   r>   z%collect_link_info.<locals>.<listcomp>t   s    RRRAPQRaRRRr,   c              3   X   K   | ]%}t          |                                          V  &d S N)r   r]   )r'   rN   s     r*   	<genexpr>z$collect_link_info.<locals>.<genexpr>t   s6      LL$t002233LLLLLLr,   c              3   &   K   | ]}|d k     dV  dS )
   r   Nr&   )r'   lengths     r*   rh   z$collect_link_info.<locals>.<genexpr>w   s&      <<6Q<<r,   )listmapr\   sum)rc   mylistlengths
shortelemss       r*   collect_link_inforr   p   su     SRLLLLLRRRF3sF##$$G<<W<<<<<Jw<<Vj&88r,   rQ   textfavor_precisionc                    |                      d          }|sdg fS |                     d          dg fS g }t          |          dk    rg|rdnd}t          |d                                                   }t          |          |k    r't          |          t          |          d	z  k    rd
g fS | j        dk    r|                                 dnd}n|                                 d}nd}t          |          }||k     rXt          |          \  }	}
}}|
dk    rd
|fS t          	                    d|	|||
           |	|dz  k    s|
dk    r||
z  dk    rd
|fS d|fS )z>Remove sections which are rich in links (probably boilerplate).//refFz
.//graphicNr   rj   d   r   g?Tp<      i,  u8   list link text/total: %s/%s – short elems/total: %s/%s皙?)
findallrI   r\   r   r]   rE   getnextrr   LOGGERdebug)rQ   rs   rt   rc   ro   len_threshold	link_textlimitlenelemlenlinklenelemnumrq   s               r*   link_density_testr   {   s   //(++K by||L!!-byF
;1-63Q446677	y>>M))c)nns4yy3.N.N8O{c **222??$HH H$iiG/@/M/M,*fa<<<F	
 	
 	
 Ws]""w{{zG7Kc7Q7Q<&=r,   c                 @   |                      d          }|sdS t          t          |                                                     }|dk     rdS t	          |          \  }}}}|dk    rdS t
                              d||           |dk     r	|d|z  k    n|d	|z  k    S )
z=Remove tables which are rich in links (probably boilerplate).rv   F   r   Tztable link text: %s / total: %si  r{   g      ?)r|   r\   r   r]   rr   r~   r   )rQ   rc   r   r   r   _s         r*   link_density_test_tablesr      s    //(++K u$w++--..//G}}u.{;;GWa!||t
LL2GWEEE&-nn7S7]""'C'M:QQr,   r`   tagnamebacktrackingc                    g }|rdnd}|rdnd}|                      |          D ]}t          |                                          }t          |||          \  }	}
|	s4|rG|
rEdt	          |          cxk     r|k     r+n Zt	          |          |k    r|                    |           t                              |          D ]}t          |           | S )z{Determine the link density of elements with respect to their length,
    and remove the elements identified as boilerplate.r   rw   r      r   )	rJ   r   r]   r   r\   appenddictfromkeysr   )r`   r   r   rt   	deletionsr   depth_thresholdrN   elemtextresulttemplists              r*   delete_by_link_densityr      s	    I*3CCM*1aaOW%% # #))++,,,T8_MM 	#l 	#x 	#AH4U4U4U4U4U4U4U4U4UZ]^bZcZcgvZvZvT""" i((  tNr,   TrN   comments_fixpreserve_spacesc                 R   | j         dk    rt          |           r| S | j         dk    s!t          |           dk    r| j        s	| j        sdS |s*| j         dk    r|st          | j                  pd| _        | S | j        s;t          |           dk    r(| j        dc| _        | _        |r| j         dk    rd| _         |s=t          | j                  pd| _        | j        rt          | j                  pd| _        | j        st          |           s|j        rt          | |          rdS | S )z3Convert, format, and probe potential text elements.graphicdoner   Nlb rx   )	rE   r   r\   rs   tailr   r   dedupr   )rN   r2   r   r   s       r*   handle_textnoder      sL    x9!1$!7!7x6c$ii1nnTYntynt  DH,, 	0TY/4DI 9 Ta  $y"	49 	DH,,DH  0OO+t	9 	0TY/4DI 9 D)) gm tU\@]@] tKr,   c                    | j         dk    s!t          |           dk    r| j        s	| j        sdS t	          | j                  pdt	          | j                  pdc| _        | _        | j         dk    r"| j        s| j        r| j        dc| _        | _        | j        s| j        r(t          |           s|j        rt          | |          rdS | S )zBConvert, format, and probe potential text elements (light format).r   r   Nr   )rE   r\   rs   r   r   r   r   r   )rN   r2   s     r*   process_noder      s    x6c$ii1nnTYntynt  	??2dDOO4KtDIty x4	di#y$	49 y DI d 	 	.w2O2O 	4Kr,   c                    |                      d| j                   d| _        d}|                     ddd          D ]O}|j        dv r=|                     dt          |j                   d|            |j        dk    r|dz  }d	|_        Pd
S )zGConvert <ul> and <ol> to <list> and underlying <li> elements to <item>.rendrl   r   dddtli)r   r   -itemN)setrE   rJ   str)rN   r   subelems      r*   convert_listsr     s    HHVTXDH	A99T4..  ;,&&KK3w{#3#3 9 9a 9 9:::{d""Q r,   c                    d}| j         dk    rst          |           dk    r| d         j         dk    rd}|                     d          }|r d}|D ]}|j                                         t          | j                  rd}|rdnd	| _         d
S )z?Convert quoted elements while accounting for nested structures.Fprer   r   spanTz#.//span[starts-with(@class,'hljs')]codequoteN)rE   r\   rD   attribclear_is_code_blockrs   )rN   	code_flag
code_elemsr   s       r*   convert_quotesr     s    Ix5 t99>>d1gkV33IZZ EFF
 	'I% ' '$$&&&&$)$$ 	I"/vvDHHHr,   c                 0    | sdS t           D ]	}|| v r dS 
dS )z2Check if the element text is part of a code block.FT)CODE_INDICATORS)rs   	indicators     r*   r   r   2  s:     u$  	44 5r,   c                 |    | j                                          |                     d| j                   d| _        dS )z$Add head tags and delete attributes.r   headN)r   r   r   rE   rN   s    r*   convert_headingsr   <  s7    KHHVTXDHHHr,   c                     d| _         dS )zConvert <br> and <hr> to <lb>r   N)rE   r   s    r*   convert_line_breaksr   C  s    DHHHr,   c                 @    d| _         |                     dd           dS )z7Convert <del>, <s>, <strike> to <del rend="overstrike">delr   
overstrikeN)rE   r   r   s    r*   convert_deletionsr   H  s#    DHHHV\"""""r,   c                 R    d| _         |                     d          D ]	}d|_         
dS )zHandle details and summary.r9   summaryr   N)rE   rJ   )rN   r   s     r*   convert_detailsr   N  s7    DH99Y''   r,   dlolulh1h2h3h4h5h6brhr
blockquoter   qr   sstrikedetailsbase_urlc                     d| _         |                     d          }| j                                         |r*|rt	          ||          }|                     d|           dS dS )z7Replace link tags and href attributes, delete the rest.refhreftargetN)rE   getr   r   r   r   )rN   r   r   s      r*   convert_linkr   l  sq    DHXXfFK # 	9&x88F6"""""	# #r,   urlc                 |   |j         s>d}|j        r|dz  }|                     |          D ]	}d|_        
t	          | d           n:|ot          |          }|                     dd          D ]}t          ||           |j        rv|                     t          
                                          D ]H}|j                                         |                    dt          |j                            d|_        In$t	          | gt          
                                R   |                     t          
                                          D ]}t          |j                 |           |j        r|                     d          D ]	}d|_        
|j         rt!          |                     d                    D ]}t!          |                    d                    }t#          |          D ]}|                    |           |r5|                                                                st+          |           | S )	zBSimplify markup and convert relevant HTML tags to an XML standard.z).//*[self::div or self::li or self::p]//az|.//table//ar   ar   hir?   r   )linksrB   rD   rE   r
   r   rJ   r   
formattingREND_TAG_MAPPINGkeysr   r   r   CONVERSIONSrF   rl   reversedaddnextr]   stripr   )	r1   r2   r   
xpath_exprrN   r   r   graphicsr   s	            r*   convert_tagsr   x  sV    = )@
> 	).(JJJz** 	 	DDHH4 ,<,,IIc5)) 	) 	)Dx(((( 3II.335566 	 	DKHHV-dh7888DHH	
 	42*//112222 		+**,,-- $ $DHd####~ (IIe$$ 	! 	!D DHH= 
	(DIIe,,-- 	( 	( 3 344'11 ) )GKK((((  (C$4$4$6$6$<$<$>$> ("3'''Kr,   r   c                 ^    dt          |                     dd          dd                     S )Nhr   r   r   )intr   r   s    r*   <lambda>r     s.    >S&$!7!7!;<<>> r,   r   r   c                 D    t           |                     dd                   S )Nr   r   )HTML_TAG_MAPPINGr   r   s    r*   r   r     s    '(>(>? r,   )	rl   r   r   r   r   r   r?   r   r   c                    |                      t                                                    D ]}t          t          |j                           }t          |          r ||          |_        n||_        |j        dk    r0|                    d|j                            dd                     |j        	                                 d| _        t          d          }|                    |            |S )zConvert XML to simplified HTML.r   r   r   r   bodyhtml)rJ   HTML_CONVERSIONSr   r   rE   callabler   r   popr   r   r   )r1   rN   
conversionroots       r*   convert_to_htmlr     s    		*//1122    %c$(mm4
J 	"!z$''DHH!DH8s??HHVT[__Xr::;;;;KDH6??DKKKr,   documentwith_metadatac                    t          | j                  }|rTt          d          }t          D ]'}t	          | |          x}rt          |d||           (|                    d|           t          |dd                                          S )z1Convert the document to HTML and return a string.r   meta)namecontentr   Tunicode)pretty_printencoding)	r   r   r   r   getattrr   insertr   r   )r   r   	html_treer   r   values         r*   build_html_outputr    s    ..I "v# 	C 	CD$///u C4dEBBBBD!!!ID9EEEKKMMMr,   )rS   )F)FF)TFrg   )B__doc__loggingrA   r   courlan.urlutilsr   r   
lxml.etreer   r   r   r	   r
   r   	lxml.htmlr   deduplicationr   settingsr   r   r   r   r   utilsr   r   r   xmlr   r   	getLogger__name__r~   r   itemsr   r;   r   rR   r   rK   rl   boolrb   tupler   rr   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r&   r,   r*   <module>r     sz           < < < < < < < < Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q ! ! ! ! ! ! ) ) ) ) ) )              6 5 5 5 5 5 5 5 5 5 0 0 0 0 0 0 0 0		8	$	$ 			
   ?>%5%;%;%=%=>>> 777 --- +  +i  +K  +  +  +  +F [  k     { d5k PT al    (9k"9
3S$s)#$9 9 9 9& &{ &# & &Y^_ceijmen_nYo & & & &RRk Rd R R R R, !	   	
    : !	' '
'' ' 	'
 _' ' ' 'Tx ) 4    ( T     0 0d 0 0 0 0&t     8     h 4    
#H # # # # #( t    -- 	- 	
	
 	
 	
 	
 	
 	
 	
 	
 . 
>  
  	!" #$ % .	#{ 	#cDj 	#T 	# 	# 	# 	#. .{ .Y .S4Z .S^ . . . .d >>

?
?
 
 ( x    (N N N N# N N N N N Nr,   