box_script.py 3.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. import re
  2. def extract_quantity_and_unit(text: str):
  3. """
  4. 从药品选择文本中提取数量与单位。
  5. 优先级:
  6. 1. 选几发几 → (1, '盒')
  7. 2. X盒装 / X瓶装 → (X, 单位)
  8. 3. 已选: X盒 / 已选择: X瓶 → (X, 单位)
  9. 4. 显式数字/中文数字 + 单位(如 10盒, 三粒)
  10. 5. 特殊模式 *数字.../盒 或 *数字.../瓶(如 0.5g*15袋/盒)→ (1, 盒/瓶)
  11. 6. 数字ml/单位(如 100ml/盒)→ (1, 单位)
  12. 7. 单独数字ml(如 120ml)→ (1, '瓶')
  13. """
  14. unit_pattern = '瓶|盒|支|只|个|袋|包|粒|片|贴|罐|桶|条|板|枚|颗|管|套|丸|锭|听'
  15. def chinese_to_int(s: str):
  16. if s.isdigit():
  17. return int(s)
  18. chinese_map = {'一':1,'二':2,'三':3,'四':4,'五':5,
  19. '六':6,'七':7,'八':8,'九':9,'十':10,
  20. '百':100,'千':1000,'万':10000}
  21. if len(s) == 1:
  22. return chinese_map.get(s, 0)
  23. if len(s) == 2 and s[0] in chinese_map and s[1] == '十':
  24. return chinese_map[s[0]] * 10
  25. if s == '十':
  26. return 10
  27. return 1
  28. # 1. 选几发几
  29. if re.search(r'选\d+发\d+|选[一二三四五六七八九十]+发[一二三四五六七八九十]+', text):
  30. return (1, '盒')
  31. # 2. 匹配 "X盒装" 或 "X瓶装"
  32. package_match = re.search(r'(\d+)\s*(瓶|盒)装', text)
  33. if package_match:
  34. quantity = int(package_match.group(1))
  35. unit = package_match.group(2)
  36. return (quantity, unit)
  37. # 3. 匹配 "已选: X盒" 或 "已选择: X瓶"
  38. selected_match = re.search(r'已选[择::]\s*(\d+)\s*(盒|瓶)', text)
  39. if selected_match:
  40. quantity = int(selected_match.group(1))
  41. unit = selected_match.group(2)
  42. return (quantity, unit)
  43. # 4. 显式数字/中文数字 + 单位(优先级最高)
  44. explicit_match = re.search(
  45. r'([一二三四五六七八九十百千万]+|\d+)\s*/?\s*(' + unit_pattern + r')',
  46. text
  47. )
  48. if explicit_match:
  49. num_str, unit = explicit_match.groups()
  50. quantity = chinese_to_int(num_str)
  51. return (quantity, unit)
  52. # 5. 特殊模式:*数字.../盒 或 *数字.../瓶
  53. special_match = re.search(r'\*\s*\d+\s*.*?/(盒|瓶)(?:装)?', text, re.IGNORECASE)
  54. if special_match:
  55. unit = special_match.group(1)
  56. return (1, unit)
  57. # 6. 数字ml/单位
  58. implicit_match = re.search(r'[\d\.]+\s*ml\s*/\s*(' + unit_pattern + r')', text, re.I)
  59. if implicit_match:
  60. unit = implicit_match.group(1)
  61. return (1, unit)
  62. # 7. 单独数字ml → 1瓶
  63. if re.search(r'[\d\.]+\s*ml', text, re.I):
  64. return (1, '瓶')
  65. return (None, None)
  66. # 测试使用,后续有问题在这里测试修改
  67. # if __name__ == '__main__':
  68. # test_cases = [
  69. # "已选: 1盒装", # → 1盒
  70. # "已选: 2盒", # → 2盒
  71. # "12瓶装", # → 12瓶
  72. # "0.5g*15袋/盒", # → 1盒
  73. # "0.33g*24/粒/盒", # → 1盒
  74. # "0.5g*100/片/瓶", # → 1瓶
  75. # "10mg*20/粒/瓶", # → 1瓶
  76. # "已选择: 25ml/瓶", # → 1瓶
  77. # "0.5g*15袋/盒装", # → 1盒
  78. # "10盒", # → 10盒
  79. # "一支", # → 1支
  80. # "两粒", # → 2粒
  81. # ]
  82. # for ex in test_cases:
  83. # q, u = extract_quantity_and_unit(ex)
  84. # print(f"{ex:30s} -> {q}{u if u else ''}")