v1.2.91 行情录入优化版:批量录入冠字号矫正、价格提取、编码规则统一

This commit is contained in:
甲辰生产 2026-04-14 02:02:56 +08:00
parent 2306e35dec
commit 4ac2492265
1 changed files with 140 additions and 23 deletions

View File

@ -452,19 +452,57 @@ def create_information(
db: Session = Depends(get_db) db: Session = Depends(get_db)
): ):
"""发布资讯""" """发布资讯"""
# 生成行情编号:日期 + 5位自然数从00001开始 # 验证并矫正冠字号必须是J0开头 + 8位数字 = 共10位
if data.title:
import re
# 提取冠字号J0开头后面跟数字
match = re.search(r'J0(\d+)', data.title)
if match:
num = match.group(1)
# 必须是8位数字
if len(num) > 8:
# 多于8位取前8位
num = num[:8]
elif len(num) < 8:
# 少于8位前面补0
num = num.zfill(8)
# 重新构建title确保是J0开头
original = match.group(0)
data.title = data.title.replace(original, 'J0' + num, 1)
else:
# 如果不是J0开头尝试转换
other_match = re.search(r'J([1-9]\d{0,8})', data.title)
if other_match:
# 非J0开头的尝试补0变成J0开头
num = other_match.group(1).zfill(8)[:8]
original = other_match.group(0)
data.title = data.title.replace(original, 'J0' + num, 1)
# 生成行情编号:年份后两位+月+日+当日序号如260414001
# 序号在当天最大序号基础上+1
deal_no = None deal_no = None
if data.info_type == 'deal': if data.info_type == 'deal':
today = datetime.now().strftime('%Y%m%d')
# 查询当天已有行情数量
from app.models.models import Information from app.models.models import Information
count_today = db.query(Information).filter( today = datetime.now().strftime('%y%m%d') # 如260414
# 查询当天最大的deal_no
max_deal = db.query(Information.deal_no).filter(
Information.info_type == 'deal', Information.info_type == 'deal',
Information.deal_no.like(f'DJ{today}%') Information.deal_no.isnot(None),
).count() Information.deal_no != '',
# 编号 = 日期 + 5位自然数如 DJ2026041100001 Information.deal_no.like(f'{today}%')
seq = count_today + 1 ).order_by(Information.deal_no.desc()).first()
deal_no = f'DJ{today}{seq:05d}'
if max_deal and max_deal[0] and max_deal[0].startswith(today):
# 当天已有编号,提取序号并+1
try:
current_seq = int(max_deal[0][6:]) # 取最后3位序号
new_seq = current_seq + 1
except:
new_seq = 1
else:
# 新的一天从001开始
new_seq = 1
deal_no = f'{today}{new_seq:03d}'
info = Information( info = Information(
user_id=current_user.f99_90_id, user_id=current_user.f99_90_id,
@ -511,6 +549,12 @@ def create_information(
view_count=info.view_count, view_count=info.view_count,
contact_count=info.contact_count, contact_count=info.contact_count,
created_at=info.created_at, created_at=info.created_at,
packaging=info.packaging,
is_graded=info.is_graded,
grading_company=info.grading_company,
grading_score=info.grading_score,
category=info.category,
deal_no=info.deal_no,
user_name=current_user.f01_01_name, user_name=current_user.f01_01_name,
user_avatar=current_user.avatar, user_avatar=current_user.avatar,
collection_name=None, collection_name=None,
@ -1277,7 +1321,45 @@ async def batch_parse_deals(text: str = Body(..., embed=True)):
# 尝试直接解析 # 尝试直接解析
data = json.loads(content.strip()) data = json.loads(content.strip())
return {"success": True, "data": data} # 对AI返回的数据进行冠字号矫正 - 确保J0开头+8位数字
def normalize_serial_ai(num_str):
"""矫正冠字号J0开头8位数字共10位"""
if not num_str.startswith('J0'):
return None
num = num_str[2:] # 去掉J0
diff = 8 - len(num)
# 位数正好8位不需要矫正
if diff == 0:
return num_str
elif diff == -1:
# 多1位取前4位+最后4位
if len(num) >= 4:
result = num[:4] + num[-4:]
if len(result) == 8:
return 'J0' + result
elif diff == 1:
# 少1位J0 + 0 + 数字
return 'J0' + '0' + num
elif diff == -2:
# 多2位取前4位+最后4位
if len(num) >= 4:
result = num[:4] + num[-4:]
if len(result) == 8:
return 'J0' + result
elif diff == 2:
# 少2位J0 + 00 + 数字
return 'J0' + '00' + num
return None
# 矫正每条记录的冠字号
corrected_data = []
for item in data:
if 'serial' in item:
normalized = normalize_serial_ai(item['serial'])
if normalized:
item['serial'] = normalized
corrected_data.append(item)
return {"success": True, "data": corrected_data}
except json.JSONDecodeError: except json.JSONDecodeError:
# 尝试用正则提取 # 尝试用正则提取
match = re.search(r'\[.*\]', content, re.DOTALL) match = re.search(r'\[.*\]', content, re.DOTALL)
@ -1330,24 +1412,59 @@ def parse_deals_locally(text: str, default_packaging: str = '', default_date: st
default_date = datetime.now().strftime('%Y-%m-%d') default_date = datetime.now().strftime('%Y-%m-%d')
deal_date = extracted_date or default_date deal_date = extracted_date or default_date
# 冠字号矫正函数 - 确保是J0开头+8位数字
def normalize_serial(num_str, needs_j0=False):
"""矫正冠字号J0开头8位数字共10位"""
num = num_str
# 如果是单独的7-9位数字无J0前缀取后8位
if needs_j0 and len(num) > 8:
num = num[-8:]
diff = 8 - len(num)
# 位数正好8位不需要矫正
if diff == 0:
return 'J0' + num
# 少1位7位数字→ J0 + 0 + 数字
elif diff == 1:
return 'J0' + '0' + num
# 多1位9位数字→ J0 + 取前4位+后4位 = 8位数字
elif diff == -1:
if len(num) >= 8:
result = num[:4] + num[-4:]
return 'J0' + result
return None # 无法矫正
lines = text.strip().split('\n') lines = text.strip().split('\n')
for line in lines: for line in lines:
line = line.strip() line = line.strip()
if not line or 'J0' not in line: if not line:
continue continue
# 提取冠字号 J0 + 8-9位数字 # 提取冠字号J0 + 至少7位数字可能到10位或者单独的7~9位数字
serial_match = re.search(r'J0(\d{8,9})', line) # 优先匹配 J0开头否则匹配单独的7-9位数字
serial_num = None
serial_match = re.search(r'J0(\d{7,11})', line)
if not serial_match: if not serial_match:
continue # 尝试匹配单独的7-9位数字前面是空格或行首
serial_match = re.search(r'(?:^|\s)(\d{7,9})(?:\s|$|\n)', line)
if serial_match:
# 单独的7-9位数字需要加上J0前缀
num = serial_match.group(1)
serial_num = num
serial = normalize_serial(num, needs_j0=True)
else:
continue
else:
# J0开头的7-9位数字
serial_num = serial_match.group(1)
serial = normalize_serial(serial_num, needs_j0=False)
serial_num = serial_match.group(1) if not serial:
if len(serial_num) == 9: continue # 跳过无法矫正的数据
serial_num = serial_num[:8]
serial = 'J0' + serial_num
# 提取价格 ¥xxx,xxx 或 xxx,xxx必须在J0之后 # 提取价格:在冠字号之后提取价格
serial_pos = line.find(serial) serial_pos = line.find(serial)
after_serial = line[serial_pos + len(serial):] after_serial = line[serial_pos + len(serial):]
price_match = re.search(r'[¥¥]?\s*([1-9][\d,]{2,})', after_serial) price_match = re.search(r'[¥¥]?\s*([1-9][\d,]{2,})', after_serial)
@ -1356,13 +1473,13 @@ def parse_deals_locally(text: str, default_packaging: str = '', default_date: st
price = int(price_match.group(1).replace(',', '')) price = int(price_match.group(1).replace(',', ''))
# 提取卖家(价格后面的中文字符) # 提取卖家(价格后面的中文字符)
after_price_pos = after_serial.find(price_match.group(0)) + len(price_match.group(0)) after_price_pos = line.find(price_match.group(0)) + len(price_match.group(0))
after_price = after_serial[after_price_pos:] after_price = line[after_price_pos:]
seller_match = re.search(r'([^\d\s¥¥]+?)(?:\s*$|\s*\n)', after_price) seller_match = re.search(r'([^\d\s¥¥]+?)(?:\s*$|\s*\n)', after_price)
seller = seller_match.group(1).strip() if seller_match else '' seller = seller_match.group(1).strip() if seller_match else ''
# 分类判断 # 分类判断使用矫正后的冠字号去掉J0前缀的8位数字
digits = serial_num digits = serial[2:] # 去掉J0前缀
d = digits d = digits
category = '通货' category = '通货'
if not any(c in d for c in ['1','2','3','4','5','7']): category = '圆圆号' if not any(c in d for c in ['1','2','3','4','5','7']): category = '圆圆号'