|
9 | 9 | import json |
10 | 10 | import os |
11 | 11 | import re |
| 12 | +import sys |
12 | 13 |
|
13 | 14 | from pythainlp import __version__ |
14 | 15 | from pythainlp.corpus import corpus_db_path, corpus_db_url, corpus_path |
15 | 16 | from pythainlp.tools import get_full_data_path |
16 | 17 |
|
17 | 18 | _CHECK_MODE = os.getenv("PYTHAINLP_READ_MODE") |
| 19 | +_USER_AGENT = ( |
| 20 | + f"PyThaiNLP/{__version__} " |
| 21 | + f"(Python/{sys.version_info.major}.{sys.version_info.minor}; " |
| 22 | + f"{sys.platform})" |
| 23 | +) |
| 24 | + |
| 25 | + |
| 26 | +class _ResponseWrapper: |
| 27 | + """Wrapper to provide requests.Response-like interface for urllib response.""" |
| 28 | + |
| 29 | + def __init__(self, response): |
| 30 | + self.status_code = response.status |
| 31 | + self.headers = response.headers |
| 32 | + self._content = response.read() |
| 33 | + |
| 34 | + def json(self): |
| 35 | + """Parse JSON content from response.""" |
| 36 | + try: |
| 37 | + return json.loads(self._content.decode("utf-8")) |
| 38 | + except (json.JSONDecodeError, UnicodeDecodeError) as err: |
| 39 | + raise ValueError(f"Failed to parse JSON response: {err}") |
18 | 40 |
|
19 | 41 |
|
20 | 42 | def get_corpus_db(url: str): |
21 | 43 | """Get corpus catalog from server. |
22 | 44 |
|
23 | 45 | :param str url: URL corpus catalog |
24 | 46 | """ |
25 | | - import requests |
| 47 | + from urllib.error import HTTPError, URLError |
| 48 | + from urllib.request import Request, urlopen |
26 | 49 |
|
27 | 50 | corpus_db = None |
28 | 51 | try: |
29 | | - corpus_db = requests.get(url, timeout=10) |
30 | | - except requests.exceptions.HTTPError as http_err: |
| 52 | + req = Request(url, headers={"User-Agent": _USER_AGENT}) |
| 53 | + with urlopen(req, timeout=10) as response: |
| 54 | + corpus_db = _ResponseWrapper(response) |
| 55 | + except HTTPError as http_err: |
31 | 56 | print(f"HTTP error occurred: {http_err}") |
32 | | - except requests.exceptions.RequestException as err: |
33 | | - print(f"Non-HTTP error occurred: {err}") |
| 57 | + except URLError as err: |
| 58 | + print(f"URL error occurred: {err}") |
| 59 | + except Exception as err: |
| 60 | + print(f"Error occurred: {err}") |
34 | 61 |
|
35 | 62 | return corpus_db |
36 | 63 |
|
@@ -284,30 +311,28 @@ def _download(url: str, dst: str) -> int: |
284 | 311 | """ |
285 | 312 | CHUNK_SIZE = 64 * 1024 # 64 KiB |
286 | 313 |
|
287 | | - from urllib.request import urlopen |
288 | | - |
289 | | - import requests |
| 314 | + from urllib.request import Request, urlopen |
290 | 315 |
|
291 | | - file_size = int(urlopen(url).info().get("Content-Length", -1)) |
292 | | - r = requests.get(url, stream=True, timeout=10) |
293 | | - with open(get_full_data_path(dst), "wb") as f: |
294 | | - pbar = None |
295 | | - try: |
296 | | - from tqdm.auto import tqdm |
297 | | - |
298 | | - pbar = tqdm(total=int(r.headers["Content-Length"])) |
299 | | - except ImportError: |
| 316 | + req = Request(url, headers={"User-Agent": _USER_AGENT}) |
| 317 | + with urlopen(req, timeout=10) as response: |
| 318 | + file_size = int(response.info().get("Content-Length", -1)) |
| 319 | + with open(get_full_data_path(dst), "wb") as f: |
300 | 320 | pbar = None |
| 321 | + try: |
| 322 | + from tqdm.auto import tqdm |
| 323 | + |
| 324 | + pbar = tqdm(total=file_size) |
| 325 | + except ImportError: |
| 326 | + pbar = None |
301 | 327 |
|
302 | | - for chunk in r.iter_content(chunk_size=CHUNK_SIZE): |
303 | | - if chunk: |
| 328 | + while chunk := response.read(CHUNK_SIZE): |
304 | 329 | f.write(chunk) |
305 | 330 | if pbar: |
306 | 331 | pbar.update(len(chunk)) |
307 | | - if pbar: |
308 | | - pbar.close() |
309 | | - else: |
310 | | - print("Done.") |
| 332 | + if pbar: |
| 333 | + pbar.close() |
| 334 | + else: |
| 335 | + print("Done.") |
311 | 336 | return file_size |
312 | 337 |
|
313 | 338 |
|
|
0 commit comments