11import requests ,time
2+ from datetime import datetime
23from newsdataapi import constants
34from typing import Optional ,Union
45from urllib .parse import urlencode , quote
@@ -8,7 +9,7 @@ class NewsDataApiClient:
89
910 def __init__ (
1011 self , apikey :str , session :bool = False , max_retries :int = constants .DEFAULT_MAX_RETRIES , retry_delay :int = constants .DEFAULT_RETRY_DELAY ,
11- proxies :Optional [dict ]= None , request_timeout :int = constants .DEFAULT_REQUEST_TIMEOUT ,max_result :int = 10 ** 10
12+ proxies :Optional [dict ]= None , request_timeout :int = constants .DEFAULT_REQUEST_TIMEOUT ,max_result :int = 10 ** 10 , debug : Optional [ bool ] = False
1213 ):
1314 """Initializes newsdata client object for access Newsdata APIs."""
1415 self .apikey = apikey
@@ -19,6 +20,7 @@ def __init__(
1920 self .proxies = proxies
2021 self .request_timeout = request_timeout
2122 self .recursive_retry = max_retries
23+ self .is_debug = debug
2224
2325 def set_retries ( self , max_retries :int , retry_delay :int )-> None :
2426 """ API maximum retry and delay"""
@@ -36,7 +38,7 @@ def api_proxies( self, proxies:dict)->None:
3638 def __validate_parms (self ,param :str ,value :Union [list ,int ,str ,bool ])-> dict :
3739 bool_params = {'full_content' ,'image' ,'video' }
3840 int_params = {'size' ,'prioritydomain' ,'timeframe' }
39- string_params = {'q' ,'qInTitle' ,'country' ,'category' ,'language' ,'domain' ,'domainurl' ,'excludedomain' ,'timezone' ,'page' ,'from_date' ,'to_date' ,'apikey' }
41+ string_params = {'q' ,'qInTitle' ,'country' ,'category' ,'language' ,'domain' ,'domainurl' ,'excludedomain' ,'timezone' ,'page' ,'from_date' ,'to_date' ,'apikey' , 'qInMeta' }
4042
4143 if param in string_params :
4244 if isinstance (value ,list ):
@@ -58,18 +60,35 @@ def __get_feeds(self,url:str)-> dict:
5860 if self .recursive_retry <= 0 :
5961 raise NewsdataException ('maximum retry limit reached.' )
6062 response = self .request_method .get (url = url ,proxies = self .proxies ,timeout = self .request_timeout )
63+ if self .is_debug == True :
64+ headers = response .headers
65+ print (f'Debug | { datetime .utcnow ().replace (microsecond = 0 )} | x_rate_limit_remaining: { headers .get ("x_rate_limit_remaining" )} | x_api_limit_remaining: { headers .get ("x_api_limit_remaining" )} ' )
6166 feeds_data :dict = response .json ()
6267 if response .status_code != 200 :
63- if response .status_code == 500 or feeds_data .get ('results' ,{}).get ('code' ) == 'TooManyRequests' or feeds_data .get ('results' ,{}).get ('code' ) == 'RateLimitExceeded' :
68+ if response .status_code == 500 :
69+ if self .is_debug == True :
70+ print (f"Debug | { datetime .utcnow ().replace (microsecond = 0 )} | Encountered 'ServerError' going to sleep for: { self .retry_delay } seconds." )
6471 time .sleep (self .retry_delay )
6572 self .recursive_retry -= 1
6673 return self .__get_feeds (url = url )
67- raise NewsdataException (response .json ())
74+ elif feeds_data .get ('results' ,{}).get ('code' ) == 'TooManyRequests' :
75+ if self .is_debug == True :
76+ print (f"Debug | { datetime .utcnow ().replace (microsecond = 0 )} | Encountered 'TooManyRequests' going to sleep for: { constants .DEFAULT_RETRY_DELAY_TooManyRequests } seconds." )
77+ time .sleep (constants .DEFAULT_RETRY_DELAY_TooManyRequests )
78+ self .recursive_retry -= 1
79+ return self .__get_feeds (url = url )
80+ elif feeds_data .get ('results' ,{}).get ('code' ) == 'RateLimitExceeded' :
81+ if self .is_debug == True :
82+ print (f"Debug | { datetime .utcnow ().replace (microsecond = 0 )} | Encountered 'RateLimitExceeded' going to sleep for: { constants .DEFAULT_RETRY_DELAY_RateLimitExceeded } seconds." )
83+ time .sleep (constants .DEFAULT_RETRY_DELAY_RateLimitExceeded )
84+ self .recursive_retry -= 1
85+ return self .__get_feeds (url = url )
86+ else :
87+ raise NewsdataException (response .json ())
6888 else :
6989 self .recursive_retry = self .max_retries
7090 return feeds_data
7191 except requests .exceptions .ConnectionError :
72- time .sleep (self .retry_delay )
7392 if isinstance (self .request_method ,requests .Session ):
7493 self .request_method = requests .Session ()
7594 self .recursive_retry -= 1
@@ -88,12 +107,11 @@ def __get_feeds_all(self,url:str)-> dict:
88107 response = self .__get_feeds (url = f'{ url } &page={ data .get ("nextPage" )} ' if data .get ('results' ) else url )
89108 data ['totalResults' ] = response .get ('totalResults' )
90109 results = response .get ('results' )
91- for feed in results :
92- data ['results' ].append (feed )
93- feeds_count += 1
94- if feeds_count >= self .max_result :
95- return data
110+ data ['results' ].extend (results )
96111 data ['nextPage' ] = response .get ('nextPage' )
112+ feeds_count += len (results )
113+ if feeds_count >= self .max_result :
114+ return data
97115 time .sleep (0.5 )
98116 return data
99117
@@ -102,7 +120,7 @@ def news_api(
102120 language :Optional [Union [str , list ]]= None , domain :Optional [Union [str , list ]]= None , timeframe :Optional [int ]= None , size :Optional [int ]= None ,
103121 domainurl :Optional [Union [str , list ]]= None , excludedomain :Optional [Union [str , list ]]= None , timezone :Optional [str ]= None , full_content :Optional [bool ]= None ,
104122 image :Optional [bool ]= None , video :Optional [bool ]= None , prioritydomain :Optional [int ]= None , page :Optional [str ]= None , scroll :Optional [bool ]= False ,
105- max_result :Optional [int ]= None
123+ max_result :Optional [int ]= None , qInMeta : Optional [ str ] = None
106124 )-> dict :
107125 """
108126 Sending GET request to the news api.
@@ -111,7 +129,7 @@ def news_api(
111129 params = {
112130 'apikey' :self .apikey ,'q' :q ,'qInTitle' :qInTitle ,'country' :country ,'category' :category ,'language' :language ,'domain' :domain ,'timeframe' :timeframe ,'size' :size ,
113131 'domainurl' :domainurl ,'excludedomain' :excludedomain ,'timezone' :timezone ,'full_content' :full_content ,'image' :image ,'video' :video ,'prioritydomain' :prioritydomain ,
114- 'page' :page ,
132+ 'page' :page ,'qInMeta' : qInMeta
115133 }
116134
117135 URL_parameters = {}
@@ -132,7 +150,7 @@ def archive_api(
132150 language :Optional [Union [str , list ]]= None , domain :Optional [Union [str , list ]]= None , size :Optional [int ]= None ,domainurl :Optional [Union [str , list ]]= None ,
133151 excludedomain :Optional [Union [str , list ]]= None , timezone :Optional [str ]= None , full_content :Optional [bool ]= None ,image :Optional [bool ]= None ,
134152 video :Optional [bool ]= None ,prioritydomain :Optional [int ]= None , page :Optional [str ]= None , scroll :Optional [bool ]= False , max_result :Optional [int ]= None ,
135- from_date :Optional [str ]= None , to_date :Optional [str ]= None
153+ from_date :Optional [str ]= None , to_date :Optional [str ]= None , qInMeta : Optional [ str ] = None
136154 ) -> dict :
137155 """
138156 Sending GET request to the archive api
@@ -141,7 +159,7 @@ def archive_api(
141159 params = {
142160 'q' :q ,'qInTitle' :qInTitle ,'country' :country ,'category' :category ,'language' :language ,'domain' :domain ,'size' :size ,'domainurl' :domainurl ,'excludedomain' :excludedomain ,
143161 'timezone' :timezone ,'full_content' :full_content ,'image' :image ,'video' :video ,'prioritydomain' :prioritydomain ,'page' :page ,'from_date' :from_date ,'to_date' :to_date ,
144- 'apikey' :self .apikey
162+ 'apikey' :self .apikey , 'qInMeta' : qInMeta
145163 }
146164 URL_parameters = {}
147165 for key ,value in params .items ():
@@ -177,7 +195,7 @@ def crypto_api(
177195 language :Optional [Union [str , list ]]= None , domain :Optional [Union [str , list ]]= None , timeframe :Optional [int ]= None , size :Optional [int ]= None ,
178196 domainurl :Optional [Union [str , list ]]= None , excludedomain :Optional [Union [str , list ]]= None , timezone :Optional [str ]= None , full_content :Optional [bool ]= None ,
179197 image :Optional [bool ]= None , video :Optional [bool ]= None , prioritydomain :Optional [int ]= None , page :Optional [str ]= None , scroll :Optional [bool ]= False ,
180- max_result :Optional [int ]= None
198+ max_result :Optional [int ]= None , qInMeta : Optional [ str ] = None
181199 )-> dict :
182200 """
183201 Sending GET request to the crypto api
@@ -186,7 +204,8 @@ def crypto_api(
186204
187205 params = {
188206 'apikey' :self .apikey ,'q' :q ,'qInTitle' :qInTitle ,'country' :country ,'category' :category ,'language' :language ,'domain' :domain ,'size' :size ,'domainurl' :domainurl ,
189- 'excludedomain' :excludedomain ,'timezone' :timezone ,'full_content' :full_content ,'image' :image ,'video' :video ,'prioritydomain' :prioritydomain ,'page' :page ,'timeframe' :timeframe
207+ 'excludedomain' :excludedomain ,'timezone' :timezone ,'full_content' :full_content ,'image' :image ,'video' :video ,'prioritydomain' :prioritydomain ,'page' :page ,
208+ 'timeframe' :timeframe ,'qInMeta' :qInMeta
190209 }
191210
192211 URL_parameters = {}
0 commit comments