提高速度,Python脚本从邮件中提取Gmail标签

ep6jt1vc  于 2024-01-05  发布在  Python
关注(0)|答案(1)|浏览(233)

我正在编写一个Python脚本,它可以将Gmail帐户中的每个邮件ID沿着及其添加的标签(完整的标签路径)导出到一个TXT文件中。
脚本本身可以工作,但导出速度大约为每秒2条消息。对于较小的帐户,这很好,但对于较大的帐户,导出可能需要几天,在某些情况下,几周。
是否有方法可以提高脚本的处理速度,或者限制来自Google本身?

  1. def get_label_path(service, label_id):
  2. label = service.users().labels().get(userId='me', id=label_id).execute()
  3. label_path = label['name']
  4. while 'parent' in label:
  5. label = service.users().labels().get(userId='me', id=label['parent']).execute()
  6. label_path = label['name'] + '/' + label_path
  7. return label_path
  8. def get_message_ids_with_labels(service):
  9. profile = service.users().getProfile(userId='me').execute()
  10. page_token = None
  11. with open(OUTPUT_FILE_PATH, 'w') as output_file:
  12. while True:
  13. results = service.users().messages().list(userId='me', pageToken=page_token).execute()
  14. messages = results.get('messages', [])
  15. if not messages:
  16. break
  17. for message in messages:
  18. message_id = message['id']
  19. msg = get_message(service, message_id)
  20. headers = msg['payload']['headers']
  21. message_id = next((header['value'] for header in headers if header['name'].lower() == 'message-id'), None)
  22. label_ids = msg.get('labelIds', [])
  23. labels = [get_label_path(service, label_id) for label_id in label_ids]
  24. output_file.write(f"Message-ID: {message_id} - Labels: {labels}\n")
  25. page_token = results.get('nextPageToken')
  26. if not page_token:
  27. break

字符串

5q4ezhmt

5q4ezhmt1#

我相信你的目标如下。

  • 您希望减少显示脚本的过程成本。

在您的情况下,以下流程如何?
1.使用Method: users.labels.list将标签列表转换为对象。
1.使用Method: users.messages.lis删除所有消息ID。
1.使用Method: users.messages.get从消息ID中删除标签ID。在这种情况下,使用批处理请求。
1.使用标签列表对象和标签ID创建结果文本。
1.将结果文本写入文件。
当这个流反映在修改后的脚本中时,它变成如下所示。

修改脚本:

请设置OUTPUT_FILE_PATH

  1. OUTPUT_FILE_PATH = "sample.txt" # Please set your output filename.
  2. ar = []
  3. def sample(id, res, err):
  4. # print(id)
  5. # print(err)
  6. ar.append([res["id"], res.get("labelIds", [])])
  7. def get_labels(service):
  8. obj = service.users().labels().list(userId='me').execute()
  9. labels = obj.get('labels', [])
  10. labelObj = {}
  11. for e in labels:
  12. labelObj[e["id"]] = e["name"]
  13. return labelObj
  14. def get_message_ids_with_labels(service):
  15. # Retrieve label list as an object.
  16. labelObj = get_labels(service)
  17. # Retrieve all message IDs.
  18. messageIds = []
  19. page_token = ""
  20. while page_token is not None:
  21. obj = service.users().messages().list(userId='me', pageToken=page_token, maxResults=500).execute()
  22. messages = [e["id"] for e in obj.get('messages', [])]
  23. messageIds += messages
  24. page_token = obj.get("nextPageToken")
  25. print(f"Total message IDs: {len(messageIds)}")
  26. # Retrieve label ids from message IDs.
  27. for i in range(0, len(messageIds), 100):
  28. batchIds = messageIds[i:i+100]
  29. print(f"Processing from {i} to {i + len(batchIds)}")
  30. batch = service.new_batch_http_request(callback=sample)
  31. for messageId in batchIds:
  32. batch.add(service.users().messages().get(userId='me', id=messageId, fields="id,labelIds"))
  33. batch.execute()
  34. # Create result texts using the label list object and label IDs.
  35. arr = []
  36. for e in ar:
  37. labelNames = []
  38. for f in e[1]:
  39. labelNames.append(labelObj[f])
  40. arr.append(f"Message-ID: {e[0]} - Labels: {','.join(labelNames)}")
  41. res = "\n".join(arr)
  42. # Write the result texts into a file.
  43. with open(OUTPUT_FILE_PATH, 'w') as output_file:
  44. output_file.write(res)
  45. print("Done")

字符串

  • 在这个脚本中,请调用一个函数get_message_ids_with_labels(service)service是一个使用Gmail API的客户端。
  • 运行此脚本时,将使用上述流程创建一个包含Message-ID: ### - Labels: ###的文本文件。

注意:

  • 在这个修改中,它假设您的客户端service可以用于使用Gmail API。请注意这一点。
  • 在我的环境中,大约1分钟可以处理3,000条消息。

参考资料:

新增1:

从你下面的回复来看,
有一个巨大的速度增加。只有一个问题,因为我需要“消息ID”从metadataHeaders[]",
我没有注意到你想从你的问题中检索标题中的Message-ID的值。我以为你想检索Gmail的消息ID。如果标题中的Message-ID的值,那么下面的示例脚本如何?上面的示例脚本被修改了。

示例脚本:

  1. OUTPUT_FILE_PATH = "sample.txt" # Please set your output filename.
  2. ar = []
  3. def sample(id, res, err):
  4. # print(id)
  5. # print(err)
  6. ar.append([res["payload"]["headers"][0]["value"], res.get("labelIds", [])])
  7. def get_labels(service):
  8. obj = service.users().labels().list(userId='me').execute()
  9. labels = obj.get('labels', [])
  10. labelObj = {}
  11. for e in labels:
  12. labelObj[e["id"]] = e["name"]
  13. return labelObj
  14. def get_message_ids_with_labels(service):
  15. # Retrieve label list as an object.
  16. labelObj = get_labels(service)
  17. # Retrieve all message IDs.
  18. messageIds = []
  19. page_token = ""
  20. while page_token is not None:
  21. obj = service.users().messages().list(userId='me', pageToken=page_token, maxResults=500).execute()
  22. messages = [e["id"] for e in obj.get('messages', [])]
  23. messageIds += messages
  24. page_token = obj.get("nextPageToken")
  25. print(f"Total message IDs: {len(messageIds)}")
  26. # Retrieve label ids from message IDs.
  27. for i in range(0, len(messageIds), 100):
  28. batchIds = messageIds[i:i+100]
  29. print(f"Processing from {i} to {i + len(batchIds)}")
  30. batch = service.new_batch_http_request(callback=sample)
  31. for messageId in batchIds:
  32. batch.add(service.users().messages().get(userId='me', id=messageId, format='metadata', metadataHeaders=['Message-ID']))
  33. batch.execute()
  34. # Create result texts using the label list object and label IDs.
  35. arr = []
  36. for e in ar:
  37. labelNames = []
  38. for f in e[1]:
  39. labelNames.append(labelObj[f])
  40. arr.append(f"Message-ID: {e[0]} - Labels: {','.join(labelNames)}")
  41. res = "\n".join(arr)
  42. # Write the result texts into a file.
  43. with open(OUTPUT_FILE_PATH, 'w') as output_file:
  44. output_file.write(res)
  45. print("Done")

  • 运行此脚本时,将检索邮件头和标签中Message-ID的值。

新增2:

关于您的以下回复,
但是我收到了这个错误“行40,in sample ar.append([res[“payload”][“headers”][0][“value”],res.get(“labelIds”,[])])~^ TypeError:'NoneType' object is not subscriptable”.我假设它与没有标签的消息有关.我假设当没有标签时输出将是“. - Labels:“
在这种情况下,请按如下方式修改上述脚本。

发件人:

  1. def sample(id, res, err):
  2. # print(id)
  3. # print(err)
  4. ar.append([res["payload"]["headers"][0]["value"], res.get("labelIds", [])])

收件人:

  1. def sample(id, res, err):
  2. # print(id)
  3. # print(err)
  4. labelIds = res.get("labelIds", [])
  5. if "headers" not in res["payload"] or res["payload"]["headers"] is None or len(res["payload"]["headers"]) == 0 or "name" not in res["payload"]["headers"][0] or res["payload"]["headers"][0]["name"] != "Message-ID":
  6. ar.append(["No Message-ID", [] if labelIds is None else labelIds])
  7. else:
  8. ar.append([res["payload"]["headers"][0]["value"], [] if labelIds is None else labelIds])

展开查看全部

相关问题