extractors.py 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  1. from typing import Dict, Any
  2. from jsonpath_ng import parse
  3. def safe_extract(json_obj: Any, path: str, default=None):
  4. """
  5. 安全提取单个字段值,返回匹配到的第一个,否则返回默认值。
  6. :param json_obj: 输入的 JSON 对象
  7. :param path: JSONPath 表达式
  8. :param default: 提取失败时返回的默认值
  9. :return: 提取结果或默认值
  10. """
  11. # 处理空对象或None的情况
  12. if json_obj is None:
  13. return default
  14. try:
  15. jsonpath_expr = parse(path)
  16. match = jsonpath_expr.find(json_obj)
  17. if match:
  18. return match[0].value
  19. except Exception as e:
  20. # 记录错误但不中断程序执行
  21. print(f"[extractor] Error extracting {path}: {e}")
  22. return default
  23. def extract_multiple(json_obj: Any, fields: dict) -> dict:
  24. """
  25. 根据字段配置提取多个字段。
  26. :param json_obj: 输入的 JSON 对象
  27. :param fields: 字段配置,如 {"title": "$.title", "id": "$.id"}
  28. :return: 字段名 -> 提取值的字典
  29. """
  30. return {key: safe_extract(json_obj, path) for key, path in fields.items()}
  31. def extract_fields(video: Dict, field_map: Dict, logger=None, trace_id=None, aliyun_log=None) -> Dict:
  32. result = {}
  33. for field, path in field_map.items():
  34. # 如果path不是字符串或不是以$开头的jsonpath,则直接使用值
  35. if not isinstance(path, str) or not path.startswith("$"):
  36. result[field] = path
  37. continue
  38. value = safe_extract(video, path)
  39. if value is None and logger:
  40. logger.warning(f"字段提取失败: {field} 路径: {path}")
  41. if aliyun_log:
  42. aliyun_log.logging(
  43. code="9024",
  44. message=f"字段提取失败: {field} 路径: {path}",
  45. data={"video": video}
  46. )
  47. result[field] = value
  48. return result