44import os
55import copy
66import pprint
7- from typing import Callable
7+ from typing import Callable , List
88from ._navigator import Navigator
99from ._proxy_generator import ProxyGenerator
1010from dotenv import find_dotenv , load_dotenv
1414
1515_AUTHSEARCH = '/citations?hl=en&view_op=search_authors&mauthors={0}'
1616_KEYWORDSEARCH = '/citations?hl=en&view_op=search_authors&mauthors=label:{0}'
17+ _KEYWORDSEARCHBASE = '/citations?hl=en&view_op=search_authors&mauthors={}'
1718_PUBSEARCH = '/scholar?hl=en&q={0}'
1819
1920
@@ -181,7 +182,7 @@ def search_author(self, name: str):
181182 url = _AUTHSEARCH .format (requests .utils .quote (name ))
182183 return self .__nav .search_authors (url )
183184
184- def fill (self , object : dict , sections = []) -> Author or Publication :
185+ def fill (self , object : dict , sections = [], sortby : str = "citedby" , publication_limit : int = 0 ) -> Author or Publication :
185186 """Fills the object according to its type.
186187 If the container type is Author it will fill the additional author fields
187188 If it is Publication it will fill it accordingly.
@@ -190,11 +191,15 @@ def fill(self, object: dict, sections=[]) -> Author or Publication:
190191 :type object: Author or Publication
191192 :param sections: the sections that the user wants filled for an Author object. This can be: ['basics', 'indices', 'counts', 'coauthors', 'publications']
192193 :type sections: list
194+ :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'.
195+ :type sortby: string
196+ :param publication_limit: if the object is an author, select the max number of publications you want you want to fill for the author. Defaults to no limit.
197+ :type publication_limit: int
193198 """
194199
195200 if object ['container_type' ] == "Author" :
196201 author_parser = AuthorParser (self .__nav )
197- object = author_parser .fill (object , sections )
202+ object = author_parser .fill (object , sections , sortby , publication_limit )
198203 if object is False :
199204 raise ValueError ("Incorrect input" )
200205 elif object ['container_type' ] == "Publication" :
@@ -231,8 +236,12 @@ def citedby(self, object: Publication)->_SearchScholarIterator:
231236 return
232237
233238
234- def search_author_id (self , id : str , filled : bool = False )-> Author :
239+ def search_author_id (self , id : str , filled : bool = False , sortby : str = "citedby" , publication_limit : int = 0 )-> Author :
235240 """Search by author id and return a single Author object
241+ :param sortby: select the order of the citations in the author page. Either by 'citedby' or 'year'. Defaults to 'citedby'.
242+ :type sortby: string
243+ :param publication_limit: if the object is an author, select the max number of publications you want you want to fill for the author. Defaults to no limit.
244+ :type publication_limit: int
236245
237246 :Example::
238247
@@ -252,7 +261,7 @@ def search_author_id(self, id: str, filled: bool = False)->Author:
252261 'scholar_id': 'EmD_lTEAAAAJ',
253262 'source': 'AUTHOR_PROFILE_PAGE'}
254263 """
255- return self .__nav .search_author_id (id , filled )
264+ return self .__nav .search_author_id (id , filled , sortby , publication_limit )
256265
257266 def search_keyword (self , keyword : str ):
258267 """Search by keyword and return a generator of Author objects
@@ -287,6 +296,45 @@ def search_keyword(self, keyword: str):
287296 url = _KEYWORDSEARCH .format (requests .utils .quote (keyword ))
288297 return self .__nav .search_authors (url )
289298
299+ def search_keywords (self , keywords : List [str ]):
300+ """Search by keywords and return a generator of Author objects
301+
302+ :param keywords: a list of keywords to be searched
303+ :type keyword: List[str]
304+
305+ :Example::
306+
307+ .. testcode::
308+
309+ search_query = scholarly.search_keywords(['crowdsourcing', 'privacy'])
310+ scholarly.pprint(next(search_query))
311+
312+ :Output::
313+
314+ .. testoutput::
315+ {'affiliation': 'Cornell University',
316+ 'citedby': 40976,
317+ 'email_domain': '',
318+ 'filled': False,
319+ 'interests': ['Crowdsourcing',
320+ 'privacy',
321+ 'social computing',
322+ 'game theory',
323+ 'user-generated content'],
324+ 'name': 'Arpita Ghosh',
325+ 'scholar_id': '_cMw1IUAAAAJ',
326+ 'source': 'SEARCH_AUTHOR_SNIPPETS',
327+ 'url_picture': 'https://scholar.google.com/citations?view_op=medium_photo&user=_cMw1IUAAAAJ'}
328+
329+ """
330+
331+ formated_keywords = ['label:' + requests .utils .quote (keyword ) for keyword in keywords ]
332+ formated_keywords = '+' .join (formated_keywords )
333+ url = _KEYWORDSEARCHBASE .format (formated_keywords )
334+ return self .__nav .search_authors (url )
335+
336+
337+
290338 def search_pubs_custom_url (self , url : str )-> _SearchScholarIterator :
291339 """Search by custom URL and return a generator of Publication objects
292340 URL should be of the form '/scholar?q=...'
@@ -304,7 +352,25 @@ def search_author_custom_url(self, url: str)->Author:
304352 :type url: string
305353 """
306354 return self .__nav .search_authors (url )
307-
355+
356+ def get_related_articles (self , object : Publication )-> _SearchScholarIterator :
357+ """
358+ Search google scholar for related articles to a specific publication.
359+
360+ :param object: Publication object used to get the related articles
361+ :type object: Publication
362+ """
363+ if object ['container_type' ] != 'Publication' :
364+ print ("Not a publication object" )
365+ return
366+
367+ if object ['source' ] == PublicationSource .AUTHOR_PUBLICATION_ENTRY :
368+ if 'url_related_articles' not in object .keys ():
369+ object = self .fill (object )
370+ return self .__nav .search_publications (object ['url_related_articles' ])
371+ elif object ['source' ] == PublicationSource .PUBLICATION_SEARCH_SNIPPET :
372+ return self .__nav .search_publications (object ['url_related_articles' ])
373+
308374 def pprint (self , object : Author or Publication )-> None :
309375 """Pretty print an Author or Publication container object
310376
0 commit comments