1
- import time
2
1
import logging
3
- from typing import Union
4
2
from dataclasses import dataclass
5
- from urllib .parse import urlencode , quote_plus
3
+ from urllib .parse import quote_plus
6
4
7
5
import requests
6
+ from fake_useragent import UserAgent
8
7
8
+ from rosreestr_api .clients .http import RosreestrHTTPClient
9
9
10
10
logger = logging .getLogger (__name__ )
11
11
12
12
13
- def _strip_cadastral_id (cadastral_id ):
14
- stripped_cadastral_id = []
15
- cadastral_id = cadastral_id .split (':' )
16
- for part in cadastral_id :
17
- if part :
18
- stripped_cadastral_id .append (part [:- 1 ].lstrip ('0' ) + part [- 1 ])
19
- return ':' .join (stripped_cadastral_id )
20
-
21
-
22
- def _get_body_for_logging (body : Union [bytes , str ]) -> str :
23
- try :
24
- if isinstance (body , bytes ):
25
- return (b' BODY: ' + body ).decode ('utf-8' )
26
- elif isinstance (body , str ):
27
- return ' BODY: ' + body
28
- else :
29
- return ''
30
- except UnicodeDecodeError :
31
- return ''
32
-
33
-
34
- def _get_duration_for_logging (duration : str ) -> str :
35
- if duration is not None :
36
- return ' {0:.6f}s' .format (duration )
37
- else :
38
- return ''
39
-
40
-
41
- class HTTPClient :
42
-
43
- GET_HTTP_METHOD = 'GET'
44
- POST_HTTP_METHOD = 'POST'
45
- PATCH_HTTP_METHOD = 'PATCH'
46
- PUT_HTTP_METHOD = 'PUT'
47
-
48
- BODY_LESS_METHODS = [GET_HTTP_METHOD ]
49
- LOG_REQUEST_TEMPLATE = '%(method)s %(url)s%(request_body)s%(duration)s'
50
- LOG_RESPONSE_TEMPLATE = (LOG_REQUEST_TEMPLATE +
51
- ' - HTTP %(status_code)s%(response_body)s%(duration)s' )
52
-
53
- def __init__ (self , timeout = 3 , keep_alive = False , default_headers = None ):
54
- self .timeout = timeout
55
- self .keep_alive = keep_alive
56
- self .default_headers = default_headers or {}
57
- self ._session = None
58
-
59
- def _log_request (self , method , url , body , duration = None , log_method = logger .info ):
60
- message_params = {
61
- 'method' : method , 'url' : url , 'request_body' : _get_body_for_logging (body ),
62
- 'duration' : _get_duration_for_logging (duration )}
63
- log_method (self .LOG_REQUEST_TEMPLATE , message_params )
64
-
65
- def _log_response (self , response , duration , log_method = logger .info ):
66
- message_params = {
67
- 'method' : response .request .method ,
68
- 'url' : response .request .url ,
69
- 'request_body' : _get_body_for_logging (response .request .body ),
70
- 'status_code' : response .status_code ,
71
- 'response_body' : _get_body_for_logging (response .content ),
72
- 'duration' : _get_duration_for_logging (duration )}
73
- log_method (self .LOG_RESPONSE_TEMPLATE , message_params )
74
-
75
- def _make_request (self , method , url , ** kwargs ) -> requests .Response :
76
- kwargs .setdefault ('timeout' , self .timeout )
77
- session = self .session
78
- timeout = kwargs .pop ('timeout' , self .timeout )
79
-
80
- headers = self .default_headers .copy ()
81
- headers .update (kwargs .pop ('headers' , {}))
82
-
83
- request = requests .Request (method , url , headers = headers , ** kwargs )
84
- prepared_request = request .prepare ()
85
- self ._log_request (method , url , prepared_request .body )
86
- start_time = time .time ()
87
- try :
88
- response = session .send (prepared_request , timeout = timeout )
89
- duration = time .time () - start_time
90
- if response .status_code >= 400 :
91
- log_method = logging .error
92
- else :
93
- log_method = logging .debug
94
-
95
- self ._log_response (response , duration = duration , log_method = log_method )
96
- return response
97
- except requests .exceptions .RequestException as e :
98
- duration = time .time () - start_time
99
- if e .response :
100
- self ._log_response (e .response , duration = duration , log_method = logging .error )
101
- else :
102
- self ._log_request (method , url , prepared_request .body , log_method = logging .exception )
103
- raise
104
- finally :
105
- if not self .keep_alive :
106
- session .close ()
107
-
108
- @property
109
- def session (self ) -> requests .Session :
110
- if self .keep_alive :
111
- if not self ._session :
112
- self ._session = requests .Session ()
113
- return self ._session
114
- else :
115
- return requests .Session ()
116
-
117
- def get (self , url , params = None , ** kwargs ) -> requests .Response :
118
- if params :
119
- url_with_query_params = url + '?' + urlencode (params )
120
- else :
121
- url_with_query_params = url
122
-
123
- return self ._make_request (self .GET_HTTP_METHOD , url_with_query_params , ** kwargs )
124
-
125
- def post (self , url , ** kwargs ) -> requests .Response :
126
- return self ._make_request (self .POST_HTTP_METHOD , url , ** kwargs )
127
-
128
- def patch (self , url , ** kwargs ) -> requests .Response :
129
- return self ._make_request (self .PATCH_HTTP_METHOD , url , ** kwargs )
130
-
131
- def put (self , url , ** kwargs ) -> requests .Response :
132
- return self ._make_request (self .PUT_HTTP_METHOD , url , ** kwargs )
133
-
134
-
135
13
@dataclass
136
14
class AddressWrapper :
137
15
@@ -156,7 +34,7 @@ def __post_init__(self):
156
34
157
35
class RosreestrAPIClient :
158
36
159
- BASE_URL = 'http ://rosreestr.ru/api/online'
37
+ BASE_URL = 'https ://rosreestr.gov .ru/api/online'
160
38
MACRO_REGIONS_URL = f'{ BASE_URL } /macro_regions/'
161
39
REGIONS_URL = f'{ BASE_URL } /regions/' + '{}/'
162
40
REGION_TYPES_URL = f'{ BASE_URL } /region_types/' + '{}/'
@@ -171,7 +49,11 @@ class RosreestrAPIClient:
171
49
REPUBLIC = 'республика'
172
50
173
51
def __init__ (self , timeout = 5 , keep_alive = False ):
174
- self ._http_client = HTTPClient (timeout = timeout , keep_alive = keep_alive )
52
+ self ._http_client = RosreestrHTTPClient (
53
+ timeout = timeout ,
54
+ keep_alive = keep_alive ,
55
+ default_headers = {'User-Agent' : UserAgent ().random }
56
+ )
175
57
self ._macro_regions = None
176
58
self ._macro_regions_to_regions = None
177
59
@@ -296,7 +178,11 @@ class PKKRosreestrAPIClient:
296
178
SEARCH_PARCEL_BY_CADASTRAL_ID_URL = SEARCH_OBJECT_BY_CADASTRAL_ID .format (object_type = 1 )
297
179
298
180
def __init__ (self , timeout = 5 , keep_alive = False ):
299
- self ._http_client = HTTPClient (timeout = timeout , keep_alive = keep_alive )
181
+ self ._http_client = RosreestrHTTPClient (
182
+ timeout = timeout ,
183
+ keep_alive = keep_alive ,
184
+ default_headers = {'User-Agent' : UserAgent ().random }
185
+ )
300
186
301
187
def get_parcel_by_coordinates (self , * , lat , long , limit = 11 , tolerance = 2 ) -> dict :
302
188
url = self .SEARCH_PARCEL_BY_COORDINATES_URL .format (
@@ -317,3 +203,12 @@ def get_building_by_coordinates(self, *, lat, long, limit=11, tolerance=2) -> di
317
203
url = self .SEARCH_BUILDING_BY_COORDINATES_URL .format (
318
204
lat = lat , long = long , limit = limit , tolerance = tolerance )
319
205
return self ._http_client .get (url ).json ()
206
+
207
+
208
+ def _strip_cadastral_id (cadastral_id ):
209
+ stripped_cadastral_id = []
210
+ cadastral_id = cadastral_id .split (':' )
211
+ for part in cadastral_id :
212
+ if part :
213
+ stripped_cadastral_id .append (part [:- 1 ].lstrip ('0' ) + part [- 1 ])
214
+ return ':' .join (stripped_cadastral_id )
0 commit comments