Skip to content

Commit 9674bef

Browse files
committed
fix: 修复多个问题
- 支持仅年份格式的出版日期解析 (YYYY) - 修复多个著者的分割逻辑,使用换行符而非 & 符号 - 将静态常量改为 CONFIG 字典,实现动态配置加载
1 parent 4744cc5 commit 9674bef

1 file changed

Lines changed: 72 additions & 52 deletions

File tree

src/__init__.py

Lines changed: 72 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -34,17 +34,20 @@
3434
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0'
3535
}
3636

37-
MAX_WORKERS = 2
38-
MAX_TITLE_LIST_NUM = 6
39-
SPIDER_BASE_SLEEP_TIME = 200
40-
IS_STRIP_TITLE = True
41-
IS_STRIP_AUTHOR = True
42-
IS_NCLHASH = True
43-
IS_PURSETAG = False
44-
IS_FUZZY_SEARCH_WITH_AUTHOR = True
45-
ADD_CLC_TO_TAGS = True
46-
CONVERT_CLC_TO_TAG = True
47-
CLC_PARSE_LEVEL = 2
37+
# 配置字典:存储所有可配置项的默认值
38+
CONFIG = {
39+
'max_workers': 2,
40+
'max_title_list_num': 6,
41+
'spider_base_sleep_time': 200,
42+
'is_strip_title': True,
43+
'is_strip_author': True,
44+
'is_nlchash': True,
45+
'is_pursetag': False,
46+
'is_fuzzy_search_with_author': True,
47+
'add_clc_to_tags': True,
48+
'convert_clc_to_tag': True,
49+
'clc_parse_level': 2,
50+
}
4851

4952
def spider_sleep():
5053
"""
@@ -53,7 +56,7 @@ def spider_sleep():
5356
函数通过模拟掷8个120面的骰子并求和,加上一个随机数和基础睡眠时间,来确定睡眠时间,并使当前线程进入睡眠状态。
5457
"""
5558
sleep_time = sum(randint(1, 120) for _ in range(8)) # 掷3个8到120面的骰子并求和
56-
sleep_time = sleep_time + randint(30, 600) + SPIDER_BASE_SLEEP_TIME
59+
sleep_time = sleep_time + randint(30, 600) + CONFIG['spider_base_sleep_time']
5760
time.sleep(sleep_time / 1000)
5861

5962

@@ -93,43 +96,53 @@ def get_dynamic_url(log):
9396
else:
9497
raise ValueError("无法找到动态URL")
9598

96-
def title2metadata(title, log, result_queue, clean_downloaded_metadata, max_workers=MAX_WORKERS, max_title_list_num=MAX_TITLE_LIST_NUM ):
99+
def title2metadata(title, log, result_queue, clean_downloaded_metadata, max_workers=None, max_title_list_num=None):
100+
if max_workers is None:
101+
max_workers = CONFIG['max_workers']
102+
if max_title_list_num is None:
103+
max_title_list_num = CONFIG['max_title_list_num']
104+
97105
if not isinstance(title, str):
98106
raise TypeError("title必须是字符串")
99-
107+
100108
title = urllib.parse.quote(f"{title}")
101109
dynamic_url = get_dynamic_url(log)
102110
if not dynamic_url:
103111
return None
104112

105113
search_url = SEARCH_URL_TEMPLATE_TITLE.format(title=title)
106-
114+
107115
response = urllib.request.urlopen(urllib.request.Request(search_url, headers=HEADERS), timeout=10)
108116

109117
response_text = response.read().decode('utf-8')
110118

111119
titlelist = parse_search_list(response_text, log)
112-
120+
113121
spider_sleep()
114122

115-
116-
if len(titlelist)>MAX_TITLE_LIST_NUM:
117-
titlelist = titlelist[:MAX_TITLE_LIST_NUM]
123+
124+
if len(titlelist)>max_title_list_num:
125+
titlelist = titlelist[:max_title_list_num]
118126
# 使用线程池处理并发请求
119127
metadatas = []
120-
with ThreadPoolExecutor(max_workers=MAX_WORKERS) as executor:
121-
future_to_url = {executor.submit(url2metadata, item[1], log, result_queue, clean_downloaded_metadata, max_workers= MAX_WORKERS, max_title_list_num= MAX_TITLE_LIST_NUM): item for item in titlelist}
128+
with ThreadPoolExecutor(max_workers=max_workers) as executor:
129+
future_to_url = {executor.submit(url2metadata, item[1], log, result_queue, clean_downloaded_metadata, max_workers=max_workers, max_title_list_num=max_title_list_num): item for item in titlelist}
122130
for future in as_completed(future_to_url):
123131
data = future.result()
124132
if data:
125133
metadatas.append(data)
126134
return metadatas
127135

128-
def url2metadata(url, log, result_queue, clean_downloaded_metadata, max_workers= MAX_WORKERS, max_title_list_num= MAX_TITLE_LIST_NUM ):
136+
def url2metadata(url, log, result_queue, clean_downloaded_metadata, max_workers=None, max_title_list_num=None):
137+
if max_workers is None:
138+
max_workers = CONFIG['max_workers']
139+
if max_title_list_num is None:
140+
max_title_list_num = CONFIG['max_title_list_num']
141+
129142
if not isinstance(url, str):
130143
raise TypeError("url必须是字符串")
131144
search_url = url
132-
145+
133146
spider_sleep()
134147

135148
try:
@@ -333,7 +346,7 @@ def get_parse_metadata(html, isbn, log):
333346

334347
# 优化标题格式
335348
title = data.get("题名与责任", f"{isbn}")
336-
if IS_STRIP_TITLE:
349+
if CONFIG['is_strip_title']:
337350
pattern = r"([\u4e00-\u9fa5a-zA-Z0-9]+(?:[\u4e00-\u9fa5a-zA-Z0-9\s]+)?)(?=\s\[[\u4e00-\u9fa5]{2}\])" #
338351
try:
339352
match = re.search(pattern, title)
@@ -342,8 +355,8 @@ def get_parse_metadata(html, isbn, log):
342355
except re.error as e:
343356
log.error(f"正则表达式匹配错误: {e}, title: {title}")
344357

345-
authors = data.get("著者", "").split(' & ')
346-
if IS_STRIP_AUTHOR:
358+
authors = data.get("著者", "").split('\n')
359+
if CONFIG['is_strip_author']:
347360
author_pattern = re.compile(r'^(.*?)\s+(?:著|编)')
348361
try:
349362
stripped_authors = []
@@ -376,16 +389,16 @@ def get_parse_metadata(html, isbn, log):
376389
publisher = publisher_match.group(1) if publisher_match else ""
377390

378391
tags = data.get("主题", "").replace('--', '&')
379-
if not IS_PURSETAG:
392+
if not CONFIG['is_pursetag']:
380393
tags += f' & {publisher}'
381394
if year:
382395
tags += f' & {year}'
383396
# 处理中图分类号相关选项
384397
clc_code = data.get("中图分类号", "")
385-
if ADD_CLC_TO_TAGS:
386-
if CONVERT_CLC_TO_TAG:
398+
if CONFIG['add_clc_to_tags']:
399+
if CONFIG['convert_clc_to_tag']:
387400
# 使用 Parser 解析中图分类号
388-
parse_level = CLC_PARSE_LEVEL
401+
parse_level = CONFIG['clc_parse_level']
389402
parsed_clc = Parser.parse(clc_code)
390403
if parsed_clc:
391404
clc_codes = list(parsed_clc.values())[0]
@@ -425,7 +438,7 @@ def to_metadata(book, add_translator_to_author, log):
425438
) if add_translator_to_author and book.get('translators', None) else book['authors']
426439
mi = MetaInformation(book['title'], authors)
427440

428-
if IS_NCLHASH:
441+
if CONFIG['is_nlchash']:
429442
mi.identifiers = {PROVIDER_ID: book.get('isbn', ''),
430443
'nlchash': f"{hash_utf8_string(book['title']+book.get('pubdate', None))}"
431444
}
@@ -439,7 +452,9 @@ def to_metadata(book, add_translator_to_author, log):
439452
pubdate = book.get('pubdate', None)
440453
if pubdate:
441454
try:
442-
if re.compile('^\\d{4}-\\d+$').match(pubdate):
455+
if re.compile('^\\d{4}$').match(pubdate):
456+
mi.pubdate = datetime.strptime(pubdate, '%Y')
457+
elif re.compile('^\\d{4}-\\d+$').match(pubdate):
443458
mi.pubdate = datetime.strptime(pubdate, '%Y-%m')
444459
elif re.compile('^\\d{4}-\\d+-\\d+$').match(pubdate):
445460
mi.pubdate = datetime.strptime(pubdate, '%Y-%m-%d')
@@ -470,64 +485,69 @@ class NLCISBNPlugin(Source):
470485
# name, type, default, label, default, choices
471486
# type 'number', 'string', 'bool', 'choices'
472487
Option(
473-
'max_workers', 'number', MAX_WORKERS,
488+
'max_workers', 'number', CONFIG['max_workers'],
474489
_('最大线程数'),
475490
_('爬虫最大线程数。如果过大可能导致用户IP被封锁。')
476491
),
477492
Option(
478-
'max_title_list_num', 'number', MAX_TITLE_LIST_NUM,
493+
'max_title_list_num', 'number', CONFIG['max_title_list_num'],
479494
_('最大返回量'),
480495
_('通过标题搜索时,最多返回多少数据。请求量过多可能因为请求过于频繁被封锁IP。')
481496
),
482497
Option(
483-
'spider_base_sleep_time', 'number', SPIDER_BASE_SLEEP_TIME,
498+
'spider_base_sleep_time', 'number', CONFIG['spider_base_sleep_time'],
484499
_('爬虫基础间隔时间'),
485500
_('爬虫两次爬取的间隔时间(单位:ms毫秒)。爬虫间隔时间 = 爬虫基础间隔时间 + 30 ~ 600 ms 的随机间隔时间')
486501
),
487502
Option(
488-
'is_strip_title', 'bool', IS_STRIP_TITLE,
503+
'is_strip_title', 'bool', CONFIG['is_strip_title'],
489504
_('是否优化标题(实验功能)'),
490-
_('是否优化标题。如果该项为“是”,则去除标题中多余的部分。默认为“是”。')
505+
_('是否优化标题。如果该项为"是",则去除标题中多余的部分。默认为"是"。')
491506
),
492507
Option(
493-
'is_strip_author', 'bool', IS_STRIP_AUTHOR,
508+
'is_strip_author', 'bool', CONFIG['is_strip_author'],
494509
_('是否优化作者字段(实验功能)'),
495-
_('是否优化作者字段。如果该项为“是”,则去除作者字段中多余的部分。默认为“是”。该项可能导致错误,例如名字末尾本身带有著/编。')
510+
_('是否优化作者字段。如果该项为"是",则去除作者字段中多余的部分。默认为"是"。该项可能导致错误,例如名字末尾本身带有"著/编"。')
496511
),
497512
Option(
498-
'is_nlchash', 'bool', IS_NCLHASH,
513+
'is_nlchash', 'bool', CONFIG['is_nlchash'],
499514
_('是否使用nlchash字段(实验功能)'),
500-
_('是否使用nlchash字段。如果该项为“否”,则去除nlchash字段。默认为“是”。该项可能有利于改善isbn相同,而标题不同的情况。')
515+
_('是否使用nlchash字段。如果该项为"否",则去除nlchash字段。默认为"是"。该项可能有利于改善isbn相同,而标题不同的情况。')
501516
),
502517
Option(
503-
'is_pursetag', 'bool', IS_PURSETAG,
518+
'is_pursetag', 'bool', CONFIG['is_pursetag'],
504519
_('纯净的标签'),
505-
_('是否添加“日期”和“出版社到标签。如果该项为“否”,则不添加日期和出版社信息到标签。默认为“否”。')
520+
_('是否添加"日期"和"出版社"到标签。如果该项为"否",则不添加日期和出版社信息到标签。默认为"否"。')
506521
),
507522
Option(
508-
'is_fuzzy_search_with_author', 'bool', IS_FUZZY_SEARCH_WITH_AUTHOR,
523+
'is_fuzzy_search_with_author', 'bool', CONFIG['is_fuzzy_search_with_author'],
509524
_('是否使用作者信息进行模糊搜索(实验功能)'),
510-
_('是否将作者信息添加到标题中进行模糊搜索。如果该项为“是”,则将作者信息添加到标题中进行模糊搜索。默认为“是”。')
525+
_('是否将作者信息添加到标题中进行模糊搜索。如果该项为"是",则将作者信息添加到标题中进行模糊搜索。默认为"是"。')
511526
),
512527
Option(
513-
'add_clc_to_tags', 'bool', ADD_CLC_TO_TAGS,
528+
'add_clc_to_tags', 'bool', CONFIG['add_clc_to_tags'],
514529
_('是否添加中图分类号到标签'),
515-
_('是否将中图分类号添加到书籍标签中。默认为“是”。')
530+
_('是否将中图分类号添加到书籍标签中。默认为"是"。')
516531
),
517532
Option(
518-
'convert_clc_to_tag', 'bool', CONVERT_CLC_TO_TAG,
519-
_('中图分类号是否转化为具体分类'),
520-
_('是否将中图分类号转换为具体的分类信息。默认为“是”。')
533+
'convert_clc_to_tag', 'bool', CONFIG['convert_clc_to_tag'],
534+
_('中图分类号是否转化为具体分类'),
535+
_('是否将中图分类号转换为具体的分类信息。默认为"是"。')
521536
),
522537
Option(
523-
'clc_parse_level', 'number', CLC_PARSE_LEVEL,
538+
'clc_parse_level', 'number', CONFIG['clc_parse_level'],
524539
_('中图分类号解析层级'),
525540
_('解析中图分类号的层级深度,取值范围1-3。1表示仅解析一级分类,3表示解析完整分类。默认为2。')
526541
)
527542
)
528543

529544
def __init__(self, *args, **kwargs):
530545
Source.__init__(self, *args, **kwargs)
546+
# 从用户设置更新 CONFIG
547+
global CONFIG
548+
for key in CONFIG:
549+
if key in self.prefs:
550+
CONFIG[key] = self.prefs[key]
531551

532552
def get_book_url(self, identifiers):
533553
return None
@@ -549,7 +569,7 @@ def identify(self, log, result_queue, abort, title=None, authors=None, identifie
549569
metadata = None
550570
if title:
551571
log.info(f"正在根据书名获取metadata...")
552-
if IS_FUZZY_SEARCH_WITH_AUTHOR and authors and isinstance(authors, list):
572+
if CONFIG['is_fuzzy_search_with_author'] and authors and isinstance(authors, list):
553573
title += authors[0]
554574

555575
metadatas = title2metadata(title, log, result_queue, self.clean_downloaded_metadata,

0 commit comments

Comments
 (0)