spiders.py 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. # backend/app/api/spiders.py
  2. from fastapi import APIRouter, Depends, HTTPException, status, UploadFile, File, Form
  3. from sqlalchemy.orm import Session
  4. from typing import Optional
  5. import os
  6. from ..database import get_db
  7. from ..models import Spider, Category
  8. from ..schemas import SpiderCreate, SpiderUpdate, Spider, ListResponse, SuccessResponse
  9. from ..services.category_service import CategoryService
  10. from ..services.file_service import FileService
  11. router = APIRouter(prefix="/api/spiders", tags=["spiders"])
  12. @router.post("/", response_model=Spider)
  13. def create_spider(
  14. name: str = Form(...),
  15. description: Optional[str] = Form(None),
  16. cron_expression: str = Form("0 0 * * *"),
  17. enabled: bool = Form(True),
  18. timeout: int = Form(300),
  19. category_id: int = Form(...),
  20. code_content: Optional[str] = Form(None),
  21. file: Optional[UploadFile] = File(None),
  22. db: Session = Depends(get_db)
  23. ):
  24. # 验证分类是否存在
  25. category = CategoryService.get_category_by_id(db, category_id)
  26. # 检查脚本名称是否重复
  27. existing_spider = db.query(Spider).filter(Spider.name == name).first()
  28. if existing_spider:
  29. raise HTTPException(
  30. status_code=status.HTTP_400_BAD_REQUEST,
  31. detail="脚本名称已存在"
  32. )
  33. file_service = FileService()
  34. filename = None
  35. file_path = None
  36. final_code_content = code_content
  37. if file and file.filename:
  38. # 文件上传方式
  39. filename, file_path = file_service.save_uploaded_file(file)
  40. final_code_content = file_service.read_file_content(file_path)
  41. elif code_content:
  42. # 代码粘贴方式
  43. filename, file_path = file_service.save_code_content(code_content, name)
  44. else:
  45. raise HTTPException(
  46. status_code=status.HTTP_400_BAD_REQUEST,
  47. detail="必须提供代码内容或上传文件"
  48. )
  49. spider_data = {
  50. "name": name,
  51. "description": description,
  52. "filename": filename,
  53. "file_path": file_path,
  54. "code_content": final_code_content,
  55. "cron_expression": cron_expression,
  56. "enabled": enabled,
  57. "timeout": timeout,
  58. "category_id": category_id
  59. }
  60. db_spider = Spider(**spider_data)
  61. db.add(db_spider)
  62. db.commit()
  63. db.refresh(db_spider)
  64. return db_spider
  65. @router.get("/", response_model=ListResponse)
  66. def get_spiders(category_id: Optional[int] = None, db: Session = Depends(get_db)):
  67. query = db.query(Spider)
  68. if category_id:
  69. query = query.filter(Spider.category_id == category_id)
  70. spiders = query.all()
  71. # 加载分类信息
  72. for spider in spiders:
  73. spider.category
  74. return ListResponse(total=len(spiders), items=spiders)
  75. @router.get("/{spider_id}", response_model=Spider)
  76. def get_spider(spider_id: int, db: Session = Depends(get_db)):
  77. spider = db.query(Spider).filter(Spider.id == spider_id).first()
  78. if not spider:
  79. raise HTTPException(
  80. status_code=status.HTTP_404_NOT_FOUND,
  81. detail="脚本不存在"
  82. )
  83. spider.category
  84. return spider
  85. @router.put("/{spider_id}", response_model=Spider)
  86. def update_spider(spider_id: int, spider_update: SpiderUpdate, db: Session = Depends(get_db)):
  87. db_spider = db.query(Spider).filter(Spider.id == spider_id).first()
  88. if not db_spider:
  89. raise HTTPException(
  90. status_code=status.HTTP_404_NOT_FOUND,
  91. detail="脚本不存在"
  92. )
  93. update_data = spider_update.dict(exclude_unset=True)
  94. file_service = FileService()
  95. # 如果更新了代码内容,需要更新文件
  96. if 'code_content' in update_data and update_data['code_content']:
  97. # 删除旧文件
  98. file_service.delete_file(db_spider.file_path)
  99. # 保存新文件
  100. filename, file_path = file_service.save_code_content(
  101. update_data['code_content'],
  102. update_data.get('name', db_spider.name)
  103. )
  104. update_data['filename'] = filename
  105. update_data['file_path'] = file_path
  106. # 更新字段
  107. for field, value in update_data.items():
  108. if field != 'code_content':
  109. setattr(db_spider, field, value)
  110. db.commit()
  111. db.refresh(db_spider)
  112. return db_spider
  113. @router.delete("/{spider_id}")
  114. def delete_spider(spider_id: int, db: Session = Depends(get_db)):
  115. db_spider = db.query(Spider).filter(Spider.id == spider_id).first()
  116. if not db_spider:
  117. raise HTTPException(
  118. status_code=status.HTTP_404_NOT_FOUND,
  119. detail="脚本不存在"
  120. )
  121. # 删除服务器上的脚本文件
  122. file_service = FileService()
  123. file_service.delete_file(db_spider.file_path)
  124. db.delete(db_spider)
  125. db.commit()
  126. return SuccessResponse(success=True, message="脚本删除成功")
  127. @router.put("/{spider_id}/toggle", response_model=Spider)
  128. def toggle_spider(spider_id: int, db: Session = Depends(get_db)):
  129. db_spider = db.query(Spider).filter(Spider.id == spider_id).first()
  130. if not db_spider:
  131. raise HTTPException(
  132. status_code=status.HTTP_404_NOT_FOUND,
  133. detail="脚本不存在"
  134. )
  135. db_spider.enabled = not db_spider.enabled
  136. db.commit()
  137. db.refresh(db_spider)
  138. return db_spider