Python实现批量下载邮箱中京东商城的发票

以QQ邮箱为例
可以设置获取指定时间内的邮件中的发票
可以设置获取指定地点内的邮件中的发票

import poplib
from  urllib import request
from email import policy
from email.parser import BytesParser
from email.header import decode_header, make_header
from email.headerregistry import UniqueDateHeader
import re,os
from xml.dom.minidom import parse# 定义EmailClient类,用于连接到POP3服务器并从指定的邮件地址获取邮件
class JDInvoiceDownload:# 在初始化函数中,设置POP3服务器的来源、用户、密码和待查询的目标邮件地址def __init__(self, host,pop_server_port, user, password, target_email,file_path,target_addr=None,target_time=None):"""初始化EmailClient类的新实例。参数:- host: 邮件服务器的主机名或IP地址。- pop_server_port: POP3服务器的端口号。- user: 用户名,用于登录邮件服务器。- password: 用户密码,用于登录邮件服务器。- target_email: 目标电子邮件地址。- file_path: 附件的文件路径。"""self.POP3_SSL(host,pop_server_port)self.login(user, password)self.target_email = target_emailself.file_path = file_pathself.target_addr = target_addrself.target_time = target_timedef POP3_SSL(self,pop_server_host,pop_server_port):try:# 连接pop服务器。如果没有使用SSL,将POP3_SSL()改成POP3()即可其他都不需要做改动self.pop_server = poplib.POP3_SSL(host=pop_server_host, port=pop_server_port, timeout=10)print("pop3----连接服务器成功,现在将检查用户名")except:print("pop3----对不起,给定的电子邮件服务器地址连接超时")exit(1)def login(self,user,password):try:# 验证邮箱是否存在self.pop_server.user(user)print("pop3----用户名已存在,现在将检查密码")except:print("pop3----对不起,给定的电子邮件地址似乎不存在")exit(1)try:# 验证邮箱密码是否正确self.pop_server.pass_(password)print("pop3----密码正确,现在将列出电子邮件")except:print("pop3----对不起,给定的用户名似乎不正确")exit(1)# 定义一个函数,用以清除文件名中的无效字符def sanitize_folder_name(self, name):invalid_characters = "<>:\"/\\|?*@"for char in invalid_characters:  # 遍历所有无效字符name = name.replace(char, "_")  # 将无效字符替换为下划线return name  # 返回清理后的名称# 定义一个函数,用以提取邮件的payload(有效载荷,即邮件主体内容)def get_payload(self, email_message):if email_message.is_multipart():  # 判断邮件是否为多部分邮件for part in email_message.iter_parts():  # 如果是,则遍历其中的每一部分content_type = part.get_content_type()  # 获取该部分的内容类型if content_type == 'text/html':  # 如果内容类型为HTML,则返回该部分内容return part.get_content()elif content_type == 'text/plain':  # 如果内容类型为纯文本,则返回该部分内容return part.get_content()elif email_message.get_content_type() == 'text/html':  # 如果邮件非多部分形式,且为HTML类型,则返回邮件内容return email_message.get_content()elif email_message.get_content_type() == 'text/plain':  # 如果邮件非多部分形式,且为纯文本类型,则返回邮件内容return email_message.get_content()def fetch_email(self):# 邮箱中其收到的邮件的数量email_count = len(self.pop_server.list()[1])print("email_num: ",email_count)# list()返回所有邮件的编号:_, mails, _ = self.pop_server.list()# for i in range(len(mails),len(mails)-1,-1):for i in range(len(mails),1, -1):# 通过retr(index)读取第index封邮件的内容;这里读取最后一封,也即最新收到的那一封邮件resp, lines, octets = self.pop_server.retr(i)email_content = b'\r\n'.join(lines)  # 将所有行连接成一个bytes对象# 解析邮件内容email_parser = BytesParser(policy=policy.default)  # 创建一个邮件解析器email = email_parser.parsebytes(email_content)  # 解析邮件内容,返回一个邮件对象email_time =  self.get_email_time(email)print("email_time: ",email_time)if email_time == self.target_time and  self.check_email_from(email):  # 如果发件人地址与指定的目标邮件地址一致,对邮件进行处理email_body = self.get_payload(email)  # 获取邮件正文if self.check_invoice_target_addr(email_body):self.download_invoice(email_body,f"{i}.pdf",email_time)print("--------------------------------------------------------------------------------------")def check_email_from(self, email) -> bool:"""对比发件人地址与指定的目标邮件地址是否一致:param email::return:"""# 解析邮件头部信息并提取发件人信息email_from = email.get('From').strip()  # 获取发件人信息,并去除尾部的空格email_from = str(make_header(decode_header(email_from)))  # 解码发件人信息,并将其转换为字符串print("发件人地址:", email_from," ",email_from == self.target_email)return  email_from == self.target_emaildef get_email_time(self,email):"""解析邮件时间:param email::return:"""# 解析邮件时间email_time: UniqueDateHeader = email.get('Date')  # 获取邮件时间# 获取年月日return   email_time.datetime.strftime("%Y-%m-%d")def download_invoice(self, body, filename,email_time):"""下载发票:param body::param filename::param email_time::return:"""pattern = r'href="([^"]*)">发票PDF文件下载</a>'match = re.search(pattern, body)if match:# 提取URLurl = match.group(1)print("找到的-PDF-URL是:", "".join(url.split("amp;")))try:file_path = f"{self.file_path}\\{email_time}"# 判断文件夹是否存在if not os.path.exists(file_path):os.makedirs(file_path)request.urlretrieve("".join(url.split("amp;")), f"{file_path}\\{filename}")except Exception as e:print("Error downloading:", e)def check_invoice_target_addr(self, body) -> bool:"""读取XML文件,判断是否是某个地方的发票"""pattern = r'href="([^"]*)">发票XML文件下载</a> 'match = re.search(pattern, body)if match:# 提取URLurl = match.group(1)print("找到的-XML-URL是:", "".join(url.split("amp;")))try:file_name = f"{self.file_path}\\xml_file_test.xml"request.urlretrieve("".join(url.split("amp;")),file_name)dom = parse(file_name)# 获取文档元素对象data = dom.documentElementseller_addr = data.getElementsByTagName("EInvoiceData")[0].getElementsByTagName("SellerInformation")[0].getElementsByTagName("SellerAddr")[0].childNodes[0].nodeValueprint("seller_addr:",seller_addr," "+self.target_addr in  seller_addr)if not self.target_addr in  seller_addr:return  Falseexcept Exception as e:print("Error parsing XML:", e)return  Truedef close(self):# 关闭连接self.pop_server.close()if __name__ == '__main__':client = JDInvoiceDownload(host='pop.qq.com', # 邮箱服务器地址(qq邮箱无需改)pop_server_port=995, # 端口号(qq邮箱无需改)user=input("请输入你的邮箱地址:"), # 邮箱账号password=input("请输入你的授权码:"), # 授权码target_email='"京东JD.com" <customer_service@jd.com>', # 发件人file_path="D:\\Test", # 保存文件路径target_addr="广州", # 发票地址(不需要判断设置为None即可)target_time="2024-11-10" # 发票时间 (不需要判断设置为None即可))client.fetch_email()client.close()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/60079.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

网络安全SQL初步注入2

六.报错注入 mysql函数 updatexml(1,xpath语法,0) xpath语法常用concat拼接 例如: concat(07e,(查询语句),07e) select table_name from information_schema.tables limit 0,1 七.宽字节注入(如果后台数据库的编码为GBK) url编码:为了防止提交的数据和url中的一些有特殊意…

three.js 杂记

在Three.js中&#xff0c;Object3D是所有3D对象的基类&#xff0c;而Group是Object3D的一个子类。Group的目的是为了简化处理多个对象的集合。当你将对象添加到Group中时&#xff0c;它们会以一个单元格的形式被处理&#xff0c;参与Group的某些操作&#xff0c;例如位置更新、…

一文熟悉新版llama.cpp使用并本地部署LLAMA

0. 简介 最近是快到双十一了再给大家上点干货。去年我们写了一个大模型的系列&#xff0c;经过一年&#xff0c;大模型的发展已经日新月异。这一次我们来看一下使用llama.cpp这个项目&#xff0c;其主要解决的是推理过程中的性能问题。主要有两点优化&#xff1a; llama.cpp …

基于 Python flask 的微博舆论情感分析,微博大数据可视化系统

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…

【编码】【特征选择】【降维】

简要介绍 编码&#xff08;Encoding&#xff09; 编码是将原始数据转换为模型能够理解和处理的格式的过程。常见的编码方法包括&#xff1a; 标签编码&#xff08;Label Encoding&#xff09;&#xff1a; 适用于类别较少的分类数据。将每个类别映射到一个唯一的整数。独热编…

大数据之多级缓存方案

多级缓存介绍&#xff1f;多级缓存优缺点&#xff0c;应用场景&#xff1f;多级缓存架构&#xff1f; 多级缓存介绍 多级缓存方案是一种优化手段&#xff0c;通过在多个级别上存储数据来提高应用程序的性能和响应速度。以下是对多级缓存方案的详细解析&#xff1a; 一、多级缓…

HBuilderX运行微信小程序,编译的文件在哪,怎么运行

1. 点击HBuilderX顶部的运行-运行到小程序模拟器-微信开发者工具&#xff0c;就会开始编译 2. 编译完成后的文件在根目录找到 unpackage -- dist -- dev -- mp-weixin, 这里面就是编译后的文件&#xff0c;如果未跳转到开发者工具&#xff0c;那可能是没设置启动路径&#xff0…

Git超详细笔记包含IDEA整合操作

git超详细笔记 文章目录 git超详细笔记第1章Git概述1.1、何为版本控制1.2、为什么需要版本控制1.3、版本控制工具1.4 、Git简史1.5、Git工作机制1.6 、Git和代码托管中心 第2章Git安装第3章Git常用命令3.1、设置用户签名3.2、初始化本地库本地库&#xff08;Local Repository&a…

人工智能理论之opencv图像预处理、数据库、GUI布局的综合应用(图像预处理版块)

文章目录 前言图像预处理卷积核概念图像平滑处理高斯滤波 双边滤波中值滤波Canny边缘检测图像形态学操作形态学梯度顶帽小结 图片预处理1.引入库 图像预处理错误尝试成功运行 总结 前言 对前面学习综合应用的总结&#xff0c;不单是一个版块&#xff0c;而是三个版块综合到一起…

Nginx(编译)+Lua脚本+Redis 实现自动封禁访问频率过高IP

1.安装lua 1.1安装LuaJIT yum install readline-devel mkdir -p lua-file cd lua-file/ wget https://github.com/LuaJIT/LuaJIT/archive/refs/tags/v2.0.5.tar.gz tar -zxvf LuaJIT-2.0.5.tar.gz cd LuaJIT-2.0.5 make && make install PREFIX/usr/local/luajit 1.2…

【python程序】恢复曾经删除的QQ说说

是否还能想起曾经的QQ说说&#xff0c;是否还想知道自己以前删除了什么 今天就给大家介绍下这个可以恢复以前删除的QQ说说的 小工具 这个工具是由python编写的&#xff0c;也已经打包好了小程序&#xff0c;一键运行 具体下载地址&#xff1a;https://pan.quark.cn/s/b3f41e3…

【统计子矩阵——部分前缀和+双指针】

题目 代码 #include <bits/stdc.h> using namespace std; typedef long long ll; const int N 510; int s[N][N]; int main() {ios::sync_with_stdio(0);cin.tie(0);int n, m, k;cin >> n >> m >> k;for(int i 1; i < n; i)for(int j 1; j <…

Java版——设计模式笔记

Java版——设计模式笔记 设计模式的分类 创建型模式&#xff08;Creational&#xff09;&#xff1a;关注对象的实例化过程&#xff0c;包括了如何实例化对象、隐藏对象的创建细节等。常见的创建型模式有单例模式、工厂模式、抽象工厂模式等。结构型模式&#xff08;Structur…

多语言电商系统的多语言设计机制

在全球化电商市场中&#xff0c;跨语言沟通是提升用户体验和扩大市场份额的关键。为了满足不同语言用户的需求&#xff0c;构建一个支持多语言的电商系统已成为企业扩展国际市场的重要步骤。多语言电商系统需要能够根据用户的语言偏好自动显示内容&#xff0c;同时保证翻译的准…

【Steam登录】protobuf协议逆向 | 续

登录接口&#xff1a; ‘https://api.steampowered.com/IAuthenticationService/BeginAuthSessionViaCredentials/v1’ 精准定位&#xff0c;打上条件断点 this.CreateWebAPIURL(t) ‘https://api.steampowered.com/IAuthenticationService/BeginAuthSessionViaCredentials/v1…

Python | Leetcode Python题解之第556题下一个更大元素III

题目&#xff1a; 题解&#xff1a; class Solution:def nextGreaterElement(self, n: int) -> int:x, cnt n, 1while x > 10 and x // 10 % 10 > x % 10:cnt 1x // 10x // 10if x 0:return -1targetDigit x % 10x2, cnt2 n, 0while x2 % 10 < targetDigit:c…

Python——数列1/2,2/3,3/4,···,n/(n+1)···的一般项为Xn=n/(n+1),当n—>∞时,判断数列{Xn}是否收敛

没注释的源代码 from sympy import * n symbols(n) s n/(n1) print(数列的极限为&#xff1a;,limit(s,n,oo))

Java基础——类和对象的定义链表的创建,输出

目录 什么是类&#xff1f; 什么是对象? 如何创建链表&#xff1f; 尾插法&#xff1a; 头插法&#xff1a; 输出链表的长度 输出链表的值 什么是类&#xff1f; 创建Java程序必须创建一个类class. .java程序需要经过javac指令将文件翻译为.class字节码文件&#xff0c…

python代码打包exe文件(可执行文件)

一、exe打包 1、构建虚拟环境 conda create -n env_name python3.8 #env_name,python根据自己需求修改2、保存和安装项目所需的所有库 pip freeze > requirements.txt3、虚拟环境安装项目包、库 pip install -r requirements.txt4、安装pyinstaller pip install pyinst…

【Linux】冯诺依曼体系结构

目录 一、冯诺依曼体系结构二、冯诺依曼体系结构的基本组成三、关于冯诺依曼体系结构的一些问题结尾 一、冯诺依曼体系结构 冯诺依曼体系结构&#xff0c;也称为普林斯顿结构&#xff0c;是现代计算机设计的基础框架。这一体系结构由数学家冯诺依曼在20世纪40年代提出&#xf…