cloudroam
2 天以前 4992631aef19d7f644cbcd6cd5e37dde37c6e149
add:增加对外接口
已修改4个文件
326 ■■■■ 文件已修改
app.py 55 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
douban.py 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
douban_tv.py 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
test2.py 258 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app.py
@@ -10,6 +10,11 @@
from werkzeug.exceptions import BadRequest
from ner_config import NERConfig, RepaymentNERConfig, IncomeNERConfig, FlightNERConfig, TrainNERConfig
import re
import threading
import subprocess
from test2 import process_films
# 配置日志
logging.basicConfig(
@@ -1681,5 +1686,55 @@
            "message": "服务器内部错误"
        }), 500
def run_douban_spider(type_, tag):
    subprocess.run(
        ["python", "douban.py", type_, tag],
        capture_output=True,
        text=True
    )
def run_process_films():
    try:
        process_films()
    except Exception as e:
        logger.error(f"处理电影内容失败: {str(e)}")
@app.route("/crawl-douban", methods=["POST"])
def crawl_douban():
    try:
        default_params = {"type": "tv", "tag": "热门"}
        # 尝试解析 JSON,失败则使用默认值
        # 先检查 Content-Type 和数据结构
        if request.is_json:
            params = request.get_json()
            if not isinstance(params, dict):  # 确保是字典类型
                params = default_params
        else:
            params = default_params
        # 获取参数(带默认值)
        type_ = params.get("type", default_params["type"])
        tag = params.get("tag", default_params["tag"])
        # 打印接收到的参数(调试用)
        print(f"Received params - type: {type_}, tag: {tag}")
        # 启动线程异步执行爬虫
        t = threading.Thread(target=run_douban_spider, args=(type_, tag))
        t.start()
        return jsonify({"status": "success", "message": "爬虫任务已启动", "type": type_, "tag": tag})
    except Exception as e:
        return jsonify({"status": "error", "message": str(e)}), 500
@app.route('/generate-film-content', methods=['POST'])
def generate_film_content_api():
    """生成电影内容接口"""
    try:
           threading.Thread(target=run_process_films).start()
           return jsonify({"status": "accepted", "message": "任务已异步启动"})
    except Exception as e:
         return jsonify({"status": "error", "message": str(e)}), 500
if __name__ == "__main__":
    app.run(host="0.0.0.0", port=5000)
douban.py
@@ -1,7 +1,16 @@
from douban_tv import DoubanTVSpider
from scrapy.crawler import CrawlerProcess
import sys
if __name__ == "__main__":
    # 获取命令行参数
    type_ = "tv"
    tag = "热门"
    if len(sys.argv) > 1:
        type_ = sys.argv[1]
    if len(sys.argv) > 2:
        tag = sys.argv[2]
    process = CrawlerProcess(settings={
        "USER_AGENT": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/112.0.0.0 Safari/537.36",
        "DOWNLOAD_DELAY": 2,
@@ -9,5 +18,5 @@
        "ROBOTSTXT_OBEY": False,
        "LOG_LEVEL": "INFO"
    })
    process.crawl(DoubanTVSpider)
    process.crawl(DoubanTVSpider, type_=type_, tag=tag)
    process.start()
douban_tv.py
@@ -127,7 +127,7 @@
        # 发送数据到API
        try:
            response = requests.post(
                'http://192.168.1.213:8080/flower/api/filmWorks/new',
                'http://14.103.144.28:8090/flower/api/filmWorks/new',
                json=api_data,
                headers={'Content-Type': 'application/json'}
            )
test2.py
@@ -14,21 +14,164 @@
    api_key="5017c24f-581f-48fb-abef-8ac4654e9018",  # 直接填写密钥
)
DEFAULT_PROMPTS = {
    "promptArticle": """请为电影《{film_name}》的拍摄地写一篇小红书风格的文章要求:
                    1. 标题要吸引人,包含电影名称和拍摄地
                    2. 开头要吸引人,可以用电影中的经典台词或场景引入
                    3. 详细介绍每个拍摄地点的特色和亮点
                    4. 包含实用的参观建议和交通信息
                    5. 使用emoji表情增加趣味性
                    6. 最后要有总结和推荐
                    7. 添加相关标签
                    请以html格式返回,包含标题、正文和标签.生成内容字体要符合在小程序上合适的大小阅读,标题不要超过h3。""",
    "promptRoute": """请为电影《{film_name}》的拍摄地设计一条最优游玩路线。要求:
                   1. 考虑各个景点之间的距离和交通方式
                   2. 合理安排游览顺序,避免来回奔波
                   3. 预估每个景点的游览时间
                   4. 提供具体的交通建议
                   5. 考虑用餐和休息时间
                   6. 提供备选方案
                   请以JSON格式返回,格式如下:
                   {{
                       "route_name": "路线名称",
                       "total_time": "预计总时间",
                       "stops": [
                           {{
                               "location_name": "地点名称",
                               "visit_time": "建议游览时间",
                               "transportation": "前往下一个地点的交通方式",
                               "tips": "游览建议"
                           }}
                       ],
                       "alternative_routes": [
                           {{
                               "route_name": "备选路线名称",
                               "description": "路线说明"
                           }}
                       ]
                   }}""",
    "promptTravel": """请为电影《{film_name}》的拍摄地写一篇小红书风格的路线攻略要求:
                 1. 标题要吸引人,突出"最佳路线"或"完美行程"等关键词
                 2. 开头要说明这条路线是如何规划的,为什么这样安排
                 3. 详细介绍每个景点的游览时间和交通方式
                 4. 使用emoji表情增加趣味性
                 5. 提供实用的时间安排建议
                 6. 包含备选路线方案
                 7. 最后要有总结和注意事项
                 8. 添加相关标签
                 请以html格式返回,包含标题、正文和标签,生成内容字体要符合在小程序上合适的大小阅读,标题不要超过h3。""",
    "promptLocation": """请为电影《{film_name}》生成所有主要拍摄地点细信息。每部电影通常有多个拍摄地点,请尽可能详细地列出所有重要的拍摄地点。
                对于每个拍摄地点,请提供以下信息:
                1. 拍摄地点名称
                2. 详细地址
                3. 场景类型
                4. 经典画面描述
                5. 是否开放参观
                6. 参观提示
                7. 地标性建筑描述
                8. 交通指引说明
                9. 停车场信息
                10. 周边设施描述
                请以JSON数组格式返回,格式如下:
                [
                    {{
                        "locationName": "地点1名称",
                        "address": "地点1详细地址",
                        "gpsLat": "纬度坐标(精确到小数点后6位)",
                        "gpsLng": "经度坐标(精确到小数点后6位)",
                        "sceneType": "场景类型",
                        "classicScene": "经典画面描述",
                        "isOpenVisit": 0或1,
                        "visitInfo": "参观提示",
                        "landmarkDesc": "地标描述",
                        "transportGuide": "交通指引",
                        "parkingInfo": "停车信息",
                        "surroundingFacilities": "周边设施"
                    }},
                    {{
                        "locationName": "地点2名称",
                        ...
                    }}
                ]
                请确保返回所有重要的拍摄地点,每个地点都要包含完整的信息。"""
}
def get_ai_task_config():
    """从API获取AI任务配置,保留原始HTML内容"""
    try:
        # 设置请求超时时间
        response = requests.get(
            "http://14.103.144.28:8090/flower/api/aiTaskConfig/all",
            timeout=100
        )
        # 检查HTTP状态码
        response.raise_for_status()
        # 解析JSON响应
        response_data = response.json()
        # 验证响应结构
        if response_data.get("code") != "0" or not isinstance(response_data.get("data"), list):
            print(f"无效的API响应结构: {response_data}")
            return {}
        config_list = response_data["data"]
        # 返回第一条有效配置(保留原始HTML内容)
        if config_list:
            return {
                "promptArticle": config_list[0].get("promptArticle", ""),
                "promptRoute": config_list[0].get("promptRoute", ""),
                "promptTravel": config_list[0].get("promptTravel", ""),
                "promptLocation": config_list[0].get("promptLocation", "")  # 注意字段名拼写差异
            }
        return {}
    except requests.exceptions.RequestException as e:
        print(f"请求AI任务配置失败: {str(e)}")
        return {}
    except json.JSONDecodeError as e:
        print(f"解析API响应JSON失败: {str(e)}")
        return {}
    except Exception as e:
        print(f"获取AI任务配置发生未知错误: {str(e)}")
        return {}
def get_prompt(prompt_type):
    """获取指定类型的提示模板
    参数:
        prompt_type: 提示类型,必须是DEFAULT_PROMPTS中定义的键
    返回:
        从API获取的提示模板,如果为空则返回默认模板
    """
    # 验证输入参数
    if prompt_type not in DEFAULT_PROMPTS:
        raise ValueError(f"无效的prompt类型: {prompt_type}")
    # 获取配置
    config = get_ai_task_config()
    # 获取指定类型的提示,确保内容非空
#     custom_prompt = config.get(prompt_type, "").strip()
    custom_prompt = config.get(prompt_type)
    # 更严格的空值检查
    if custom_prompt is not None and str(custom_prompt).strip():
        return str(custom_prompt).strip()
    # 返回有效的提示模板
    return custom_prompt if custom_prompt else DEFAULT_PROMPTS[prompt_type]
def generate_xiaohongshu_article(film_name, locations):
    """生成小红书风格的文章"""
    prompt = get_prompt("promptArticle").format(film_name=film_name)
    try:
        prompt = f"""请为电影《{film_name}》的拍摄地写一篇小红书风格的文章。要求:
1. 标题要吸引人,包含电影名称和拍摄地
2. 开头要吸引人,可以用电影中的经典台词或场景引入
3. 详细介绍每个拍摄地点的特色和亮点
4. 包含实用的参观建议和交通信息
5. 使用emoji表情增加趣味性
6. 最后要有总结和推荐
7. 添加相关标签
请以html格式返回,包含标题、正文和标签.生成内容字体要符合在小程序上合适的大小阅读,标题不要超过h3。"""
        completion = client.chat.completions.create(
            model="bot-20250512103613-6rwj8",
            messages=[
@@ -44,35 +187,8 @@
def generate_travel_route(film_name, locations):
    """生成游玩路线"""
    prompt = get_prompt("promptRoute").format(film_name=film_name)
    try:
        prompt = f"""请为电影《{film_name}》的拍摄地设计一条最优游玩路线。要求:
1. 考虑各个景点之间的距离和交通方式
2. 合理安排游览顺序,避免来回奔波
3. 预估每个景点的游览时间
4. 提供具体的交通建议
5. 考虑用餐和休息时间
6. 提供备选方案
请以JSON格式返回,格式如下:
{{
    "route_name": "路线名称",
    "total_time": "预计总时间",
    "stops": [
        {{
            "location_name": "地点名称",
            "visit_time": "建议游览时间",
            "transportation": "前往下一个地点的交通方式",
            "tips": "游览建议"
        }}
    ],
    "alternative_routes": [
        {{
            "route_name": "备选路线名称",
            "description": "路线说明"
        }}
    ]
}}"""
        completion = client.chat.completions.create(
            model="bot-20250512103613-6rwj8",
            messages=[
@@ -95,18 +211,8 @@
def generate_xiaohongshu_route(film_name, locations):
    """生成小红书风格的路线攻略"""
    prompt = get_prompt("promptTravel").format(film_name=film_name)
    try:
        prompt = f"""请为电影《{film_name}》的拍摄地写一篇小红书风格的路线攻略。要求:
1. 标题要吸引人,突出"最佳路线"或"完美行程"等关键词
2. 开头要说明这条路线是如何规划的,为什么这样安排
3. 详细介绍每个景点的游览时间和交通方式
4. 使用emoji表情增加趣味性
5. 提供实用的时间安排建议
6. 包含备选路线方案
7. 最后要有总结和注意事项
8. 添加相关标签
请以html格式返回,包含标题、正文和标签,生成内容字体要符合在小程序上合适的大小阅读,标题不要超过h3。"""
        completion = client.chat.completions.create(
            model="bot-20250512103613-6rwj8",
@@ -123,7 +229,7 @@
def get_film_works():
    try:
        url = "http://192.168.1.213:8090/flower/api/filmWorks/pending/create"
        url = "http://14.103.144.28:8090/flower/api/filmWorks/pending/create"
        response = requests.get(url)
        if response.status_code == 200:
            return response.json().get("data", [])
@@ -137,44 +243,8 @@
def get_location_info_from_model(film_name):
    """使用模型获取多个拍摄地点信息"""
    prompt = get_prompt("promptLocation").format(film_name=film_name)
    try:
        prompt = f"""请为电影《{film_name}》生成所有主要拍摄地点的详细信息。每部电影通常有多个拍摄地点,请尽可能详细地列出所有重要的拍摄地点。
对于每个拍摄地点,请提供以下信息:
1. 拍摄地点名称
2. 详细地址
3. 场景类型
4. 经典画面描述
5. 是否开放参观
6. 参观提示
7. 地标性建筑描述
8. 交通指引说明
9. 停车场信息
10. 周边设施描述
请以JSON数组格式返回,格式如下:
[
    {{
        "locationName": "地点1名称",
        "address": "地点1详细地址",
        "gpsLat": "纬度坐标(精确到小数点后6位)",
        "gpsLng": "经度坐标(精确到小数点后6位)",
        "sceneType": "场景类型",
        "classicScene": "经典画面描述",
        "isOpenVisit": 0或1,
        "visitInfo": "参观提示",
        "landmarkDesc": "地标描述",
        "transportGuide": "交通指引",
        "parkingInfo": "停车信息",
        "surroundingFacilities": "周边设施"
    }},
    {{
        "locationName": "地点2名称",
        ...
    }}
]
请确保返回所有重要的拍摄地点,每个地点都要包含完整的信息。"""
        # Non-streaming:
        print("----- standard request -----")
        completion = client.chat.completions.create(
@@ -221,7 +291,7 @@
def create_film_location(film_id, film_name, location_info, article, route_article):
    try:
        url = "http://192.168.1.213:8090/flower/api/filmLocation/new"
        url = "http://14.103.144.28:8090/flower/api/filmLocation/new"
        # 默认值设置
        default_data = {
@@ -294,7 +364,7 @@
    except Exception as e:
        print(f"保存文件失败: {str(e)}")
def main():
def process_films():
    # 获取所有电影作品
    try:
        film_works = get_film_works()
@@ -343,7 +413,7 @@
                
                # 保存到新接口
                try:
                    save_url = "http://192.168.1.213:8090/flower/api/filmWorks/edit"
                    save_url = "http://14.103.144.28:8090/flower/api/filmWorks/edit"
                    save_data = {
                        "id": film_id,
                        "type": "sys",
@@ -373,6 +443,8 @@
            print(f"处理电影 {film.get('nameCn', '未知电影')} 时发生错误: {str(e)}")
            continue
def main():
   process_films()
if __name__ == "__main__":
    main()
# if __name__ == "__main__":
#     main()