
    Si7                         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mZ d dl	m
Z
 d dl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mZmZ  G d de      Z G d de e      Z!y)    )absolute_import)division)print_function)unicode_literals   )ProxyGeneratorMaxTriesExceededExceptionDOSException)BeautifulSoupN)Timeout)TimeoutException)By_SearchScholarIterator)AuthorParser)PublicationParser)AuthorPublicationSource	ProxyModec                   "     e Zd Zi Z fdZ xZS )	Singletonc                 ~    | | j                   vr t        t        |   |i || j                   | <   | j                   |    S N)
_instancessuperr   __call__)clsargskwargs	__class__s      L/home/agent/.friday_env/lib/python3.12/site-packages/scholarly/_navigator.pyr   zSingleton.__call__   sD    cnn$"'	3"@$ #KCI#KCNN3~~c""    )__name__
__module____qualname__r   r   __classcell__r    s   @r!   r   r      s    J# #r"   r   c                       e Zd ZdZ fdZdefdZdefdZd!de	d	e	fd
Z
d"dZd#dededefdZdeddfdZdefdZd"defdZdefdZdedefdZdedefdZ	 d#dededefdZdedefdZd$dededededef
dZdededefd Z xZS )%	Navigatorz1A class used to navigate pages on google scholar.c                 @   t         t        |           t        j                  d      | _        d| _        d| _        t               | _	        t               | _
        | j                  j                         | _        | j                  j                         | _        d| _        y )N	scholarly   F)r   r)   __init__logging	getLoggerlogger_TIMEOUT_max_retriesr   pm1pm2get_session	_session1	_session2got_403)selfr    s    r!   r-   zNavigator.__init__#   sv    i')''4 "#!#--/--/r"   enablec                     | j                   j                  |rt        j                         yt        j                         y)z0Enable or disable the logger for google scholar.N)r0   setLevelr.   INFOCRITICAL)r9   r:   s     r!   
set_loggerzNavigator.set_logger2   s'     	fgllL':J:JLr"   timeoutc                     |dk\  r|| _         yy)z+Set timeout period in seconds for scholarlyr   N)r1   )r9   r@   s     r!   set_timeoutzNavigator.set_timeout7   s    a<#DM r"   Npg1pg2c                 @   ||| _         ||| _        nMt               | _        | j                  j                         }|s"| j                  j                  d       || _        | j                   j                         | _        | j                  j                         | _        y )NzWFreeProxy as a secondary proxy is not working. Using the primary proxy for all requests)	r3   r4   r   FreeProxiesr0   infor5   r6   r7   )r9   rC   rD   proxy_workss       r!   	use_proxyzNavigator.use_proxy<   s    ?DH?DH%'DH((..0K   "L M--/--/r"   c                     d| _         |r" | j                  j                  di || _        y  | j                  j                  di || _        y )NF )r8   r3   _new_sessionr6   r4   r7   )r9   premiumr   s      r!   rL   zNavigator._new_sessionM   sB    2TXX22<V<DN2TXX22<V<DNr"   pagerequestrM   returnc                     | j                   j                  d|       d}d}d|v r|s| j                  }| j                  }d}n| j                  }| j
                  }d}|j                  t        j                  u r| j                  d       | j                  }|| j                  k  r	 t        j                  dd	      }t        j                  |       |j!                  ||
      }|du r4| j                   j#                  dj%                  |j&                               | j)                  |j*                        }	|j,                  dk(  r|	s|j*                  S |j,                  dk(  r!| j                   j#                  d       |dz  }|	r.| j                   j                  d       |j/                  |      }|j,                  dk(  r| j                   j                  d       |j1                         s| j                   j                  d       | j2                  s| j                   j                  d       ns|j                  t        j4                  t        j                  fvrGt        j                  dd      }| j                   j                  d|       t        j                  |       | j7                  |       d| _        +| j                   j                  d       nl|j,                  dk(  r7|j8                  r+| j                   j#                  d       |j:                  d   }n&| j                   j                  d|j,                         |dz  }	 |jK                  |||j&                  j!                  d$d      %      \  }}|| j                  k  r|s| jM                  |d      S tO        d'      # t<        $ rx |j1                         se| j                   j                  d       t        j                  dd      }| j                   j                  d|       t        j                  |       Y Y t>        t@        f$ r}
dtC        |
      jD                  d|
jF                  }| j                   j                  |       |d| j                  z  k  r0| j                   j                  d        || j                  z   }Y d}
~
*| j                   j                  d!       Y d}
~
d}
~
wtH        $ rf}
d"tC        |
      jD                  d|
jF                  }| j                   j                  |       | j                   j                  d#       Y d}
~
d}
~
ww xY w# tH        $ r | j                   j                  d&       Y w xY w)(aP  Return the data from a webpage

        :param pagerequest: the page url
        :type pagerequest: str
        :param premium: whether or not to use the premium proxy right away
        :type premium: bool
        :returns: the text from a webpage
        :rtype: {str}
        :raises: MaxTriesExceededException, DOSException
        z
Getting %sNr   z
citations?FT<   r      )r@   zSession proxy config is {}   i  z+Got a 404 error. Attempting with same proxyzGot a captcha request.i  z!Got an access denied error (403).zNo other connections possible.z*Retrying immediately with another session.x   z5Will retry after %.2f seconds (with another session).)rM   z0We can use another connection... let's try that.i.  zGot a redirect.locationzAResponse code %d.
                                    Retrying...z6Will retry after %.2f seconds (with the same session).zTimeout Exception z while fetching page:    z4Increasing timeout and retrying within same session.zGiving up this session.z
Exception zRetrying with a new session.http)	num_triesold_timeout	old_proxyzRNo other secondary connections possible. Using the primary proxy for all requests.z!Cannot Fetch from Google Scholar.)(r0   rG   r4   r7   r3   r6   
proxy_moder   
SCRAPERAPIrB   r1   r2   randomuniformtimesleepgetdebugformat_proxies_requests_has_captchatextstatus_code_handle_captcha2	has_proxyr8   LUMINATIrL   has_redirect_locationheadersr
   r   r   typer#   r   	Exceptionget_next_proxy	_get_pager	   )r9   rN   rM   resptriespmsessionr@   whas_captchaeerrs               r!   rp   zNavigator._get_pageU   s    	{3K''BnnGGBnnGG==I000R d'''AANN1Q'

1{{;{@e#KK%%&B&I&I"++&VW"88C##s*;99$%%,
 KK%%&STQJE KK$$%=> 11+>G%%,KK$$%HI<<>(()IJ#|| KK,,-YZ!}}Y5G5GI]I]4^^$*NN2t$< $ 0 01hjk l $

1))'):'+ (()[\%%,1K1KKK%%&78"&,,z":KKK$$ &3484D4DF. QJE#%#4#4V]ikititixixy  BF  jG#4  $H M d'''Z >>+t44+,OPPA   ||~KK$$%EFr40AKK$$%]_`aJJqM & -. <HLQHXHXZ[Z`Z`a  %Qt}}_,KK$$%[\%5G  !:;; A@DQ@P@PRSRXRXY  %  !?@@A     "M Ns`   &B-N/ /N/ .N/ 4D
N/  BN/ 1U /A;U/U=A<S ?S  U,AUU$U=<U=num_retriesc                 2    |dk  rt        d      || _        y )Nr   z num_retries must not be negative)
ValueErrorr2   )r9   ry   s     r!   _set_retrieszNavigator._set_retries   s    !O?@@'r"   c                 4    | j                  fdfd      S )zTests whether some html text contains a captcha.

        :param text: the webpage text
        :type text: str
        :returns: whether or not the site contains a captcha
        :rtype: {bool}
        c                     d|  dv S )Nzid=""rK   )irf   s    r!   <lambda>z1Navigator._requests_has_captcha.<locals>.<lambda>   s    aS{d* r"   c                     d|  dv S )Nzclass="r   rK   )crf   s    r!   r   z1Navigator._requests_has_captcha.<locals>.<lambda>   s    1~- r"   )_has_captcha)r9   rf   s    `r!   re   zNavigator._requests_has_captcha   s       *-
 	
r"   c                 h    |r| j                   n| j                  | j                  fdfd      S )zTests whether the current webdriver page contains a captcha.

        :returns: whether or not the site contains a captcha
        :rtype: {bool}
        c                 x    t        j                         j                  t        j                  |             dkD  S Nr   )len_get_webdriverfind_elementsr   ID)r   rs   s    r!   r   z2Navigator._webdriver_has_captcha.<locals>.<lambda>   s+    s2,,.<<RUUAFG!K r"   c                 x    t        j                         j                  t        j                  |             dkD  S r   )r   r   r   r   
CLASS_NAME)r   rs   s    r!   r   z2Navigator._webdriver_has_captcha.<locals>.<lambda>   s,    s2,,.<<R]]ANORSS r"   )r3   r4   r   )r9   rM   rs   s     @r!   _webdriver_has_captchaz Navigator._webdriver_has_captcha   s/     !TXXdhh  KS
 	
r"   c                     g d}dg}t        |D cg c]
  } ||       c}      r
t               t        |D cg c]
  } ||       c}      S c c}w c c}w )N)gs_captcha_ccl	recaptchazcaptcha-formzrc-doscaptcha-body)anyr
   )r9   got_id	got_class_CAPTCHA_IDS_DOS_CLASSESr   r   s          r!   r   zNavigator._has_captcha   sX    
 !
 l3	!34. |4!F1I455 44s
   AAurlc                     | j                  dj                  |            }|j                  dd      }t        |d      }	 |j	                  dd      j                  d      | _        |S # t        $ r Y |S w xY w)	z9Return the BeautifulSoup for a page on scholar.google.comzhttps://scholar.google.com{0}     zhtml.parserdiv
gs_res_glb)idzdata-sva)rp   rc   replacer   findra   publibrn   )r9   r   htmlress       r!   	_get_soupzNavigator._get_soup   s|    ~~=DDSIJ||GT*D-0	((5\(:>>zJDK 
  	
	s    'A) )	A65A6c              #     K   | j                  |      }t        |       }	 |j                  dd      }| j                  j	                  dt        |             |D ]  }|j                  |        d}d}|j                  ||z         }|rad|j                  vrS| j                  j	                  d       |d	   d
d } t        j                  d      |      d   }| j                  |      }n| j                  j	                  d       yw)zAGenerator that returns Author objects from the author search pager   gsc_1usrzFound %d authorszgs_btnPR gs_in_ib gs_btn_half z!gs_btn_lsb gs_btn_srt gsc_pgn_pnx)class_disabledzLoading next page of authorsonclick   unicode_escaper   zNo more author pagesN)r   r   find_allr0   rG   r   
get_authorr   attrscodecs
getdecoder)	r9   r   soupauthor_parserrowsrowcls1cls2next_buttons	            r!   search_authorszNavigator.search_authors   s    ~~c"$T*==
3DKK/T; 4#..s3343D6D))49)5Kz1B1BB  !?@!),R39f''(89#>qA~~c*  !78 s   DD
filledc                     | j                  |      }t        |       }|j                  |j                  dd      d   t        j
                        }|r|j                  |      }|S )aF  Search by scholar query and return a single Publication object

        :param url: the url to be searched at
        :type url: str
        :param filled: Whether publication should be filled, defaults to False
        :type filled: bool, optional
        :returns: a publication object
        :rtype: {Publication}
        r   gs_orr   )r   r   get_publicationr   r   PUBLICATION_SEARCH_SNIPPETfill)r9   r   r   r   publication_parserpubs         r!   search_publicationzNavigator.search_publication  sa     ~~c".t4 00ug1Nq1QSdSS  A$))#.C
r"   c                     t        | |      S )zReturns a Publication Generator given a url

        :param url: the url where publications can be found.
        :type url: str
        :returns: An iterator of Publications
        :rtype: {_SearchScholarIterator}
        r   )r9   r   s     r!   search_publicationszNavigator.search_publications   s     &dC00r"   r   sortbypublication_limitc                     t        |       }|j                  |      }|r|j                  |||      }|S |j                  |dg||      }|S )a  Search by author ID and return a Author object
        :param id: the Google Scholar id of a particular author
        :type url: str
        :param filled: If the returned Author object should be filled
        :type filled: bool, optional
        :param sortby: if the object is an author, select the order of the citations in the author page. Either by 'citedby' or 'year'. Defaults to 'citedby'.
        :type sortby: string
        :param publication_limit: Select the max number of publications you want you want to fill for the author. Defaults to no limit.
        :type publication_limit: int
        :returns: an Author object
        :rtype: {Author}
        )r   r   basics)sectionsr   r   )r   r   r   )r9   r   r   r   r   r   r   s          r!   search_author_idzNavigator.search_author_id*  sc     %T*&&r*$$SK\$]C 
  $$SH:f`q$rC
r"   
fromauthorc                    | j                  |      }|j                  dd      }|r| j                  j                  d       g }|D ]J  }|j	                  |j
                  j                  |j
                  d   j                  dd      d   d       L |g k(  r\|du rX	 t        | j                  |            }| j                  |j                        j                  }d|d	<   |j	                  |       |S |S # t        $ r g }Y |S w xY w)
zGenerate instiution object from author search page.
           if no results are found and `fromuthor` is True, then use the first author from the search
           to get institution/organization name.
        h3gsc_inst_reszFound institutionhrefzorg=r   )Organizationr   Tr   )r   r   r0   rG   appendarf   splitnextr   r   r   organizationrn   )	r9   r   r   r   r   r   r   authauthorgs	            r!   search_organizationzNavigator.search_organization?  s   
 ~~c"}}T>2KK01 	^CJJ

#%%-:M:MfVW:XYZ:[\]	^ 2:*,D//45//8EE(,%

7# 
s
  
s   AC5 5DDr   )T)F)Fcitedbyr   )r#   r$   r%   __doc__r-   boolr?   intrB   r   rI   rL   strrp   r|   re   r   r   r   r   r   r   r   r   r   r   r   listr   r&   r'   s   @r!   r)   r)       s6   ;M M
$3 $
0^ 0. 0"=iQS iQ4 iQC iQX( ( (
T 


d 

6 6	S 	] 	#  . +0c #'4E$1s 1/E 13  c jm v| *s   r"   r)   )	metaclass)"
__future__r   r   r   r   _proxy_generatorr   r	   r
   bs4r   r   r.   r]   r_   requests.exceptionsr   httpxr   selenium.webdriver.common.byr   r   r   r   r   r   
data_typesr   r   r   rm   r   objectr)   rK   r"   r!   <module>r      sZ    &  % ' U U      ' " + 6 ' 1 < <# #v) vr"   