fei_shu.py 8.2 KB

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