
    AHjC                        d Z ddlZddlZddlZddlmZmZ ddlmZ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ZddlZddlm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$ 	 ddl%m&Z& ejN                  jQ                  d      Z)	 ddl+Z+ e+jX                         Z-e-j]                  e+j^                  e+j`                         e-j]                  e+j^                  e+jb                         dZ2 ejf                  e4      Z5 ejl                  ejn                  jp                         da9da:da;dedejx                  ez  fdZ=dJdZ>ej~                  j                  d      ZAe rdeAd   vreAdxx   dz  cc<   d ed      z   dz   ZBeBeAd<   g d ZCh d!ZD G d" d#      ZEd$edeFeGeH   dz  eHdz  f   fd%ZIdKd$ed&eJeHeHf   dz  deJeHeHf   fd'ZKd$edej~                  j                  fd(ZMdLd$ed)eNdejx                  ez  fd*ZOd+eHd)eNd,eNd$edeEdz  f
d-ZPd+eHd.eEd/edeNfd0ZQd+eHd.eEd1eNd/edeEeHz  dz  f
d2ZRdedfd+eHd)eNd$ed/edz  deHdz  f
d3ZSddded4d+eHd1eNd)eNd,eNd$edeEdz  fd5ZTd+eHdeNfd6ZUd+eHdeNfd7ZVd+eHdeNfd8ZW	 	 	 	 	 dMd9eGeH   d:eXeH   dz  d;eHdz  d<edz  d=eNd>eNdefd?ZYdNd<ed@eZdeFeGeH   ef   fdAZ[	 dOdBeGeH   dCe\dDeeHgef   dEe\deeFeHef   ddf   f
dFZ]	 dKdBeGeH   dCe\d/edz  deeFeHeHf   ddf   fdGZ^	 dKdBeGeH   dCe\d/edz  deeFeHeEf   ddf   fdHZ_d+eHd)eNd,eNd$edeEdz  f
dIZ`y# e*$ r dZ)Y w xY w# e*$ r dZ2Y Pw xY w)PzG
All functions needed to steer and execute downloads of web documents.
    N)Callable	Generator)ThreadPoolExecutoras_completed)ConfigParser)partial)version)BytesIO)sleep)Any)UrlStore)redirection_test   )DEFAULT_CONFIG	Extractor)HAS_ZSTDURL_BLACKLIST_REGEXdecode_fileis_acceptable_lengthmake_chunks)SOCKSProxyManager
http_proxyTFargsreturnc                  x    t         rt        nt        j                  }t         rdt         ini }d|d<    |di || S )zCConfigure urllib3 download pool according to user-defined settings.	proxy_url2   	num_pools )	PROXY_URLr   urllib3PoolManager)r   manager_classmanager_argss      M/root/tools/cai/cai_env/lib/python3.12/site-packages/trafilatura/downloads.pycreate_poolr&   @   s=    )2%8K8KM/8K+bL "L0<0400    c                 Z    t         r%| j                  t        j                  t                yy)zBRoute the pycurl request through PROXY_URL when one is configured.N)r    setoptpycurl	PRE_PROXY)curls    r%   _apply_curl_proxyr-   H   s    F$$i0 r'   )accept_encodingzstdzaccept-encodingz,zstdztrafilatura/trafilaturaz( (+https://github.com/adbar/trafilatura)
User-Agent)i  i  i  i  i  i  i  i  i	  i
  i  i  i  i  i  i  iV  >   #   6   :   ;   <   @   B   M   R   S   [   c                       e Zd ZdZg dZdedededdfdZde	fd	Z
defd
Zdeeef   ddfdZde	ddfdZdeeef   fdZy)Responsez5Store information gathered in a HTTP response object.dataheadershtmlstatusurlr@   rC   rD   r   Nc                 J    || _         d | _        d | _        || _        || _        y Nr?   )selfr@   rC   rD   s       r%   __init__zResponse.__init__p   s%    	.2 $	r'   c                     | j                   d uS rF   )r@   rG   s    r%   __bool__zResponse.__bool__w   s    yy$$r'   c                 H    | j                   xs t        | j                        S rF   )rB   r   r@   rJ   s    r%   __repr__zResponse.__repr__z   s    yy2K		22r'   
headerdictc                 ~    |j                         D ci c]  \  }}|j                         | c}}| _        yc c}}w )z#Store response headers if required.N)itemslowerrA   )rG   rN   kvs       r%   store_headerszResponse.store_headers}   s0     2<1A1A1CDA	1DDs   9decodec                 X    |r(| j                   rt        | j                         | _        yyy)z9Decode the bytestring in data and store a string in html.N)r@   r   rB   )rG   rU   s     r%   decode_datazResponse.decode_data   s"    dii#DII.DI  6r'   c                 V    | j                   D ci c]  }|t        | |       c}S c c}w )z,Convert the response object to a dictionary.)	__slots__getattr)rG   attrs     r%   as_dictzResponse.as_dict   s&    6:nnEdgdD))EEEs   &)__name__
__module____qualname____doc__rY   bytesintstrrH   boolrK   rM   dictrT   rW   r\   r   r'   r%   r>   r>   k   s    ;<IU C c d %$ %3# 3ES#X E4 E
/$ /4 /
Fc3h Fr'   r>   configc                     | j                  ddd      j                         }|r|j                         nd}| j                  dd      xs d}||fS )zARead and extract HTTP header strings from the configuration file.DEFAULTUSER_AGENTS )fallbackNCOOKIE)getstrip
splitlines)rf   myagents
agent_listmycookies       r%   _parse_configrs      sU     zz)]Rz@FFHH*2$$&J zz)X.6$Hxr'   rA   c                     | t         k7  r1t        |       \  }}i }|rt        j                  |      |d<   |r||d<   |xs t        S )z1Internal function to decide on user-agent string.r1   Cookie)r   rs   randomchoiceDEFAULT_HEADERS)rf   rA   rp   rr   s       r%   _determine_headersry      sL    *62($*MM($;GL! (GH%o%r'   c           	          t         s[t        j                  j                  | j	                  dd      | j	                  dd      d| j	                  dd      dz  t
              a t         S )z5Define a retry strategy according to the config file.rh   MAX_REDIRECTSr   DOWNLOAD_TIMEOUT   )totalredirectconnectbackoff_factorstatus_forcelist)RETRY_STRATEGYr!   utilRetrygetintFORCE_STATUSrf   s    r%   _get_retry_strategyr      s^      ++--	?;]]9o>!==4FG!K) , 
 r'   no_sslc                     |rt         nt        }|s@t        | j                  dd      |rdnt	        j
                         |rdnd      }|r|a |S |a|S )zXCreate a urllib3 pool manager according to options in the config file and HTTPS setting.rh   r|   N	CERT_NONECERT_REQUIRED)timeoutca_certs	cert_reqs)NO_CERT_POOL	HTTP_POOLr&   r   certifiwhere)rf   r   pools      r%   _initiate_poolr      sZ     "<yDMM)-?@#T%+k
 L K IKr'   rD   with_headersc                    	 t        ||      }|j                  d| t        |      t        |      d      }t	               }|j                  dd      }|j                  d      D ],  }|j                  |       t        |      |kD  s#t        d       |j                          t        t        |      |j                  |j                               }	|r|	j                  |j                          |	S # t"        j$                  j&                  $ r' t(        j+                  d	|        t-        | d
||      cY S t.        $ r!}
t(        j1                  d| |
       Y d}
~
yd}
~
ww xY w)zPInternal function to robustly send a request (SSL or not) and return its result.)r   GETF)rA   retriespreload_contentrh   MAX_FILE_SIZEi   zMAX_FILE_SIZE exceededzretrying after SSLError: %sTzdownload error: %s %sN)r   requestry   r   	bytearrayr   streamextendlen
ValueErrorrelease_connr>   ra   rC   geturlrT   rA   r!   
exceptionsSSLErrorLOGGERwarning_send_urllib_request	Exceptionerror)rD   r   r   rf   pool_managerresponser@   max_file_sizechunkresperrs              r%   r   r      s=   8%fV<  ''&v.'/! ( 
 {iA__U+ 	;EKK4y=( !9::	; 	 dX__hoo6GHx//0&& E4c:#C|VDD 8,c3778s&   BC0 A(C0 0AE3E;EEr   optionsc                     t        |j                  xs |j                  xs d      }|j                  dk7  r"t        j                  d|j                  |        yt        ||      syy)z2Check if the response conforms to formal criteria.rj      z!not a 200 response: %s for URL %sFT)r   rB   r@   rC   r   r   r   )rD   r   r   lentests       r%   _is_suitable_responser      sR    (--68==6B7G#8(//3O1r'   rU   c                 >    t        | ||      r|r|j                  S |S y)z:Internal function to run safety checks on response result.N)r   rB   )rD   r   rU   r   s       r%   _handle_responser      s$     S(G4 &x}}4H4r'   c                     |r|j                   n|}t        | d||      }|r3|j                  r'|st        |      }t	        | ||      r|j
                  S y)a  Downloads a web page and seamlessly decodes the response.

    Args:
        url: URL of the page to fetch.
        no_ssl: Do not try to establish a secure connection (to prevent SSLError).
        config: Pass configuration values for output control.
        options: Extraction options (supersedes config).

    Returns:
        Unicode string or None in case of failed downloads and invalid results.

    T)rU   r   rf   r   N)rf   fetch_responser@   r   r   rB   )rD   r   rf   r   r   s        r%   	fetch_urlr     sP    $  'W^^FFc$vfMHHMMv.G h8== r'   )rU   r   r   rf   c                    t         st        nt        }t        j	                  d|         || |||      }|st        j	                  d|        y|j                  |       |S )a  Downloads a web page and returns a full response object.

    Args:
        url: URL of the page to fetch.
        decode: Use html attribute to decode the data (boolean).
        no_ssl: Don't try to establish a secure connection (to prevent SSLError).
        with_headers: Keep track of the response headers.
        config: Pass configuration values for output control.

    Returns:
        Response object or None in case of failed downloads and invalid results.

    zsending request: %szrequest failed: %sN)
HAS_PYCURLr   _send_pycurl_requestr   debugrW   )rD   rU   r   r   rf   dl_functionr   s          r%   r   r      sV    * /9&>RK
LL&,3f=H)3/ Or'   c                    d}t        j                         }|j                  t         j                  | j	                  d             |j                  t         j
                  d       |j                  t         j                  d       |j                  t         j                  d       |j                  t         j                  d       t        |       	 |j                          |j                  t         j                        dk  }|j!                          |S # t         j                  $ r#}t        j                  d| |       d}Y d}~Cd}~ww xY w)	z+Send a basic HTTP HEAD request with pycurl.Futf-8
   r   Ti  zpycurl HEAD error: %s %sN)r*   Curlr)   URLencodeCONNECTTIMEOUTSSL_VERIFYPEERSSL_VERIFYHOSTNOBODYr-   performgetinfoRESPONSE_CODEr   r   r   close)rD   page_existsr,   r   s       r%   _pycurl_is_live_pager   ?  s    K;;=DKK

CJJw/0KK%%r*KK%%q)KK%%q)KKt$dll6#7#783>
 	JJL << /c:s   2D E)EEc                 v    	 t        |       }y# t        $ r!}t        j                  d| |       Y d}~yd}~ww xY w)zGUse courlan redirection test (based on urllib3) to send a HEAD request.zurllib3 HEAD error: %s %sNFT)r   r   r   r   )rD   _r   s      r%   _urllib3_is_live_pager   Z  s<    S!   0#s;s    	838c                 F    t         rt        |       nd}|xs t        |       S )zCSend a HTTP HEAD request without taking anything else into account.F)r   r   r   )rD   results     r%   is_live_pager   d  s"    *4!#&%F/*3//r'   	inputlist	blacklist
url_filter	url_storecompressionverbosec                 <   |t        |d|      }t        t        j                  |             } |r(| D cg c]  }t	        j
                  d|      |vs| } }|r%| D cg c]  t        fd|D              s } }|j                  |        |S c c}w c c}w )zMFilter, convert input URLs and add them to domain-aware processing dictionaryF)
compressedstrictr   rj   c              3   &   K   | ]  }|v  
 y wrF   r   ).0fus     r%   	<genexpr>z)add_to_compressed_dict.<locals>.<genexpr>}  s     0LAa0Ls   )r   listre   fromkeysr   subanyadd_urls)r   r   r   r   r   r   r   s         `r%   add_to_compressed_dictr   k  s     E7S	T]]9-.I )]1-@-D-DR-KS\-\Q]	] )M1S0L0L-LQM	My! ^ Ns   BB!B;B
sleep_timec                 h    	 | j                  |d      }|s| j                  r	 || fS t        |       2)zRDetermine threading strategy and draw URLs respecting domain-based back-off rules.i )
time_limitmax_urls)get_download_urlsdoner   )r   r   
bufferlists      r%   load_download_bufferr     sA    
00JQV0W
y   	j	 r'   r   download_threadsworker	chunksizec           	   #   
  K   t        |      5 }t        | |      D ]I  }|D ci c]  }|j                  ||      | }}t        |      D ]  }||   |j	                         f  K 	 ddd       yc c}w # 1 sw Y   yxY ww)z3Use a thread pool to perform a series of downloads.)max_workersN)r   r   submitr   r   )	r   r   r   r   executorr   rD   future_to_urlfutures	            r%   _buffered_downloadsr     s      
(8	9 =X Y7 	=EJOP3X__VS93>PMP&}5 =#F+V]]_<<=	== =P= =s,   BA7A2+A7)	B2A77B <Bc                 >    t        t        |      }t        | ||      S )z3Download queue consumer, single- or multi-threaded.)r   )r   r   r   )r   r   r   r   s       r%   buffered_downloadsr     s      Y0Fz+;VDDr'   c                 f    |r|j                   nt        }t        t        |      }t	        | ||      S )z7Download queue consumer, returns full Response objects.r   )rf   r   r   r   r   )r   r   r   rf   r   s        r%   buffered_response_downloadsr     s-      'W^^NF^F3Fz+;VDDr'   c                    t        |      j                         D cg c]  \  }}| d|  }}}t        j                         }|j	                  t        j
                  | j                  d             |j	                  t        j                  t               |j	                  t        j                  |       |j	                  t        j                  d       |j	                  t        j                  |j                  dd             |j	                  t        j                  |j                  dd             |j	                  t        j                  |j                  dd             |j	                  t        j                  |j                  dd             |j	                  t        j                   d       |du rA|j	                  t        j"                  d	       |j	                  t        j$                  d	       n2|j	                  t        j&                  t)        j*                                |r4t-               }|j	                  t        j.                  |j0                         t3        |       	 |j5                         }	tC        |	|jE                  t        jF                        |jE                  t        jH                              }|jK                          |ri }jM                         jO                  dd      jQ                         D ]=  }d|vr|jS                  dd      \  }}|jU                         ||jU                         <   ? |jW                  |       |S c c}}w # t        j6                  $ rd}
t8        j7                  d
| |
       |du r?|
j:                  d	   t<        v r*t8        j?                  d| |
       tA        | d||      cY d}
~
S Y d}
~
yd}
~
ww xY w)zDExperimental function using libcurl and pycurl to speed up downloadsz: r   r   rh   r{   r|   r   Tr   zpycurl error: %s %sFzretrying after SSL error: %s %sNz
iso-8859-1replace)errors:),ry   rP   r*   r   r)   r   r   SHARE
CURL_SHARE
HTTPHEADERFOLLOWLOCATION	MAXREDIRSr   r   TIMEOUTMAXFILESIZENOSIGNALr   r   CAINFOr   r   r
   HEADERFUNCTIONwriter-   
perform_rbr   r   r   CURL_SSL_ERRORSr   r   r>   r   r   EFFECTIVE_URLr   getvaluerU   ro   splitrn   rT   )rD   r   r   rf   headercontent
headerlistr,   headerbytesbufferbytesr   r   respheaderslinenamevalues                   r%   r   r     s   
 ASSY@Z@`@`@bc_VWVHBwi(cJc ;;=DKK

CJJw/0KKj)KK!!:.KK%%q)KK  &--	?"KLKK%%v}}Y@R'STKKi9K LMKK""FMM)_$MNKK#~F))1-F))1-FMM7==?3iF));+<+<=doo'" Kf.B.B!CT\\RXRfRfEghDJJL((*11,y1Q\\^ 	6D $**S!,KD%(-K

%	6 	;'KK dH << *C5
 U?sxx{o=LL:CE'T<HH s$   M1M$ $O7AOOO)r,   zpycurl.Curlr   NrF   )F)NNNFF)g      @)i'  )ar`   loggingosrv   collections.abcr   r   concurrent.futuresr   r   configparserr   	functoolsr   importlib.metadatar	   ior
   timer   typingr   r   r!   courlanr   courlan.networkr   settingsr   r   utilsr   r   r   r   r   urllib3.contrib.socksr   environrm   r    ImportErrorr*   	CurlSharer  r)   SH_SHARELOCK_DATA_DNSLOCK_DATA_SSL_SESSIONr   	getLoggerr]   r   disable_warningsr   InsecureRequestWarningr   r   r   r"   r&   r-   r   make_headersrx   
USER_AGENTr   r  r>   tupler   rc   rs   re   ry   r   r   rd   r   r   r   r   r   r   r   r   r   setr   floatr   rb   r   r   r   r   r   r'   r%   <module>r;     s}    	  / ? %  &      , / 7

|,I!!!#J foov';';<foov'C'CD J
 
		8	$   ++BB C	1 1 3 3c 9 11 ,,++D+Ao.?@@%&'1&gm447aa
 * ( ?F FF ,  5cT1A3:1M+N  	&| 	&d38nt6K 	&W[\_ad\dWe 	& 1C1C  <  'BUBUX[B[ *!c !4 !t !\ !^fim^m !H	s 	h 	 	t 		 *.9B^d ) $		  	
 	4Z> )	  	
   _>c d 6s t 0c 0d 0 "&!!%Cy3x$ d
 $	
   0!H !% !%PTUXPY[cPcJd ! 	=S	== cUCZ = 	=
 uS#Xd*+=" !%ES	EE E uS#Xd*+	E !%	ES		E	E 	E uS(]#T4/0		EJc J4 Jt J\ J^fim^m JY  I  Js%   .!L+ A#L9 +L65L69MM