From 90e496298b21f0594b85535ec47d26d2d7d5a9ed Mon Sep 17 00:00:00 2001
From: cloudroam <cloudroam>
Date: 星期四, 03 七月 2025 17:33:09 +0800
Subject: [PATCH] fix:生成的内容

---
 app.py   |  200 ++++++++++++++++++-
 test2.py |  381 +++++++++++++++++++++----------------
 2 files changed, 404 insertions(+), 177 deletions(-)

diff --git a/app.py b/app.py
index 9a8237a..872cff9 100644
--- a/app.py
+++ b/app.py
@@ -203,13 +203,14 @@
         # 还款短信特征
         repayment_keywords = [
             "还款", "账单", "信用卡", "借款", "贷款", "逾期", "欠款", "最低还款",
-            "应还金额", "到期还款", "还清", "应还", "还款日", "账单¥", "账单¥", "查账还款"
+            "应还金额", "到期还款", "还清", "应还", "还款日", "账单¥", "账单¥", "查账还款",
+            "扣款用于", "房贷还款", "信用卡还款", "车贷还款", "应还款额", "最低还款额"
         ]
         
         # 收入短信特征
         income_keywords = [
             "收入", "转账", "入账", "到账", "支付", "工资", "报销", "余额", 
-            "成功收款", "收到", "款项"
+            "成功收款", "收到", "款项", "收入金额"
         ]
         
         # 航班/火车票特征
@@ -342,8 +343,15 @@
             # 快递关键词
             "快递", "包裹", "取件码", "取件", "签收", "派送", "配送",
             # 收入关键词
-            "收入", "转账", "入账", "到账", "支付成功", "工资"
+            "收入", "转账", "入账", "到账", "支付成功", "工资", "支付宝转账", "微信转账"
         ]
+        
+        # 先检查是否为收入短信(优先于通知判断)
+        income_indicators = ["收入", "入账", "转账", "工资"]
+        for indicator in income_indicators:
+            if indicator in text and "元" in text:
+                # 可能是收入短信,不要判断为通知
+                return False
         
         # 运营商余额通知特征
         telecom_balance_patterns = [
@@ -458,20 +466,62 @@
                     if word in code:
                         code = code[:code.index(word)]
                 
-                # 只保留字母、数字和连字符
-                code = ''.join(c for c in code if c.isalnum() or c == "-")
+                # 针对不同快递公司采取不同策略
+                if "丰巢" in text or "蜂巢" in text:
+                    # 对于丰巢快递,只保留数字
+                    code = ''.join(c for c in code if c.isdigit())
+                elif "中国邮政" in text:
+                    # 对于中国邮政,尝试提取完整货位号
+                    cargo_match = re.search(r'货号[::]\s*([0-9A-Za-z\-]+)', text)
+                    if cargo_match:
+                        code = cargo_match.group(1)
+                    else:
+                        # 保留原始格式(字母、数字和连字符)
+                        code = ''.join(c for c in code if c.isalnum() or c == "-")
+                else:
+                    # 对于其他快递,保留字母、数字和连字符
+                    code = ''.join(c for c in code if c.isalnum() or c == "-")
                 
                 # 确保格式正确
-                parts = code.split("-")
-                valid_parts = []
-                for part in parts:
-                    if part and any(c.isalnum() for c in part):
-                        valid_parts.append(part)
-                
-                if valid_parts:
-                    result["pickup_code"] = "-".join(valid_parts)
+                if "丰巢" in text or "蜂巢" in text:
+                    # 对于丰巢快递,只保留数字
+                    if code.isdigit():
+                        result["pickup_code"] = code
+                    else:
+                        # 如果没有数字,尝试再次从文本中匹配纯数字取件码
+                        pickup_code_match = re.search(r'码[^0-9]*(\d+)', text)
+                        if pickup_code_match:
+                            result["pickup_code"] = pickup_code_match.group(1)
+                        else:
+                            result["pickup_code"] = None
+                elif "中国邮政" in text:
+                    # 对于中国邮政,验证格式是否合理
+                    if re.match(r'[0-9A-Za-z\-]+', code):
+                        result["pickup_code"] = code
+                    else:
+                        # 二次尝试:从文本中直接获取货位号
+                        cargo_match = re.search(r'货号[::]\s*([0-9A-Za-z\-]+)', text)
+                        if cargo_match:
+                            result["pickup_code"] = cargo_match.group(1)
+                        else:
+                            # 最后尝试:提取"取件密码"后的纯数字序列
+                            password_match = re.search(r'密码\s*(\d+)', text)
+                            if password_match:
+                                result["pickup_code"] = password_match.group(1)
+                            else:
+                                result["pickup_code"] = None
                 else:
-                    result["pickup_code"] = None
+                    # 对于其他快递,保持原有逻辑
+                    parts = code.split("-")
+                    valid_parts = []
+                    for part in parts:
+                        if part and any(c.isalnum() for c in part):
+                            valid_parts.append(part)
+                    
+                    if valid_parts:
+                        result["pickup_code"] = "-".join(valid_parts)
+                    else:
+                        result["pickup_code"] = None
 
             # 清理公司名称
             if result["company"]:
@@ -480,7 +530,16 @@
                 for word in invalid_words:
                     if company.endswith(word):
                         company = company[:-len(word)]
+                
+                # 特殊处理中国邮政
+                if company == "中国" and "中国邮政" in text:
+                    company = "邮政"
+                elif "中国邮政" in text and not company:
+                    company = "邮政"
+                
                 result["company"] = company.strip()
+            elif "中国邮政" in text:  # 如果NER未识别但文本中有中国邮政
+                result["company"] = "邮政"
 
             # 清理地址
             if result["address"]:
@@ -623,7 +682,8 @@
                 
                 # 尝试查找最低还款金额
                 min_amount_match = re.search(r'最低还款([\d,]+\.?\d*)(?:元|块钱|块|万元|万)?', context)
-                if min_amount_match and "MIN_CODE" in current_entity["type"]:
+                # 修复:确保current_entity存在且有type属性再使用
+                if min_amount_match and 'current_entity' in locals() and current_entity is not None and "MIN_CODE" in current_entity["type"]:
                     return min_amount_match.group(1)  # 直接返回匹配到的最低还款金额,保留原始格式
                     
                 # 在上下文中查找完整金额
@@ -1360,6 +1420,103 @@
         # 保存原始短信内容到文件
         save_sms_to_file(text)
             
+        # 已还清或已结清的短信模式
+        already_paid_patterns = [
+            r"已还清",
+            r"已结清",
+            r"还款.*?入账后.*?已还清",
+            r"还款.*?入账.*?结清"
+        ]
+        
+        # 检查是否为已还清/已结清的短信
+        for pattern in already_paid_patterns:
+            if re.search(pattern, text):
+                logger.info(f"识别为已还清/已结清短信,归类为其他: {text[:30]}...")
+                category = "其他"
+                save_sms_to_file(text, category, 1.0)
+                return jsonify({
+                    "status": "success",
+                    "data": {
+                        "category": category,
+                        "details": {}
+                    }
+                })
+            
+        # 银行收入短信特征识别
+        income_patterns = [
+            r"收入金额[\d,.]+元",
+            r"账户.*?收入.*?[\d,.]+元",
+            r"账户.*?工资",
+            r"工资.*?收入",
+            r"入账[\d,.]+元",
+            # 添加新模式匹配南京银行等类似格式
+            r"收入\d+\.\d+元",
+            r"账号.*?收入\d+\.\d+元",
+            r"尾号\d+的账号.*?收入\d+\.\d+元",
+            r"支付宝转账",
+            r"转账.*?收入"
+        ]
+        
+        # 银行还款短信特征识别
+        repayment_patterns = [
+            r"信用卡.*?还款",
+            r"账单.*?[\d,.]+元",
+            r"应还款额.*?[\d,.]+元",
+            r"最低还款额.*?[\d,.]+元",
+            r"到期还款日",
+            r"扣款.*?用于.*?还款",
+            r"扣款.*?用于.*?贷款",
+            r"扣款.*?用于.*?信用卡",
+            r"车贷还款",
+            r"房贷还款",
+            r"贷款还款",
+            r"信用卡账单",
+            r"下次还款日"
+        ]
+        
+        # 检查是否为收入短信
+        for pattern in income_patterns:
+            if re.search(pattern, text):
+                logger.info(f"识别为收入短信: {text[:30]}...")
+                category = "收入"
+                details = model_manager.extract_income_entities(text)
+                save_sms_to_file(text, category, 1.0)
+                return jsonify({
+                    "status": "success",
+                    "data": {
+                        "category": category,
+                        "details": details
+                    }
+                })
+        
+        # 检查是否为还款短信
+        for pattern in repayment_patterns:
+            if re.search(pattern, text):
+                # 二次检查:如果包含"已还清"或"已结清"等词,归类为"其他"
+                if any(re.search(paid_pattern, text) for paid_pattern in already_paid_patterns):
+                    logger.info(f"虽然识别为还款短信,但包含已还清/已结清,归类为其他: {text[:30]}...")
+                    category = "其他"
+                    save_sms_to_file(text, category, 1.0)
+                    return jsonify({
+                        "status": "success",
+                        "data": {
+                            "category": category,
+                            "details": {}
+                        }
+                    })
+                
+                logger.info(f"识别为还款短信: {text[:30]}...")
+                category = "还款"
+                details = model_manager.extract_repayment_entities(text)
+                save_sms_to_file(text, category, 1.0)
+                return jsonify({
+                    "status": "success",
+                    "data": {
+                        "category": category,
+                        "details": details
+                    }
+                })
+        
         # 特定短信识别逻辑 - 针对百度通知和招商银行账单
         # 识别百度通知
         if "百度智能云" in text and "尊敬的用户" in text and "免费额度" in text:
@@ -1376,6 +1533,19 @@
         
         # 识别招商银行账单
         if "招商银行" in text and ("账单¥" in text or "账单¥" in text or "还款日" in text):
+            # 检查是否为已还清/已结清短信
+            if any(re.search(paid_pattern, text) for paid_pattern in already_paid_patterns):
+                logger.info(f"招商银行短信包含已还清/已结清,归类为其他: {text[:30]}...")
+                category = "其他"
+                save_sms_to_file(text, category, 1.0)
+                return jsonify({
+                    "status": "success",
+                    "data": {
+                        "category": category,
+                        "details": {}
+                    }
+                })
+                
             logger.info(f"直接识别为招商银行还款短信: {text[:30]}...")
             category = "还款"
             details = model_manager.extract_repayment_entities(text)
diff --git a/test2.py b/test2.py
index aec0dcb..d8105ab 100644
--- a/test2.py
+++ b/test2.py
@@ -17,7 +17,8 @@
 
 def generate_xiaohongshu_article(film_name, locations):
     """生成小红书风格的文章"""
-    prompt = f"""请为电影《{film_name}》的拍摄地写一篇小红书风格的文章。要求:
+    try:
+        prompt = f"""请为电影《{film_name}》的拍摄地写一篇小红书风格的文章。要求:
 1. 标题要吸引人,包含电影名称和拍摄地
 2. 开头要吸引人,可以用电影中的经典台词或场景引入
 3. 详细介绍每个拍摄地点的特色和亮点
@@ -28,19 +29,23 @@
 
 请以html格式返回,包含标题、正文和标签.生成内容字体要符合在小程序上合适的大小阅读,标题不要超过h3。"""
 
-    completion = client.chat.completions.create(
-        model="bot-20250512103613-6rwj8",
-        messages=[
-            {"role": "system", "content": "你是一个专业的小红书文案写手,擅长写吸引人的旅游攻略。"},
-            {"role": "user", "content": prompt},
-        ],
-    )
-    
-    return completion.choices[0].message.content
+        completion = client.chat.completions.create(
+            model="bot-20250512103613-6rwj8",
+            messages=[
+                {"role": "system", "content": "你是一个专业的小红书文案写手,擅长写吸引人的旅游攻略。"},
+                {"role": "user", "content": prompt},
+            ],
+        )
+        
+        return completion.choices[0].message.content
+    except Exception as e:
+        print(f"生成小红书文章失败: {str(e)}")
+        return ""
 
 def generate_travel_route(film_name, locations):
     """生成游玩路线"""
-    prompt = f"""请为电影《{film_name}》的拍摄地设计一条最优游玩路线。要求:
+    try:
+        prompt = f"""请为电影《{film_name}》的拍摄地设计一条最优游玩路线。要求:
 1. 考虑各个景点之间的距离和交通方式
 2. 合理安排游览顺序,避免来回奔波
 3. 预估每个景点的游览时间
@@ -68,26 +73,30 @@
     ]
 }}"""
 
-    completion = client.chat.completions.create(
-        model="bot-20250512103613-6rwj8",
-        messages=[
-            {"role": "system", "content": "你是一个专业的旅游路线规划师,擅长设计最优游览路线。"},
-            {"role": "user", "content": prompt},
-        ],
-    )
-    
-    try:
-        response_text = completion.choices[0].message.content
-        cleaned_text = re.sub(r'```json|```', '', response_text)
-        cleaned_text = re.sub(r'^[^{[]*', '', cleaned_text)
-        return json.loads(cleaned_text)
+        completion = client.chat.completions.create(
+            model="bot-20250512103613-6rwj8",
+            messages=[
+                {"role": "system", "content": "你是一个专业的旅游路线规划师,擅长设计最优游览路线。"},
+                {"role": "user", "content": prompt},
+            ],
+        )
+        
+        try:
+            response_text = completion.choices[0].message.content
+            cleaned_text = re.sub(r'```json|```', '', response_text)
+            cleaned_text = re.sub(r'^[^{[]*', '', cleaned_text)
+            return json.loads(cleaned_text)
+        except Exception as e:
+            print(f"解析路线失败: {str(e)}\n原始响应: {response_text}")
+            return None
     except Exception as e:
-        print(f"解析路线失败: {str(e)}\n原始响应: {response_text}")
+        print(f"生成游玩路线失败: {str(e)}")
         return None
 
 def generate_xiaohongshu_route(film_name, locations):
     """生成小红书风格的路线攻略"""
-    prompt = f"""请为电影《{film_name}》的拍摄地写一篇小红书风格的路线攻略。要求:
+    try:
+        prompt = f"""请为电影《{film_name}》的拍摄地写一篇小红书风格的路线攻略。要求:
 1. 标题要吸引人,突出"最佳路线"或"完美行程"等关键词
 2. 开头要说明这条路线是如何规划的,为什么这样安排
 3. 详细介绍每个景点的游览时间和交通方式
@@ -99,27 +108,37 @@
 
 请以html格式返回,包含标题、正文和标签,生成内容字体要符合在小程序上合适的大小阅读,标题不要超过h3。"""
 
-    completion = client.chat.completions.create(
-        model="bot-20250512103613-6rwj8",
-        messages=[
-            {"role": "system", "content": "你是一个专业的小红书文案写手,擅长写吸引人的旅游路线攻略。"},
-            {"role": "user", "content": prompt},
-        ],
-    )
-    
-    return completion.choices[0].message.content
+        completion = client.chat.completions.create(
+            model="bot-20250512103613-6rwj8",
+            messages=[
+                {"role": "system", "content": "你是一个专业的小红书文案写手,擅长写吸引人的旅游路线攻略。"},
+                {"role": "user", "content": prompt},
+            ],
+        )
+        
+        return completion.choices[0].message.content
+    except Exception as e:
+        print(f"生成小红书路线攻略失败: {str(e)}")
+        return ""
 
 def get_film_works():
-    url = "http://192.168.1.213:8090/flower/api/filmWorks/pending/create"
-    response = requests.get(url)
-    if response.status_code == 200:
-        return response.json().get("data", [])
-    return []
+    try:
+        url = "http://192.168.1.213:8090/flower/api/filmWorks/pending/create"
+        response = requests.get(url)
+        if response.status_code == 200:
+            return response.json().get("data", [])
+        else:
+            print(f"获取电影作品失败,状态码: {response.status_code}")
+            return []
+    except Exception as e:
+        print(f"获取电影作品失败: {str(e)}")
+        return []
 
 
 def get_location_info_from_model(film_name):
     """使用模型获取多个拍摄地点信息"""
-    prompt = f"""请为电影《{film_name}》生成所有主要拍摄地点的详细信息。每部电影通常有多个拍摄地点,请尽可能详细地列出所有重要的拍摄地点。
+    try:
+        prompt = f"""请为电影《{film_name}》生成所有主要拍摄地点的详细信息。每部电影通常有多个拍摄地点,请尽可能详细地列出所有重要的拍摄地点。
 
 对于每个拍摄地点,请提供以下信息:
 1. 拍摄地点名称
@@ -156,165 +175,203 @@
 ]
 
 请确保返回所有重要的拍摄地点,每个地点都要包含完整的信息。"""
-    # Non-streaming:
-    print("----- standard request -----")
-    completion = client.chat.completions.create(
-        model="bot-20250512103613-6rwj8",  # bot-20250512103613-6rwj8 为您当前的智能体的ID,注意此处与Chat API存在差异。差异对比详见 SDK使用指南
-        # messages=[
-        #     {"role": "system", "content": "你是DeepSeek,是一个 AI 人工智能助手"},
-        #     {"role": "user", "content": "常见的十字花科植物有哪些?"},
-        # ],
-        messages=[
-            {"role": "system",
-             "content": "你是一个专业的影视拍摄地点信息专家,请根据电影名称生成所有重要拍摄地点的详细信息。"},
-            {"role": "user", "content": prompt},
-        ],
-    )
-    print(completion.choices[0].message.content)
-    if hasattr(completion, "references"):
-        print(completion.references)
-    if hasattr(completion.choices[0].message, "reasoning_content"):
-        print(completion.choices[0].message.reasoning_content)  # 对于R1模型,输出reasoning content
-    # try:
-    #     # 尝试解析模型返回的JSON
-    #     response_text = completion.choices[0].message.content
-    #     location_info_list = json.loads(response_text)
-    #     return location_info_list
-    # except:
-    #     # 如果解析失败,返回默认值
-    #     return None
-        try:
-            response_text = completion.choices[0].message.content
-            # 清理响应内容
-            cleaned_text = re.sub(r'```json|```', '', response_text)  # 移除Markdown标记
-            cleaned_text = re.sub(r'^[^{[]*', '', cleaned_text)  # 清理开头非JSON内容
+        # Non-streaming:
+        print("----- standard request -----")
+        completion = client.chat.completions.create(
+            model="bot-20250512103613-6rwj8",  # bot-20250512103613-6rwj8 为您当前的智能体的ID,注意此处与Chat API存在差异。差异对比详见 SDK使用指南
+            # messages=[
+            #     {"role": "system", "content": "你是DeepSeek,是一个 AI 人工智能助手"},
+            #     {"role": "user", "content": "常见的十字花科植物有哪些?"},
+            # ],
+            messages=[
+                {"role": "system",
+                 "content": "你是一个专业的影视拍摄地点信息专家,请根据电影名称生成所有重要拍摄地点的详细信息。"},
+                {"role": "user", "content": prompt},
+            ],
+        )
+        print(completion.choices[0].message.content)
+        if hasattr(completion, "references"):
+            print(completion.references)
+        if hasattr(completion.choices[0].message, "reasoning_content"):
+            print(completion.choices[0].message.reasoning_content)  # 对于R1模型,输出reasoning content
+        # try:
+        #     # 尝试解析模型返回的JSON
+        #     response_text = completion.choices[0].message.content
+        #     location_info_list = json.loads(response_text)
+        #     return location_info_list
+        # except:
+        #     # 如果解析失败,返回默认值
+        #     return None
+            try:
+                response_text = completion.choices[0].message.content
+                # 清理响应内容
+                cleaned_text = re.sub(r'```json|```', '', response_text)  # 移除Markdown标记
+                cleaned_text = re.sub(r'^[^{[]*', '', cleaned_text)  # 清理开头非JSON内容
 
-            # 解析
-            location_info_list = json.loads(cleaned_text)
-            return location_info_list
-        except Exception as e:
-            print(f"解析失败: {str(e)}\n原始响应: {response_text}")
-            return None
+                # 解析
+                location_info_list = json.loads(cleaned_text)
+                return location_info_list
+            except Exception as e:
+                print(f"解析失败: {str(e)}\n原始响应: {response_text}")
+                return None
+    except Exception as e:
+        print(f"获取拍摄地点信息失败: {str(e)}")
+        return None
 
 
 def create_film_location(film_id, film_name, location_info, article, route_article):
-    url = "http://192.168.1.213:8090/flower/api/filmLocation/new"
+    try:
+        url = "http://192.168.1.213:8090/flower/api/filmLocation/new"
 
-    # 默认值设置
-    default_data = {
-        "filmId": film_id,
-        "locationName": f"{film_name}拍摄地",
-        "address": "待补充",
-        "gpsLat": 0.0,
-        "gpsLng": 0.0,
-        "startDate": datetime.now().strftime("%Y-%m-%d"),
-        "endDate": datetime.now().strftime("%Y-%m-%d"),
-        "sceneType": "外景",
-        "classicScene": "待补充",
-        "isOpenVisit": 0,
-        "visitInfo": json.dumps({"tips": "暂无参观信息"}),
-        "landmarkDesc": "待补充",
-        "transportGuide": "待补充",
-        "parkingInfo": "待补充",
-        "surroundingFacilities": "待补充",
-        "arEntry": "",
-        "status": 1,
-        "deleted": 0,
-        "createBy": "system",
-        "updateBy": "system",
-        "checkinCount": 0,
-        "visitorPhotos": json.dumps([]),
-        "xiaohongshuArticle": article,  # 新增:小红书风格文章
-        "xiaohongshuRoute": route_article  # 新增:小红书风格路线
-    }
+        # 默认值设置
+        default_data = {
+            "filmId": film_id,
+            "locationName": f"{film_name}拍摄地",
+            "address": "待补充",
+            "gpsLat": 0.0,
+            "gpsLng": 0.0,
+            "startDate": datetime.now().strftime("%Y-%m-%d"),
+            "endDate": datetime.now().strftime("%Y-%m-%d"),
+            "sceneType": "外景",
+            "classicScene": "待补充",
+            "isOpenVisit": 0,
+            "visitInfo": json.dumps({"tips": "暂无参观信息"}),
+            "landmarkDesc": "待补充",
+            "transportGuide": "待补充",
+            "parkingInfo": "待补充",
+            "surroundingFacilities": "待补充",
+            "arEntry": "",
+            "status": 1,
+            "deleted": 0,
+            "createBy": "system",
+            "updateBy": "system",
+            "checkinCount": 0,
+            "visitorPhotos": json.dumps([]),
+            "xiaohongshuArticle": article,  # 新增:小红书风格文章
+            "xiaohongshuRoute": route_article  # 新增:小红书风格路线
+        }
 
-    # 更新默认值
-    if location_info:
-        for key, value in location_info.items():
-            if key in default_data:
-                if key in ['visit_info', 'visitor_photos']:
-                    default_data[key] = json.dumps(value)
-                else:
-                    default_data[key] = value
+        # 更新默认值
+        if location_info:
+            for key, value in location_info.items():
+                if key in default_data:
+                    if key in ['visit_info', 'visitor_photos']:
+                        default_data[key] = json.dumps(value)
+                    else:
+                        default_data[key] = value
 
-    response = requests.post(url, json=default_data)
-    return response.json()
+        response = requests.post(url, json=default_data)
+        return response.json()
+    except Exception as e:
+        print(f"创建拍摄地点失败: {str(e)}")
+        return {"error": str(e)}
 
 def save_article_and_route(film_id, film_name, article, route, route_article):
     """保存文章和路线到文件"""
-    # 创建输出目录
-    output_dir = "output"
-    if not os.path.exists(output_dir):
-        os.makedirs(output_dir)
-    
-    # 保存文章
-    article_file = os.path.join(output_dir, f"{film_name}_article.md")
-    with open(article_file, "w", encoding="utf-8") as f:
-        f.write(article)
-    
-    # 保存路线(JSON格式)
-    route_file = os.path.join(output_dir, f"{film_name}_route.json")
-    with open(route_file, "w", encoding="utf-8") as f:
-        json.dump(route, f, ensure_ascii=False, indent=2)
-    
-    # 保存路线(小红书风格)
-    route_article_file = os.path.join(output_dir, f"{film_name}_route_article.md")
-    with open(route_article_file, "w", encoding="utf-8") as f:
-        f.write(route_article)
+    try:
+        # 创建输出目录
+        output_dir = "output"
+        if not os.path.exists(output_dir):
+            os.makedirs(output_dir)
+        
+        # 保存文章
+        article_file = os.path.join(output_dir, f"{film_name}_article.md")
+        with open(article_file, "w", encoding="utf-8") as f:
+            f.write(article if article else "文章生成失败")
+        
+        # 保存路线(JSON格式)
+        route_file = os.path.join(output_dir, f"{film_name}_route.json")
+        with open(route_file, "w", encoding="utf-8") as f:
+            if route:
+                json.dump(route, f, ensure_ascii=False, indent=2)
+            else:
+                json.dump({"error": "路线生成失败"}, f, ensure_ascii=False, indent=2)
+        
+        # 保存路线(小红书风格)
+        route_article_file = os.path.join(output_dir, f"{film_name}_route_article.md")
+        with open(route_article_file, "w", encoding="utf-8") as f:
+            f.write(route_article if route_article else "路线文章生成失败")
+    except Exception as e:
+        print(f"保存文件失败: {str(e)}")
 
 def main():
     # 获取所有电影作品
-    film_works = get_film_works()
+    try:
+        film_works = get_film_works()
+    except Exception as e:
+        print(f"获取电影作品失败: {str(e)}")
+        return
 
     # 为每个电影作品创建拍摄地点
     for film in film_works:
-        film_name = film.get("nameCn")
-        film_id = film.get("id")
-        if film_name:
-            print(f"正在处理电影: {film_name}")
+        try:
+            film_name = film.get("nameCn")
+            film_id = film.get("id")
+            if film_name:
+                print(f"正在处理电影: {film_name}")
 
-            # 获取所有拍摄地点信息
-            location_info_list = get_location_info_from_model(film_name)
+                # 获取所有拍摄地点信息
+                location_info_list = get_location_info_from_model(film_name)
 
-            if location_info_list:
                 # 生成小红书文章
                 article = generate_xiaohongshu_article(film_name, location_info_list)
                 # 清理文章中的HTML标记
-                article = re.sub(r'```html|```', '', article)
-                print(f"\n生成的文章:\n{article}")
+                if article:
+                    article = re.sub(r'```html|```', '', article)
+                    print(f"\n生成的文章:\n{article}")
+                else:
+                    print("文章生成失败,使用空内容")
                 
                 # 生成游玩路线(JSON格式)
                 route = generate_travel_route(film_name, location_info_list)
-                print(f"\n生成的路线:\n{json.dumps(route, ensure_ascii=False, indent=2)}")
+                if route:
+                    print(f"\n生成的路线:\n{json.dumps(route, ensure_ascii=False, indent=2)}")
+                else:
+                    print("路线生成失败,使用空内容")
                 
                 # 生成小红书风格路线
                 route_article = generate_xiaohongshu_route(film_name, location_info_list)
                 # 清理路线文章中的HTML标记
-                route_article = re.sub(r'```html|```', '', route_article)
-                print(f"\n生成的路线文章:\n{route_article}")
+                if route_article:
+                    route_article = re.sub(r'```html|```', '', route_article)
+                    print(f"\n生成的路线文章:\n{route_article}")
+                else:
+                    print("路线文章生成失败,使用空内容")
                 
                 # 合并文章和路线
                 combined_content = f"{article}\n\n{route_article}"
                 
                 # 保存到新接口
-                save_url = "http://192.168.1.213:8090/flower/api/filmWorks/edit"
-                save_data = {
-                    "id": film_id,
-                    "type": "sys",
-                    "filmContent": combined_content
-                }
-                save_response = requests.post(save_url, json=save_data)
-                print(f"保存到新接口结果: {save_response.json()}")
+                try:
+                    save_url = "http://192.168.1.213:8090/flower/api/filmWorks/edit"
+                    save_data = {
+                        "id": film_id,
+                        "type": "sys",
+                        "filmContent": combined_content
+                    }
+                    save_response = requests.post(save_url, json=save_data)
+                    print(f"保存到新接口结果: {save_response.json()}")
+                except Exception as e:
+                    print(f"保存到新接口失败: {str(e)}")
                 
                 # 为每个拍摄地点创建记录
-                for location_info in location_info_list:
-                    result = create_film_location(film_id, film_name, location_info, article, route_article)
-                    print(f"创建拍摄地点 {location_info.get('locationName', '未知地点')} 结果: {result}")
+                if location_info_list:
+                    for location_info in location_info_list:
+                        result = create_film_location(film_id, film_name, location_info, article, route_article)
+                        print(f"创建拍摄地点 {location_info.get('locationName', '未知地点')} 结果: {result}")
+                else:
+                    print("没有拍摄地点信息,跳过创建拍摄地点记录")
                 
                 # 保存文章和路线到文件
-                save_article_and_route(film_id, film_name, article, route, route_article)
+                try:
+                    save_article_and_route(film_id, film_name, article, route, route_article)
+                except Exception as e:
+                    print(f"保存文件失败: {str(e)}")
             else:
-                print(f"未能获取到电影 {film_name} 的拍摄地点信息")
+                print(f"电影名称为空,跳过处理")
+        except Exception as e:
+            print(f"处理电影 {film.get('nameCn', '未知电影')} 时发生错误: {str(e)}")
+            continue
 
 
 if __name__ == "__main__":

--
Gitblit v1.9.3