fei_shu.py 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. import os
  2. import uuid
  3. from typing import Any, Dict, Optional
  4. import lark_oapi as lark
  5. from lark_oapi.core.enum import LogLevel
  6. class FeiShu(object):
  7. _instance = None
  8. def __new__(cls, *args, **kwargs):
  9. if cls._instance is None:
  10. cls._instance = super().__new__(cls, *args, **kwargs)
  11. return cls._instance
  12. def __init__(self):
  13. app_id = os.getenv('FEISHU_APP_ID')
  14. app_secret = os.getenv('FEISHU_APP_SECRET')
  15. self.file_token = os.getenv('FEISHU_FILE_TOKEN')
  16. self.client = (lark.client.Client().builder()
  17. .app_id(app_id)
  18. .app_secret(app_secret)
  19. .log_level(LogLevel.INFO)
  20. .build())
  21. def create_table(self, name: str) -> str:
  22. request = (lark.bitable.v1.CreateAppTableRequest.builder()
  23. .app_token(self.file_token)
  24. .request_body(lark.bitable.v1.CreateAppTableRequestBody.builder()
  25. .table(lark.bitable.v1.ReqTable.builder()
  26. .name(name)
  27. .fields([
  28. lark.bitable.v1.AppTableCreateHeader.builder().field_name('原文链接').type(15).build(),
  29. lark.bitable.v1.AppTableCreateHeader.builder().field_name('抓取结果').type(1).build(),
  30. lark.bitable.v1.AppTableCreateHeader.builder().field_name('标题').type(1).build(),
  31. lark.bitable.v1.AppTableCreateHeader.builder().field_name('用户链接').type(15).build(),
  32. lark.bitable.v1.AppTableCreateHeader.builder().field_name('识别结果').type(1).build(),
  33. lark.bitable.v1.AppTableCreateHeader.builder().field_name('初步理解').type(1).build(),
  34. lark.bitable.v1.AppTableCreateHeader.builder().field_name('物理聚合').type(1).build(),
  35. ])
  36. .build())
  37. .build())
  38. .build())
  39. response = self.client.bitable.v1.app_table.create(request)
  40. if not response.success():
  41. raise RuntimeError(f'多维表格创建新数据表失败: {lark.JSON.marshal(response.error)}')
  42. return response.data.table_id
  43. def get_all_records(self, table_id: str, page_token: Optional[str] = None):
  44. request = (lark.bitable.v1.SearchAppTableRecordRequest.builder()
  45. .app_token(self.file_token)
  46. .table_id(table_id)
  47. .user_id_type('open_id')
  48. .page_size(500)
  49. .request_body(lark.bitable.v1.SearchAppTableRecordRequestBody.builder()
  50. .automatic_fields(True)
  51. .build()))
  52. if page_token:
  53. request = request.page_token(page_token)
  54. request = request.build()
  55. response = self.client.bitable.v1.app_table_record.search(request)
  56. if not response.success():
  57. raise RuntimeError(f'获取多维表格记录失败: {lark.JSON.marshal(response.error)}')
  58. return response.data
  59. def get_record(self, table_id: str, *record_ids: str):
  60. request = (lark.bitable.v1.BatchGetAppTableRecordRequest.builder()
  61. .app_token(self.file_token)
  62. .table_id(table_id)
  63. .request_body(lark.bitable.v1.BatchGetAppTableRecordRequestBody.builder()
  64. .record_ids(list(record_ids))
  65. .user_id_type('open_id')
  66. .with_shared_url(True)
  67. .automatic_fields(True)
  68. .build())
  69. .build())
  70. response = self.client.bitable.v1.app_table_record.batch_get(request)
  71. if not response.success():
  72. raise RuntimeError(f'获取多维表格指定记录失败: {lark.JSON.marshal(response.error)}')
  73. return response.data
  74. def create_record(self, table_id: str, *fields: Dict[str, Any]):
  75. request = (lark.bitable.v1.BatchCreateAppTableRecordRequest.builder()
  76. .app_token(self.file_token)
  77. .table_id(table_id)
  78. .user_id_type('open_id')
  79. .client_token(str(uuid.uuid4()))
  80. .ignore_consistency_check(False)
  81. .request_body(lark.bitable.v1.BatchCreateAppTableRecordRequestBody.builder()
  82. .records([lark.bitable.v1.AppTableRecord.builder()
  83. .fields(item)
  84. .build() for item in fields])
  85. .build())
  86. .build())
  87. response = self.client.bitable.v1.app_table_record.batch_create(request)
  88. if not response.success():
  89. raise RuntimeError(f'向多维表格添加记录失败: {lark.JSON.marshal(response.error)}')
  90. return response.data
  91. def update_record(self, table_id: str, *records: lark.bitable.v1.AppTableRecord):
  92. request = (lark.bitable.v1.BatchUpdateAppTableRecordRequest.builder()
  93. .app_token(self.file_token)
  94. .table_id(table_id)
  95. .user_id_type('open_id')
  96. .ignore_consistency_check(False)
  97. .request_body(lark.bitable.v1.BatchUpdateAppTableRecordRequestBody.builder()
  98. .records(list(records))
  99. .build())
  100. .build())
  101. response = self.client.bitable.v1.app_table_record.batch_update(request)
  102. if not response.success():
  103. raise RuntimeError(f'更新多维表格指定记录失败: {lark.JSON.marshal(response.error)}')
  104. return response.data
  105. def delete_record(self, table_id: str, *record_ids: str):
  106. request = (lark.bitable.v1.BatchDeleteAppTableRecordRequest.builder()
  107. .app_token(self.file_token)
  108. .table_id(table_id)
  109. .request_body(lark.bitable.v1.BatchDeleteAppTableRecordRequestBody.builder()
  110. .records(list(record_ids))
  111. .build())
  112. .build())
  113. response = self.client.bitable.v1.app_table_record.batch_delete(request)
  114. if not response.success():
  115. raise RuntimeError(f'删除多维表格指定记录失败: {lark.JSON.marshal(response.error)}')
  116. return response.data
  117. if __name__ == '__main__':
  118. from dotenv import load_dotenv
  119. try:
  120. load_dotenv()
  121. except ImportError:
  122. raise RuntimeError('导入环境变量失败')
  123. feishu = FeiShu()
  124. # 创建数据表
  125. new_table_id = feishu.create_table('测试数据表')
  126. # 新增记录
  127. new_fields = [
  128. {
  129. '原文链接': {
  130. 'link': 'https://www.baidu.com',
  131. 'text': 'https://www.baidu.com',
  132. },
  133. '抓取结果': '这是抓取结果1',
  134. },
  135. {
  136. '原文链接': {
  137. 'link': 'https://www.qq.com',
  138. 'text': 'https://www.qq.com',
  139. },
  140. '抓取结果': '这是抓取结果2',
  141. }
  142. ]
  143. feishu.create_record(new_table_id, *new_fields)
  144. # 获取全部记录
  145. get_result = feishu.get_all_records(new_table_id)
  146. has_more = get_result.has_more # 是否有下一页
  147. next_page_token = get_result.page_token # 下一页token
  148. new_record_ids = []
  149. for record in get_result.items:
  150. new_record_ids.append(record.record_id)
  151. print(record.fields)
  152. # 更新记录
  153. new_record = (lark.bitable.v1.AppTableRecord.builder()
  154. .record_id(new_record_ids[0])
  155. .fields({'识别结果': '这是识别结果'})
  156. .build())
  157. feishu.update_record(new_table_id, new_record)
  158. # 获取指定ID记录
  159. get_result = feishu.get_record(new_table_id, *new_record_ids)
  160. for record in get_result.records:
  161. new_record_ids.append(record.record_id)
  162. print(record.fields)
  163. # 删除指定ID记录
  164. feishu.delete_record(new_table_id, new_record_ids[1])