Przeglądaj źródła

feat: 添加日志记录

SongZihuan 3 lat temu
rodzic
commit
71a6bc5c5d

+ 21 - 8
db.py

@@ -1,15 +1,20 @@
 import sqlite3
 from typing import Optional, Union, List, Tuple, Dict
 import traceback
-
+import logging
 import pandas
 import word
 import re
+import os
 
 
 class DataBase:
-    def __init__(self, name):
-        self._db_name = f"{name}.db"
+    __logger = logging.getLogger("database")
+    __logger.propagate = False
+
+    def __init__(self, name, path: str = ""):
+        self._db_name = os.path.join(path, f"{name}.db")
+        self.__logger.info(f"Mark {self._db_name}")
 
     def search(self, columns: List[str], table: str,
                where: Union[str, List[str]] = None,
@@ -92,8 +97,7 @@ class DataBase:
             cur.execute(sql)
             ret = cur.fetchall()
         except sqlite3.Error:
-            traceback.print_exc()
-            print(f"sql='{sql}'")
+            self.__logger.error(f"Sqlite({self._db_name}) SQL {sql} error", exc_info=True)
             return None
         return ret
 
@@ -104,8 +108,7 @@ class DataBase:
             cur.execute(sql)
         except sqlite3.Error:
             sqlite.rollback()
-            print(f"sql={sql}")
-            traceback.print_exc()
+            self.__logger.error(f"Sqlite({self._db_name}) SQL {sql} error", exc_info=True)
             return None
         finally:
             if not not_commit:
@@ -115,6 +118,7 @@ class DataBase:
 
 class WordDatabase(DataBase):
     word_pattern = re.compile("([a-zA-Z\']+)")  # 匹配英语单词
+    __logger = logging.getLogger("database.dict")
 
     def __init__(self, dict_name: str = "global"):
         super(WordDatabase, self).__init__(dict_name + "-dict")
@@ -154,6 +158,7 @@ class WordDatabase(DataBase):
                 self.insert(table='Word',
                             columns=['word', 'part', 'english', 'chinese', 'eg'],
                             values=f"'{name_lower}', '{part}', '{english}', '{chinese}', '{eg} '")
+                self.__logger.info(f"Add word name: {name_lower} part: {part}")
         return ret
 
     @staticmethod
@@ -174,6 +179,7 @@ class WordDatabase(DataBase):
             res = []
         if len(res) <= 0:
             return self.__add_word(q)
+        self.__logger.debug(f"Find word (not add) {q}")
         return self.__make_word(q, res)
 
     class UpdateResponse:
@@ -198,12 +204,14 @@ class WordDatabase(DataBase):
         for w in word_list:
             try:
                 if self.find_word(w) is None:
+                    self.__logger.debug(f"update word {w} fail")
                     response.add_error(w)
                 else:
+                    self.__logger.debug(f"update word {w} success")
                     response.add_success()
             except Exception as e:
                 response.add_error(w)
-                traceback.print_exc()
+                self.__logger.debug(f"update word {w} fail", exc_info=True)
         return True, response
 
     @staticmethod
@@ -248,6 +256,7 @@ class WordDatabase(DataBase):
                             "English": str(i[3]),
                             "Chinese": str(i[4]),
                             "Eg": eg_str}, ignore_index=True)
+            self.__logger.debug(f"export word {i[1]}")
         return df
 
     def delete_txt(self, line: str):
@@ -256,9 +265,13 @@ class WordDatabase(DataBase):
         for w in word_list:
             cur = self.delete(table="Word", where=f"LOWER(word)='{w.lower()}'")
             if cur[1].rowcount != -1:
+                self.__logger.debug(f"delete word {w} success")
                 count += 1
+            else:
+                self.__logger.debug(f"delete word {w} fail")
         return count
 
     def delete_all(self):
+        self.__logger.debug(f"delete all word")
         cur = self.delete(table="Word")
         return cur[1].rowcount

BIN
noto/NotoSansSC-Black.otf


BIN
noto/NotoSansSC-Bold.otf


BIN
noto/NotoSansSC-Light.otf


BIN
noto/NotoSansSC-Medium.otf


BIN
noto/NotoSansSC-Regular.otf


BIN
noto/NotoSansSC-Thin.otf


+ 0 - 93
noto/OFL.txt

@@ -1,93 +0,0 @@
-Copyright 2012 Google Inc. All Rights Reserved.
-
-This Font Software is licensed under the SIL Open Font License, Version 1.1.
-This license is copied below, and is also available with a FAQ at:
-http://scripts.sil.org/OFL
-
-
------------------------------------------------------------
-SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
------------------------------------------------------------
-
-PREAMBLE
-The goals of the Open Font License (OFL) are to stimulate worldwide
-development of collaborative font projects, to support the font creation
-efforts of academic and linguistic communities, and to provide a free and
-open framework in which fonts may be shared and improved in partnership
-with others.
-
-The OFL allows the licensed fonts to be used, studied, modified and
-redistributed freely as long as they are not sold by themselves. The
-fonts, including any derivative works, can be bundled, embedded, 
-redistributed and/or sold with any software provided that any reserved
-names are not used by derivative works. The fonts and derivatives,
-however, cannot be released under any other type of license. The
-requirement for fonts to remain under this license does not apply
-to any document created using the fonts or their derivatives.
-
-DEFINITIONS
-"Font Software" refers to the set of files released by the Copyright
-Holder(s) under this license and clearly marked as such. This may
-include source files, build scripts and documentation.
-
-"Reserved Font Name" refers to any names specified as such after the
-copyright statement(s).
-
-"Original Version" refers to the collection of Font Software components as
-distributed by the Copyright Holder(s).
-
-"Modified Version" refers to any derivative made by adding to, deleting,
-or substituting -- in part or in whole -- any of the components of the
-Original Version, by changing formats or by porting the Font Software to a
-new environment.
-
-"Author" refers to any designer, engineer, programmer, technical
-writer or other person who contributed to the Font Software.
-
-PERMISSION & CONDITIONS
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of the Font Software, to use, study, copy, merge, embed, modify,
-redistribute, and sell modified and unmodified copies of the Font
-Software, subject to the following conditions:
-
-1) Neither the Font Software nor any of its individual components,
-in Original or Modified Versions, may be sold by itself.
-
-2) Original or Modified Versions of the Font Software may be bundled,
-redistributed and/or sold with any software, provided that each copy
-contains the above copyright notice and this license. These can be
-included either as stand-alone text files, human-readable headers or
-in the appropriate machine-readable metadata fields within text or
-binary files as long as those fields can be easily viewed by the user.
-
-3) No Modified Version of the Font Software may use the Reserved Font
-Name(s) unless explicit written permission is granted by the corresponding
-Copyright Holder. This restriction only applies to the primary font name as
-presented to the users.
-
-4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
-Software shall not be used to promote, endorse or advertise any
-Modified Version, except to acknowledge the contribution(s) of the
-Copyright Holder(s) and the Author(s) or with their explicit written
-permission.
-
-5) The Font Software, modified or unmodified, in part or in whole,
-must be distributed entirely under this license, and must not be
-distributed under any other license. The requirement for fonts to
-remain under this license does not apply to any document created
-using the Font Software.
-
-TERMINATION
-This license becomes null and void if any of the above conditions are
-not met.
-
-DISCLAIMER
-THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
-OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
-COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
-DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
-OTHER DEALINGS IN THE FONT SOFTWARE.

+ 13 - 0
word.py

@@ -5,6 +5,7 @@
 使用bs4解析网页
 """
 
+import logging
 import requests
 from bs4 import BeautifulSoup
 from typing import Optional, Dict
@@ -13,6 +14,8 @@ from typing import Optional, Dict
 class WordDict:
     __data_set_search = "english-chinese-simplified"
     __url = f"https://dictionary.cambridge.org/zhs/%E6%90%9C%E7%B4%A2/direct/?datasetsearch={__data_set_search}"
+    __logger = logging.getLogger("dict")
+    __logger.propagate = False
 
     def __init__(self, user_agent: Optional[str] = None, proxies: Optional[dict] = None):
         if user_agent is None:
@@ -36,26 +39,33 @@ class WordDict:
                                 params={"q": q},
                                 headers=self.headers,
                                 proxies=self.proxies)
+        self.__logger.info(f"Get requests params: {q} url: {response.url} status: {response.status_code}")
         return Response(response)
 
 
 class Response:
+    __logger = logging.getLogger("dict.response")
+    __logger.propagate = False
+
     def __init__(self, response: requests.Response):
         self._res = response
         self._soup = None
         if self._res.status_code != 200:
+            self.__logger.debug(f"Response bad status : {self._res.status_code}")
             return
 
         self._soup = BeautifulSoup(self._res.text, "html.parser")
         self.di_body = self._soup.find(name="div", attrs={"class": "di-body"})
         if self.di_body is None:
             self._soup = None
+            self.__logger.debug(f"Response bad syntax url: {self._res.url}")
             return
 
         self.entry = [(i, 1) for i in self.di_body.findAll(name="div", attrs={"class": "pr entry-body__el"})]
         self.entry += [(i, 2) for i in self.di_body.findAll(name="div", attrs={"class": "pv-block"})]
         if len(self.entry) == 0:
             self._soup = None
+            self.__logger.debug(f"Response bad syntax url: {self._res.url}")
             return
 
         self.res: Dict[str: Word] = {}
@@ -109,6 +119,7 @@ class Response:
             word.add_comment(comment)
         if len(self.res) == 0:
             self._soup = None
+            self.__logger.debug(f"Response bad word: {self._res.url}")
 
     @property
     def is_find(self):
@@ -116,6 +127,8 @@ class Response:
 
 
 class Word:
+    __logger.propagate = False
+
     class Comment:
         def __init__(self, part: str, english: str, chinese: str):
             self.part = part   # 词性