feishu_lib.py 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345
  1. # -*- coding: utf-8 -*-
  2. # @Author: wangkun
  3. # @Time: 2022/5/11
  4. import datetime
  5. import json
  6. import time
  7. import requests
  8. import urllib3
  9. from main.common import Common
  10. proxies = {"http": None, "https": None}
  11. class Feishu:
  12. """
  13. 编辑飞书云文档
  14. """
  15. feishu_url = "https://w42nne6hzg.feishu.cn/sheets/shtcngRPoDYAi24x52j2nDuHMih?"
  16. spreadsheetToken = "shtcngRPoDYAi24x52j2nDuHMih"
  17. # 获取飞书api token
  18. @classmethod
  19. def get_token(cls):
  20. """
  21. 获取飞书api token
  22. :return:
  23. """
  24. url = "https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal/"
  25. post_data = {"app_id": "cli_a13ad2afa438d00b", # 这里账号密码是发布应用的后台账号及密码
  26. "app_secret": "4tK9LY9VbiQlY5umhE42dclBFo6t4p5O"}
  27. try:
  28. urllib3.disable_warnings()
  29. response = requests.post(url=url, data=post_data, proxies=proxies, verify=False)
  30. tenant_access_token = response.json()["tenant_access_token"]
  31. return tenant_access_token
  32. except Exception as e:
  33. Common.logger().error("获取飞书 api token 异常:{}", e)
  34. # 获取表格元数据
  35. @classmethod
  36. def get_metainfo(cls):
  37. """
  38. 获取表格元数据
  39. :return:
  40. """
  41. url = "https://open.feishu.cn/open-apis/sheets/v2/spreadsheets/" + cls.spreadsheetToken + "/metainfo"
  42. headers = {
  43. "Authorization": "Bearer " + cls.get_token(),
  44. "Content-Type": "application/json; charset=utf-8"
  45. }
  46. params = {
  47. "extFields": "protectedRange", # 额外返回的字段,extFields=protectedRange时返回保护行列信息
  48. "user_id_type": "open_id" # 返回的用户id类型,可选open_id,union_id
  49. }
  50. try:
  51. urllib3.disable_warnings()
  52. r = requests.get(url=url, headers=headers, params=params, proxies=proxies, verify=False)
  53. response = json.loads(r.content.decode("utf8"))
  54. return response
  55. except Exception as e:
  56. Common.logger().error("获取表格元数据异常:{}", e)
  57. # 读取工作表中所有数据
  58. @classmethod
  59. def get_values_batch(cls, sheetid):
  60. """
  61. 读取工作表中所有数据
  62. :param sheetid: 哪张表
  63. :return: 所有数据
  64. """
  65. url = "https://open.feishu.cn/open-apis/sheets/v2/spreadsheets/" + cls.spreadsheetToken + "/values_batch_get"
  66. headers = {
  67. "Authorization": "Bearer " + cls.get_token(),
  68. "Content-Type": "application/json; charset=utf-8"
  69. }
  70. params = {
  71. # 多个查询范围 如 url?ranges=range1,range2 ,其中 range 包含 sheetId 与单元格范围两部分
  72. "ranges": sheetid,
  73. # valueRenderOption=ToString 可返回纯文本的值(数值类型除外);
  74. # valueRenderOption=FormattedValue 计算并格式化单元格;
  75. # valueRenderOption=Formula单元格中含有公式时返回公式本身;
  76. # valueRenderOption=UnformattedValue计算但不对单元格进行格式化
  77. "valueRenderOption": "ToString",
  78. # dateTimeRenderOption=FormattedString 计算并将时间日期按照其格式进行格式化,但不会对数字进行格式化,返回格式化后的字符串。
  79. "dateTimeRenderOption": "",
  80. # 返回的用户id类型,可选open_id,union_id
  81. "user_id_type": "open_id"
  82. }
  83. try:
  84. urllib3.disable_warnings()
  85. r = requests.get(url=url, headers=headers, params=params, proxies=proxies, verify=False)
  86. response = json.loads(r.content.decode("utf8"))
  87. values = response["data"]["valueRanges"][0]["values"]
  88. return values
  89. except Exception as e:
  90. Common.logger().error("读取工作表所有数据异常:{}", e)
  91. # 工作表,插入行
  92. @classmethod
  93. def insert_columns(cls, sheetid, majordimension, startindex, endindex):
  94. """
  95. 工作表插入数据
  96. sheetid:哪张工作表
  97. majordimension:行或者列
  98. startindex:开始位置
  99. endindex:结束位置
  100. """
  101. url = "https://open.feishu.cn/open-apis/sheets/v2/spreadsheets/"\
  102. + cls.spreadsheetToken + "/insert_dimension_range"
  103. headers = {
  104. "Authorization": "Bearer " + cls.get_token(),
  105. "Content-Type": "application/json; charset=utf-8"
  106. }
  107. body = {
  108. "dimension": {
  109. "sheetId": sheetid,
  110. "majorDimension": majordimension, # 默认 ROWS ,可选 ROWS、COLUMNS
  111. "startIndex": startindex, # 开始的位置
  112. "endIndex": endindex # 结束的位置
  113. },
  114. "inheritStyle": "AFTER" # BEFORE 或 AFTER,不填为不继承 style
  115. }
  116. try:
  117. urllib3.disable_warnings()
  118. r = requests.post(url=url, headers=headers, json=body, proxies=proxies, verify=False)
  119. Common.logger().info("插入行或列:{}", r.json()["msg"])
  120. except Exception as e:
  121. Common.logger().error("插入行或列异常:{}", e)
  122. # 工作表,首行写入数据
  123. @classmethod
  124. def update_values(cls, sheetid, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1):
  125. """
  126. 写入数据
  127. :param sheetid: 哪张工作表
  128. :param a1: 单元格
  129. :param b1: 单元格
  130. :param c1: 单元格
  131. :param d1: 单元格
  132. :param e1: 单元格
  133. :param f1: 单元格
  134. :param g1: 单元格
  135. :param h1: 单元格
  136. :param i1: 单元格
  137. :param j1: 单元格
  138. :param k1: 单元格
  139. :param l1: 单元格
  140. :param m1: 单元格
  141. :param n1: 单元格
  142. :param o1: 单元格
  143. :return:
  144. """
  145. url = "https://open.feishu.cn/open-apis/sheets/v2/spreadsheets/" + cls.spreadsheetToken + "/values_batch_update"
  146. headers = {
  147. "Authorization": "Bearer " + cls.get_token(),
  148. "Content-Type": "application/json; charset=utf-8"
  149. }
  150. body = {
  151. "valueRanges": [
  152. {
  153. "range": sheetid + "!A2:O2",
  154. "values": [
  155. [a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1]
  156. ]
  157. },
  158. ],
  159. }
  160. try:
  161. urllib3.disable_warnings()
  162. r = requests.post(url=url, headers=headers, json=body, proxies=proxies, verify=False)
  163. Common.logger().info("空行写入视频数据:{}", r.json()["msg"])
  164. except Exception as e:
  165. Common.logger().error("空行写入视频数据异常:{}", e)
  166. # 写入数据
  167. @classmethod
  168. def update_hour_list_values(cls, sheetid, ranges, values):
  169. """
  170. 小时榜写入数据
  171. sheetid:工作表 ID
  172. ranges:单元格范围
  173. values:写入的具体数据,list
  174. """
  175. # 表格 ID
  176. url = "https://open.feishu.cn/open-apis/sheets/v2/spreadsheets/" + cls.spreadsheetToken + "/values_batch_update"
  177. headers = {
  178. "Authorization": "Bearer " + cls.get_token(),
  179. "Content-Type": "application/json; charset=utf-8"
  180. }
  181. body = {
  182. "valueRanges": [
  183. {
  184. "range": sheetid + "!" + ranges,
  185. "values": values
  186. },
  187. ],
  188. }
  189. try:
  190. urllib3.disable_warnings()
  191. r = requests.post(url=url, headers=headers, json=body, proxies=proxies, verify=False)
  192. Common.logger().info("小时榜写入数据:{}", r.json()["msg"])
  193. except Exception as e:
  194. Common.logger().error("小时榜写入数据异常:{}", e)
  195. # 合并单元格
  196. @classmethod
  197. def merge_cells(cls, sheetid, ranges):
  198. """
  199. 合并刚插入的单元格 G1:I1
  200. sheetid:哪张工作表
  201. ranges:需要合并的单元格范围
  202. """
  203. url = "https://open.feishu.cn/open-apis/sheets/v2/spreadsheets/" + cls.spreadsheetToken + "/merge_cells"
  204. headers = {
  205. "Authorization": "Bearer " + cls.get_token(),
  206. "Content-Type": "application/json; charset=utf-8"
  207. }
  208. body = {
  209. "range": sheetid + "!" + ranges,
  210. "mergeType": "MERGE_ROWS"
  211. }
  212. try:
  213. urllib3.disable_warnings()
  214. r = requests.post(url=url, headers=headers, json=body, proxies=proxies, verify=False)
  215. Common.logger().info("合并单元格:{}", r.json()["msg"])
  216. except Exception as e:
  217. Common.logger().error("合并单元格异常:{}", e)
  218. # 读取单元格数据
  219. @classmethod
  220. def get_range_value(cls, sheetid, cell):
  221. """
  222. 读取单元格内容
  223. :param sheetid: 哪张工作表
  224. :param cell: 哪个单元格
  225. :return: 单元格内容
  226. """
  227. url = "https://open.feishu.cn/open-apis/sheets/v2/spreadsheets/" \
  228. + cls.spreadsheetToken + "/values/" + sheetid + "!" + cell
  229. headers = {
  230. "Authorization": "Bearer " + cls.get_token(),
  231. "Content-Type": "application/json; charset=utf-8"
  232. }
  233. params = {
  234. # valueRenderOption=ToString 可返回纯文本的值(数值类型除外);
  235. # valueRenderOption=FormattedValue 计算并格式化单元格;
  236. # valueRenderOption=Formula 单元格中含有公式时返回公式本身;
  237. # valueRenderOption=UnformattedValue 计算但不对单元格进行格式化。
  238. "valueRenderOption": "FormattedValue",
  239. # dateTimeRenderOption=FormattedString 计算并对时间日期按照其格式进行格式化,但不会对数字进行格式化,返回格式化后的字符串。
  240. "dateTimeRenderOption": "",
  241. # 返回的用户id类型,可选open_id,union_id
  242. "user_id_type": "open_id"
  243. }
  244. try:
  245. urllib3.disable_warnings()
  246. r = requests.get(url=url, headers=headers, params=params, proxies=proxies, verify=False)
  247. # print(url)
  248. return r.json()["data"]["valueRange"]["values"][0]
  249. except Exception as e:
  250. Common.logger().error("读取单元格数据异常:{}", e)
  251. # 删除行或列,可选 ROWS、COLUMNS
  252. @classmethod
  253. def dimension_range(cls, sheetid, major_dimension, startindex, endindex):
  254. """
  255. 删除行或列
  256. :param sheetid:工作表
  257. :param major_dimension:默认 ROWS ,可选 ROWS、COLUMNS
  258. :param startindex:开始的位置
  259. :param endindex:结束的位置
  260. :return:
  261. """
  262. url = "https://open.feishu.cn/open-apis/sheets/v2/spreadsheets/" + cls.spreadsheetToken + "/dimension_range"
  263. headers = {
  264. "Authorization": "Bearer " + cls.get_token(),
  265. "Content-Type": "application/json; charset=utf-8"
  266. }
  267. body = {
  268. "dimension": {
  269. "sheetId": sheetid,
  270. "majorDimension": major_dimension,
  271. "startIndex": startindex,
  272. "endIndex": endindex
  273. }
  274. }
  275. try:
  276. urllib3.disable_warnings()
  277. r = requests.delete(url=url, headers=headers, json=body, proxies=proxies, verify=False)
  278. Common.logger().info("删除视频数据:{}", r.json()["msg"])
  279. except Exception as e:
  280. Common.logger().error("删除视频数据异常:{}", e)
  281. if __name__ == "__main__":
  282. feishu = Feishu()
  283. # # 获取飞书api token
  284. # feishu.get_token()
  285. # 获取表格元数据
  286. # feishu.get_metainfo()
  287. # 读取工作表中所有数据
  288. # print(feishu.get_values_batch("k2rKkv"))
  289. # print(len(feishu.get_values_batch("k2rKkv")))
  290. # for i in range(3, len(feishu.get_values_batch("k2rKkv"))+1):
  291. # print(feishu.get_range_value("k2rKkv", "A" + str(i) + ":" + "A" + str(i))[0])
  292. # print(feishu.update_hour_list_values("k2rKkv", "G" + str(i) + ":" + "H" + str(i), [["333"]]))
  293. # time.sleep(0.5)
  294. # feishu.get_range_value("k2rKkv", "F3:F3")[0]
  295. print(type(feishu.get_range_value("k2rKkv", "H19:H19")[0].split(" ")[-1].split(":")[0]))
  296. print(feishu.get_range_value("k2rKkv", "H19:H19")[0])
  297. print(int(feishu.get_range_value("k2rKkv", "H19:H19")[0].split(" ")[-1].split(":")[0]))
  298. feishu.update_hour_list_values("k2rKkv", "H12:H12", [["2022-05-17 15:14:27"]])
  299. # 看一看+工作表,插入首行
  300. # print(feishu.insert_columns("k2rKkv", "COLUMNS", 6, 9))
  301. # print(feishu.update_hour_list_values("k2rKkv"))
  302. # print(feishu.merge_cells("k2rKkv", "G1:I1"))
  303. #
  304. # # 看一看+工作表,首行写入数据
  305. # print(feishu.update_values("Y8N3Vl", "a1", "b1", "c1", "d1", "e1", "f1", "g1",
  306. # "h1", "i1", "j1", "k1", "l1", "m1", "n1", "o1"))
  307. # 查询单元格内容
  308. # print(type(feishu.get_range_value("k2rKkv", "G1:G1")[0]))
  309. #
  310. # 删除行或列,可选 ROWS、COLUMNS
  311. # feishu.dimension_range("k2rKkv", "ROWS", 3, 3)
  312. pass