@@ -59,6 +59,8 @@ class Proxy:
5959 def __init__ (self , ip : str , port : int , type_ : ProxyType ) -> None :
6060 self .ip : str = ip
6161 self .port : int = port
62+ if isinstance (type_ , str ):
63+ type_ = ProxyType .from_name (type_ )
6264 self .type : ProxyType = type_
6365
6466 def check_status (self , timeout : int = 10 , url : str = 'http://icanhazip.com/' , on_success_callback : _Callable = None ,
@@ -179,9 +181,20 @@ def __dict__(self) -> dict:
179181 'port' : self .port ,
180182 'type' : self .type .name ,
181183 'status' : self .status .name ,
184+ 'scheme' : self .type .name .lower (),
182185 'geolocation_info' : self .geolocation_info
183186 }
184187
188+ def __iter__ (self ):
189+ return iter ((
190+ ('ip' , self .ip ),
191+ ('port' , self .port ),
192+ ('type' , self .type .name ),
193+ ('status' , self .status .name ),
194+ ('scheme' , self .type .name .lower ()),
195+ ('geolocation_info' , self .geolocation_info )
196+ ))
197+
185198
186199class ProxyList (set ):
187200 def __init__ (self , proxies : _Iterable [Proxy ] = None ):
@@ -256,38 +269,50 @@ def check_proxy(proxy_: Proxy):
256269
257270 on_progress_callback (self , 100 )
258271
259- def to_text (self , separator : str = "\n " ) -> str :
272+ def to_text (self , separator : str = "\n " , format_ : str = '{scheme}://{ip}:{port}' ) -> str :
260273 """
261274 This method is used to convert the list to a text string.
275+
276+ :param separator: The separator between proxies.
277+ :param format_: The format of each proxy.
278+ :return: The text string.
262279 """
263- return separator .join (str ( proxy ) for proxy in self )
280+ return separator .join (format_ . format ( ** dict ( proxy ) ) for proxy in self )
264281
265282 def batch_collect_geolocations (self , fields : str = 'status,message,continent,continentCode,country,countryCode,'
266283 'region,regionName,city,zip,lat,lon,timezone,isp,org,as,asname,'
267- 'query' , on_progress_callback : _Callable = None ):
284+ 'query' , on_progress_callback : _Callable = None ,
285+ on_error_callback : _Callable = None ) -> None :
268286 """
269287 This method is used to collect the geolocation of all proxies in the list.
270288
271289 :param fields: The fields to be returned.
272290 :param on_progress_callback: A callback function to be called on each progress.
291+ :param on_error_callback: A callback function to be called on each error.
273292 """
274293 if on_progress_callback is not None :
275294 if not callable (on_progress_callback ):
276- raise TypeError (
277- "ProxyList.batch_collect_geolocations() argument on_progress_callback must be a callable." )
295+ raise TypeError ("ProxyList.batch_collect_geolocations() argument on_progress_callback must be a"
296+ " callable." )
278297 else :
279298 on_progress_callback = lambda proxy_list , progress : None
299+ if on_error_callback is not None :
300+ if not callable (on_error_callback ):
301+ raise TypeError ("ProxyList.batch_collect_geolocations() argument on_error_callback must be a callable." )
302+ else :
303+ on_error_callback = lambda proxy_list , error : None
280304 all_proxies = list (self )
281305 for start_index in range (0 , len (self ), 100 ):
282- end_index = start_index + 100
306+ end_index = start_index + 100 if start_index + 100 < len ( self ) else len ( self )
283307 proxies = all_proxies [start_index :end_index ]
284308 try :
285- response = requests .post (url = f"http://ip-api.com/batch?fields={ fields } " , data = proxies )
309+ response = requests .post (url = f"http://ip-api.com/batch?fields={ fields } " ,
310+ json = [proxy .ip for proxy in proxies ]).json ()
286311 for index , proxy in enumerate (proxies ):
287- proxy .geolocation_info = response .json ()[index ]
312+ proxy .geolocation_info = response [index ]
313+ on_progress_callback (self , end_index / len (self ) * 100 )
288314 except Exception as e :
289- raise Exception ("Failed to collect geolocation information." , e )
290- on_progress_callback (self , (end_index + 1 ) / len (self ) * 100 )
315+ on_error_callback (self , Exception ("Failed to collect geolocation information." , e ))
291316
292317 def to_json (self , indent : int = 4 , include_status : bool = True , include_geolocation : bool = True ) -> str :
293318 """
@@ -315,15 +340,17 @@ def to_json(self, indent: int = 4, include_status: bool = True, include_geolocat
315340
316341 return json .dumps (proxies , indent = indent )
317342
318- def to_text_file (self , filename : _Union [str , os .PathLike ], separator : str = "\n " ) -> None :
343+ def to_text_file (self , filename : _Union [str , os .PathLike ], separator : str = "\n " ,
344+ format_ : str = '{scheme}://{ip}:{port}' ) -> None :
319345 """
320346 This method is used to write the list to a text file.
321347
322348 :param filename: The name of the text file.
323349 :param separator: The separator of the text file.
350+ :param format_: The format of each proxy.
324351 """
325352 with open (filename , 'w' ) as f :
326- f .write (self .to_text (separator ))
353+ f .write (self .to_text (separator , format_ ))
327354
328355 def to_json_file (self , filename : _Union [str , os .PathLike ], indent : int = 4 , include_status : bool = True ,
329356 include_geolocation : bool = True ) -> None :
0 commit comments