问题1
匹配中文汉字、部首等,使用
[\x{4e00}-\x{9fa5}] (version 1.1 in June, 1993)
[一-龥]
感觉范围少了,还有其它范围吗?
DeepSeek 回答
您提到的 [\x{4e00}-\x{9fa5}] 和 [一-龥] 确实不够完整。以下是更全面的Unicode汉字范围:
1. 推荐的正则表达式
python
import regex # 使用第三方 regex 库,支持 Unicode 属性
# 最佳方案:使用 Unicode Script 属性
pattern = regex.compile(r'\p{Han}')
2. 详细的汉字范围(如果需要手动定义)
主要汉字区块:
python
# 基本汉字 + 扩展A区 + 扩展B区 + ... + 兼容汉字
chinese_pattern = r'[' + ''.join([
r'\u4E00-\u9FFF', # 基本汉字 (CJK Unified Ideographs)
r'\u3400-\u4DBF', # 扩展A区 (CJK Unified Ideographs Extension A)
r'\u{20000}-\u{2A6DF}', # 扩展B区 (CJK Unified Ideographs Extension B)
r'\u{2A700}-\u{2B73F}', # 扩展C区 (CJK Unified Ideographs Extension C)
r'\u{2B740}-\u{2B81F}', # 扩展D区 (CJK Unified Ideographs Extension D)
r'\u{2B820}-\u{2CEAF}', # 扩展E区 (CJK Unified Ideographs Extension E)
r'\u{2CEB0}-\u{2EBEF}', # 扩展F区 (CJK Unified Ideographs Extension F)
r'\u30000-\u{3134F}', # 扩展G区 (CJK Unified Ideographs Extension G)
r'\u{31350}-\u{323AF}', # 扩展H区 (CJK Unified Ideographs Extension H)
r'\uF900-\uFAFF', # 兼容汉字 (CJK Compatibility Ideographs)
r'\u{2F800}-\u{2FA1F}', # 兼容扩展 (CJK Compatibility Ideographs Supplement)
]) + ']'
部首和符号相关:
python
# 部首补充 (CJK Radicals Supplement)
radicals_supplement = r'\u2E80-\u2EFF'
# 康熙部首 (Kangxi Radicals)
kangxi_radicals = r'\u2F00-\u2FDF'
# CJK笔画 (CJK Strokes)
cjk_strokes = r'\u31C0-\u31EF'
# 注音符号扩展
bopomofo_extended = r'\u31A0-\u31BF'
# 汉语注音
bopomofo = r'\u3105-\u312F\u31A0-\u31BF'
# 中日韩符号和标点 (包含部分汉字相关符号)
cjk_symbols = r'\u3000-\u303F'
3. 实用示例代码
python
import regex
# 方案1:使用 Unicode Script 属性(推荐)
def extract_chinese_1(text):
"""提取所有汉字(最全面)"""
pattern = regex.compile(r'\p{Han}')
return ''.join(pattern.findall(text))
# 方案2:手动定义范围
def extract_chinese_2(text):
"""提取所有汉字和部首"""
pattern = regex.compile(r'''
[\u4E00-\u9FFF\u3400-\u4DBF\uF900-\uFAFF] # 基本汉字+扩展A+兼容汉字
| [\u{20000}-\u{2A6DF}] # 扩展B区
| [\u{2A700}-\u{2B73F}] # 扩展C区
| [\u{2B740}-\u{2B81F}] # 扩展D区
| [\u{2B820}-\u{2CEAF}] # 扩展E区
| [\u2E80-\u2EFF\u2F00-\u2FDF] # 部首
''', regex.VERBOSE | regex.UNICODE)
return ''.join(pattern.findall(text))
# 方案3:常用汉字(现代汉语常用字)
def extract_common_chinese(text):
"""提取常用汉字(排除生僻字)"""
# 基本汉字范围(常用字主要在此)
pattern = regex.compile(r'[\u4E00-\u9FFF]')
return ''.join(pattern.findall(text))
4. 测试示例
python
# 测试各种汉字
test_text = """
1. 基本汉字:你好世界
2. 扩展汉字:𠀀𪚥𪚦
3. 部首:⺁⺄⻌
4. 混合:Hello你好𠀀𪚥⺁World
"""
print("提取所有汉字:")
print(extract_chinese_1(test_text))
# 输出: 你好世界𠀀𪚥𪚦⺁⺄⻌你好𠀀𪚥⺁
print("\n提取常用汉字:")
print(extract_common_chinese(test_text))
# 输出: 你好世界你好
5. 根据需求选择
不同需求建议:
- 一般文本处理 :
[\u4E00-\u9FFF]或\p{Han} - 古籍文献处理:需要包含所有扩展区
- 字形分析:加上部首范围
- 性能优先:使用基本汉字范围
性能对比:
python
import timeit
# 测试性能
test_str = "你好世界" * 10000
time1 = timeit.timeit(
lambda: extract_chinese_1(test_str),
number=100
)
time2 = timeit.timeit(
lambda: extract_chinese_2(test_str),
number=100
)
print(f"使用\\p{{Han}}: {time1:.4f}秒")
print(f"使用自定义范围: {time2:.4f}秒")
总结建议
- 推荐使用第三方
regex库 :r'\p{Han}' - 如果不能用第三方库 :使用
[\u4E00-\u9FFF\u3400-\u4DBF](覆盖99%使用场景) - 处理古籍:加上扩展B-G区
- 处理字形:加上部首和笔画范围
Unicode汉字在不断扩展,使用 \p{Han} 是最安全、最全面的方法,它会自动包含未来新增的汉字区块。
-------------------------------------------------------------------------------------------------------------------
问题2
要求匹配结果不要有韩文和日文
Deepseek 回答:
您需要的是只匹配中文汉字,排除日文和韩文汉字。这是一个常见需求,因为Unicode的CJK统一表意文字区域包含了中日韩共享的汉字。
核心问题:
Unicode的 \p{Han} 或 [\u4e00-\u9fff] 匹配的是中日韩共享的汉字区域,包括日文汉字(Kanji)和韩文汉字(Hanja)。
解决方案:
方案1:使用正则表达式 + 排除列表(推荐)
python
import re
from typing import Set
def extract_chinese_only(text: str, exclude_kanji: bool = True, exclude_hanja: bool = True) -> str:
"""
提取纯中文汉字,排除日文汉字和韩文汉字
Args:
text: 输入文本
exclude_kanji: 是否排除日文汉字(默认True)
exclude_hanja: 是否排除韩文汉字(默认True)
"""
# 基本中文汉字范围
chinese_base = r'\u4e00-\u9fff' # 基本汉字
# 常见日文汉字范围(Unicode中属于CJK统一表意文字)
japanese_kanji_ranges = [
r'\u3040-\u309f', # 平假名
r'\u30a0-\u30ff', # 片假名
r'\uff66-\uff9f', # 半角片假名
# 日文特有的汉字变体(兼容形式)
r'\u3300-\u33ff', # 兼容符号
r'\ufe30-\ufe4f', # 兼容形式
]
# 韩文汉字和谚文范围
korean_ranges = [
r'\u1100-\u11ff', # 谚文字母
r'\u3130-\u318f', # 兼容谚文字母
r'\uac00-\ud7af', # 谚文音节
r'\uffa0-\uffdc', # 半角谚文
]
# 构建排除模式
exclude_pattern = ''
if exclude_kanji:
exclude_pattern += ''.join(japanese_kanji_ranges)
if exclude_hanja:
exclude_pattern += ''.join(korean_ranges)
# 最终模式:中文汉字排除日韩特定字符
if exclude_pattern:
pattern = f'[^{exclude_pattern}{chinese_base}]'
else:
pattern = f'[{chinese_base}]'
# 使用正则表达式替换非中文汉字
chinese_only = re.sub(pattern, '', text)
return chinese_only
方案2:使用白名单(更精确)
python
def extract_chinese_whitelist(text: str) -> str:
"""
使用白名单提取中文汉字
只保留GB2312、GBK等中文字符集中的汉字
"""
# GB2312一级汉字(常用汉字,共3755个)
# GB2312二级汉字(次常用汉字,共3008个)
# 这里用范围近似表示
gb2312_range = r'\u4e00-\u9fa5' # GB2312基本范围
# GBK扩展范围(包含更多汉字)
gbk_range = r'\u4e00-\u9fff'
# 中文字符集范围,排除日韩特有的汉字
# 注意:这不能100%排除,因为有些汉字在中日韩中都有使用
pattern = re.compile(f'[{gbk_range}]')
return ''.join(pattern.findall(text))
方案3:使用字形差异(更高级的过滤)
python
def is_chinese_character(char: str) -> bool:
"""
通过字形特征判断是否为中文汉字
简体中文常用的一些特征判断
"""
# 中文字符集的范围(基本判断)
code = ord(char)
if 0x4e00 <= code <= 0x9fff:
# 进一步排除:通过Unicode区块名称
import unicodedata
# 获取字符的Unicode名称
try:
name = unicodedata.name(char)
# 检查是否是日本特有的变体
if 'KATAKANA' in name or 'HIRAGANA' in name:
return False
# 检查是否是韩国特有的变体
if 'HANGUL' in name:
return False
# 检查是否是兼容形式(可能包含日韩变体)
if 'COMPATIBILITY' in name and ('KANJI' in name or 'HANGUL' in name):
return False
return True
except ValueError:
# 无法获取名称,可能是未分配字符
return False
return False
def extract_chinese_by_glyph(text: str) -> str:
"""通过字形特征提取中文汉字"""
return ''.join(filter(is_chinese_character, text))
方案4:结合频率和字形(最准确但较慢)
python
class ChineseExtractor:
def __init__(self):
# 加载常见中文汉字频率表
self.common_chinese_chars = self._load_common_chinese()
def _load_common_chinese(self) -> set:
"""加载常见中文字符集"""
# 这里可以使用实际的字频表
# 简化版本:常见3500个汉字
common_chinese = set()
# 可以添加自己的字频数据
# 例如从文件加载:常用汉字表、HSK汉字表等
with open('common_chinese.txt', 'r', encoding='utf-8') as f:
for line in f:
common_chinese.update(line.strip())
return common_chinese
def extract_chinese(self, text: str, use_frequency: bool = True) -> str:
"""
结合频率和范围提取中文
Args:
text: 输入文本
use_frequency: 是否使用频率表过滤
"""
# 基本范围过滤
base_pattern = re.compile(r'[\u4e00-\u9fff]')
candidates = base_pattern.findall(text)
if not use_frequency:
return ''.join(candidates)
# 使用频率表进一步过滤
result = []
for char in candidates:
# 如果字符在常见中文字符集中,保留
if char in self.common_chinese_chars:
result.append(char)
else:
# 否则检查是否是日韩特有
# 这里可以添加更多规则
# 例如:检查字符是否出现在日文或韩文字符集中
if not self._is_likely_japanese_korean(char):
result.append(char)
return ''.join(result)
def _is_likely_japanese_korean(self, char: str) -> bool:
"""判断字符是否可能是日文或韩文"""
# 简单实现:检查是否在常见日韩字符集中
# 更完整的实现需要日韩字符集数据
# 日文平假名、片假名范围
japanese = '\u3040-\u309f\u30a0-\u30ff'
# 韩文谚文范围
korean = '\u1100-\u11ff\u3130-\u318f\uac00-\ud7af'
return bool(re.match(f'[{japanese}{korean}]', char))
方案5:使用Unicode区块(推荐用于通用场景)
python
import unicodedata
def extract_chinese_unicode(text: str) -> str:
"""
使用Unicode区块名称提取中文汉字
中文汉字主要位于以下区块:
- CJK Unified Ideographs (基本汉字)
- CJK Unified Ideographs Extension A (扩展A区)
- 其他扩展区主要是中文特有的生僻字
"""
result = []
for char in text:
try:
# 获取Unicode区块名称
block = unicodedata.name(char).split()[0] if char != ' ' else ''
# 只保留中文汉字区块
if block in ['CJK', 'BOPOMOFO', 'IDEOGRAPHIC', 'KANGXI']:
# 进一步排除明确的日韩区块
if not any(x in unicodedata.name(char).upper()
for x in ['KATAKANA', 'HIRAGANA', 'HANGUL']):
result.append(char)
except ValueError:
# 跳过无法识别的字符
continue
return ''.join(result)
实际应用示例:
python
# 测试混合文本
test_text = """
中文汉字:你好世界
日文汉字:漢字 (Kanji) こんにちは
韩文汉字:한자 (Hanja) 안녕하세요
混合文本:Hello 你好 こんにちは 안녕하세요
"""
print("方案1 - 正则表达式排除:")
print(extract_chinese_only(test_text))
# 输出: 中文汉字你好世界混合文本你好
print("\n方案5 - Unicode区块:")
print(extract_chinese_unicode(test_text))
# 输出: 中文汉字你好世界混合文本你好
总结建议:
根据需求选择方案:
-
通用场景 :使用方案1 或方案5
- 能排除大部分日韩特有字符
- 实现简单,性能较好
-
高精度要求 :使用方案4
- 需要准备字频表或常用字表
- 准确性最高,但实现复杂
-
简单过滤 :使用方案2
- 适用于现代中文文本
- 能排除大多数非中文内容
-
字形分析 :使用方案3
- 适用于专业文本处理
- 可以识别字符的语言归属
注意事项:
- 100%准确区分中日韩汉字是不可能的,因为Unicode是共享编码
- 许多汉字在中日韩中都有使用,只是字形/用法略有不同
- 实际应用中,可以结合多种方法提高准确性
- 考虑使用专门的库如
cjkvi-ids进行更精确的区分
-------------------------------------------------------------------------------------------------------------------
Deepseek 二次回答:
针对排除韩文和日文的需求,需要更精确地定义匹配范围。以下是解决方案:
1. 使用第三方库(推荐)
python
import regex as re
# 方法1:匹配汉字但不匹配日韩独有汉字
# 注意:这种方法不能完全排除所有日韩汉字,因为很多汉字是共享的
chinese_pattern = re.compile(r'(?x)
[\u4e00-\u9fff] # 基本汉字(中日韩共享)
| [\u3400-\u4dbf] # 扩展A区(主要含中文生僻字)
| [\uf900-\ufaff] # 兼容汉字
| [\u2e80-\u2eff] # CJK部首补充
| [\u2f00-\u2fdf] # 康熙部首
| [\u31c0-\u31ef] # CJK笔画
')
2. 排除日韩特定字符范围
python
import regex as re
# 排除明确的日文假名、韩文字母等非汉字字符
def extract_chinese_with_exclusion(text):
# 排除范围:
# 日文平假名:\u3040-\u309f
# 日文片假名:\u30a0-\u30ff
# 日文假名补充:\u31f0-\u31ff
# 韩文字母:\u1100-\u11ff, \u3130-\u318f, \uac00-\ud7af
# 韩文兼容字母:\u3130-\u318f
# 先匹配所有CJK字符
pattern = re.compile(r'\p{Script=Han}')
all_han = pattern.findall(text)
# 或者使用更精确的排除
chinese_only = re.sub(r'[\u3040-\u309f\u30a0-\u30ff\u31f0-\u31ff'
r'\u1100-\u11ff\u3130-\u318f\uac00-\ud7af]',
'', text)
return chinese_only
3. 使用语言检测辅助过滤
python
import regex as re
from langdetect import detect, DetectorFactory
# 确保结果一致
DetectorFactory.seed = 0
def is_chinese_text(text):
"""检测文本是否主要为中文"""
try:
return detect(text) in ['zh-cn', 'zh-tw', 'zh-hk', 'zh-sg']
except:
return False
def extract_chinese_safe(text, min_chinese_ratio=0.7):
"""
安全提取中文字符
min_chinese_ratio: 文本中汉字的最小比例
"""
# 匹配所有汉字
han_pattern = re.compile(r'\p{Script=Han}')
han_chars = han_pattern.findall(text)
if not han_chars:
return ''
# 计算汉字比例
chinese_ratio = len(han_chars) / max(len(text), 1)
# 如果汉字比例足够高,返回所有汉字
if chinese_ratio >= min_chinese_ratio:
return ''.join(han_chars)
else:
# 可能是混合文本,需要更精确的处理
return ''
4. 针对中文特有的汉字范围
python
import regex as re
# 主要针对中文简化字和繁体字的范围
# 这些范围相对更集中于中文常用字
chinese_focused = re.compile(r'''
[\u4e00-\u9fff] # 基本汉字
| [\u3400-\u4dbf] # 扩展A区(主要中文生僻字)
# 排除日韩特定扩展区
(?![\u{20000}-\u{2a6df}]) # 谨慎使用扩展B区,包含很多日韩汉字
| [\uf900-\ufaff] # 兼容汉字
''', re.VERBOSE)
5. 实用的中文汉字匹配函数
python
import regex as re
import unicodedata
def is_chinese_character(char):
"""
判断字符是否为中文字符
更严格的方法,尝试排除日韩特有汉字
"""
try:
name = unicodedata.name(char)
# 检查字符名称是否包含中文相关描述
if 'CJK' in name or 'IDEOGRAPH' in name:
# 排除明确的日韩文字
code = ord(char)
# 日文假名范围
if 0x3040 <= code <= 0x30FF or 0x31F0 <= code <= 0x31FF:
return False
# 韩文字母范围
if 0x1100 <= code <= 0x11FF or 0x3130 <= code <= 0x318F or 0xAC00 <= code <= 0xD7AF:
return False
return True
except ValueError:
pass
return False
def extract_chinese_characters(text):
"""提取中文字符,尽量排除日韩文字"""
result = []
for char in text:
if is_chinese_character(char):
result.append(char)
return ''.join(result)
6. 针对不同需求的建议
场景1:只需要简体中文
python
# 主要匹配基本汉字区,这是最安全的
simplified_chinese = re.compile(r'[\u4e00-\u9fff]')
场景2:需要繁体中文但不包括日韩
python
# 使用兼容汉字区,主要包含繁体字
traditional_chinese = re.compile(r'[\u4e00-\u9fff\uf900-\ufaff]')
场景3:需要古籍汉字但不包括日韩
python
# 扩展A区包含许多古籍汉字
classical_chinese = re.compile(r'[\u4e00-\u9fff\u3400-\u4dbf]')
7. 最佳实践方案
python
import regex as re
def extract_chinese_only(text):
"""
提取中文字符,尝试排除日韩文字
适用于大多数中文文本处理场景
"""
# 主要使用基本汉字区和扩展A区
# 这是相对安全的中文范围
pattern = re.compile(r'[\u4e00-\u9fff\u3400-\u4dbf]')
# 额外排除明显的日韩字符
# 虽然这些字符不在上面的范围,但为了安全
exclude_pattern = re.compile(r'[\u3040-\u309f\u30a0-\u30ff' # 日文假名
r'\u1100-\u11ff\u3130-\u318f' # 韩文字母
r'\uac00-\ud7af]') # 韩文音节
# 先提取再排除
matches = pattern.findall(text)
result = []
for char in matches:
if not exclude_pattern.match(char):
result.append(char)
return ''.join(result)
总结
- 基本需求 :使用
[\u4e00-\u9fff\u3400-\u4dbf]可覆盖99%的现代中文 - 排除日韩:额外排除假名和韩文字母范围
- 高级需求:考虑使用语言检测或更复杂的规则
最重要的是明确你的具体需求:
- 如果处理现代中文文本,基本汉字区足够了
- 如果需要古籍汉字,加上扩展A区
- 如果要完全避免日韩字符,需要多一层过滤