分享

10个令人震惊的Python自动化脚本,你必须尝试

 思想年代 2024-05-15 发布于西藏

自动化是现代效率背后的推动力,在Python中找到了最佳伙伴——这是一种以其多样化的解决方案而著称的语言,旨在无缝简化任务。凭借其广泛的库支持、内置功能和蓬勃发展的贡献者社区,Python成为了简化工作流程的终极盟友,提供了无与伦比的便利。在这篇博客中,我们将探讨10个令人震惊的使用Python的自动化脚本,你需要尝试。 这是你需要尝试的自动化脚本系列的第八部分。

1、剪贴板管理器

📋你是否曾经在处理多个文本片段时,失去了对你所复制内容的跟踪?是否想过拥有一个可以跟踪你一天所复制所有内容的工具? 这个自动化脚本监视你复制的一切,无缝地将每个复制的文本存储在一个流畅的图形界面中,这样你就不必在无尽的标签页中搜索,从而避免丢失宝贵的信息。 这个自动化脚本利用Pyperclip库无缝捕捉复制的数据,并集成Tkinter来视觉跟踪和管理复制的文本。

#导入tkinter库,用于创建GUI应用程序,ttk是tkinter的扩展模块,用于提供更现代的界面元素。import tkinter astkfrom tkinterimport ttk#导入pyperclip库,可以用来复制和粘贴剪贴板内容。import pyperclip#定义函数,用于更新列表框的内容,将新的剪贴板内容添加到列表中。defupdate_listbox(): new_item = pyperclip.paste() # 获取当前剪贴板的内容 if new_item not in X: # 如果内容不在我们的列表中,则添加它 X.append(new_item) listbox.insert(tk.END, new_item) # 在列表框末尾添加新项目 listbox.insert(tk.END,'----------------------') #添加分隔线 listbox.yview(tk.END) # 自动滚动到列表框的底部 root.after(1000, update_listbox) # 每1000毫秒(1秒)调用一次此函数,不断更新#定义函数,用于处理列表框中元素的双击事件,将选中的内容复制到剪贴板。defcopy_to_clipboard(event): selected_item =listbox.get(listbox.curselection()) #获取当前选中的列表项 if selected_item: pyperclip.copy(selected_item) # 将选中的内容复制到剪贴板#创建一个空列表,用于存储剪贴板内容。X = []# 创建主窗口root = tk.Tk()root.title('ClipboardManager') # 设置窗口标题root.geometry('500x500') # 设置窗口大小root.configure(bg='#f0f0f0') # 设置窗口背景颜色#创建一个框架组件,用于放置其他界面元素frame =tk.Frame(root, bg='#f0f0f0')frame.pack(padx=10,pady=10) # 放置框架并设置边距#在框架内创建一个标签,显示文本提示label =tk.Label(frame, text='Clipboard Contents:', bg='#f0f0f0')label.grid(row=0,column=0) # 使用grid布局管理器放置标签# 创建一个滚动条scrollbar =tk.Scrollbar(root)scrollbar.pack(side=tk.RIGHT,fill=tk.Y) # 放置滚动条在窗口的右侧,填充Y方向#创建一个列表框,用于显示剪贴板的内容listbox =tk.Listbox(root, width=150, height=150, yscrollcommand=scrollbar.set)listbox.pack(pady=10) # 放置列表框并设置垂直边距scrollbar.config(command=listbox.yview) # 设置滚动条控制列表框的垂直滚动# 调用函数,开始更新列表框内容update_listbox()#绑定双击左键事件到copy_to_clipboard函数,实现双击复制功能listbox.bind('<Double-Button-1>',copy_to_clipboard)# 运行主事件循环,等待用户交互root.mainloop()

脚本应用:

·捕获并分类从各种来源复制的研究笔记。

·扩展脚本可以捕获重要的日历事件、提醒、密码等。

2、代码质量检查器

每个开发者都经历过在Python代码中追踪错误的挫败感,只是为了发现自己迷失在错误迷宫中。作为开发者,我们理解编写干净高效代码的重要性——但手动分析代码质量可能是一项压力巨大的任务。 这个自动化脚本利用Pylint和Flake8 Python包进行全面的代码质量审查。比较你的代码与编码标准,并识别逻辑错误。它确保你的代码符合行业最佳实践,并保持无错误。

#导入os模块,用于操作文件和目录。import os#导入subprocess模块,用于执行外部命令。import subprocess#定义函数analyze_code,接受一个参数directory,即要分析的目录路径。defanalyze_code(directory): # 列出目录中所有以.py结尾的文件,构成一个列表。 python_files = [file for file inos.listdir(directory) if file.endswith('.py')] # 如果没有找到Python文件,输出提示信息并返回。 if not python_files: print('No Python files found inthe specified directory.') return # 遍历找到的Python文件。 for file in python_files: print(f'Analyzing file:{file}')  # 打印正在分析的文件名。 file_path = os.path.join(directory,file)  # 获取文件的完整路径。 # 使用pylint工具分析代码质量。 print('\nRunningpylint...')  # 提示开始运行pylint。 pylint_command = f'pylint{file_path}'  # 构造pylint命令。 subprocess.run(pylint_command,shell=True)  # 执行命令,shell=True允许在命令行中运行。 # 使用flake8工具分析代码风格。 print('\nRunningflake8...')  # 提示开始运行flake8。 flake8_command = f'flake8{file_path}'  # 构造flake8命令。 subprocess.run(flake8_command,shell=True)  # 执行命令。#如果此脚本被直接运行,而不是被导入到另一个脚本中。if __name__ =='__main__': directory =r'C:\Users\abhay\OneDrive\Desktop\Part7'  # 指定要分析的目录。 analyze_code(directory)  # 调用分析函数。

脚本应用:

·自动代码增强器——稍作扩展,可以用来创建一个Python脚本,识别代码中的问题并相应地进行更改。

· 自动代码审查。

3、防篡改 🚫

文件篡改,也称为数据篡改,是指未经授权故意改变信息,可能包括销毁、操纵或编辑数据。 世界各地的许多威胁者滥用文件篡改技术,并在关键系统文件中引入不同的漏洞或后门,危害安全并实现未经授权的访问。 为了降低这种风险,验证文件的完整性至关重要,确保它们保持原始状态未被改变。这个自动化脚本可以帮助你测试任何文件,并识别它是否被篡改。

#导入hashlib模块,用于加密哈希功能。import hashlib#导入os模块,用于操作文件和目录。import os#定义函数calculate_sha256,计算文件的SHA-256哈希值。defcalculate_sha256(file_path): sha256 = hashlib.sha256() # 创建一个sha256哈希对象 # 以二进制读取模式打开文件 with open(file_path, 'rb') as file: # 读取文件内容,每次读取4096字节 for chunk in iter(lambda:file.read(4096), b''): sha256.update(chunk) # 更新哈希对象的状态 return sha256.hexdigest() # 返回哈希值的十六进制表示#定义函数check_integrity,验证文件的完整性。defcheck_integrity(file_path, expected_checksum): actual_checksum =calculate_sha256(file_path) #计算文件的实际SHA-256哈希值 return actual_checksum ==expected_checksum # 比较实际哈希值与预期哈希值是否相同# 如果此脚本被直接运行。if __name__ =='__main__': file_path = input('Enter the path tothe file: ') # 获取用户输入的文件路径 expected_checksum = input('Enter theexpected SHA-256 checksum: ') #获取用户输入的预期SHA-256哈希值 # 检查文件是否存在 if os.path.isfile(file_path): # 调用check_integrity函数验证文件完整性 if check_integrity(file_path,expected_checksum): print('File integrityverified: The file has not been tampered with.') # 验证成功 else: print('File integrity checkfailed: The file may have been tampered with.') # 验证失败 else: print('Error: File notfound.') # 文件不存在错误提示

4、智能交易

交易指的是购买和出售金融工具,如股票、债券、货币、商品或衍生品,目的是为了获利。期刊交易者整天都在查看不同的仪表板,试图找出是否买入或卖出的那一个完美决定。 这个自动化脚本可以帮助交易者和投资者很好地了解你想投资的任何股票。它使用Python的Prophet库,基于从雅虎财经获取的历史股票数据来预测近期的股票价格。

#导入Streamlit库用于创建Web应用import streamlitas st# 导入date用于处理日期from datetimeimport date#导入yfinance库,用于从Yahoo Finance获取股票数据import yfinanceas yf#导入Prophet库,用于进行时间序列预测from prophetimport Prophet#导入Prophet的Plotly绘图接口和Plotly图形对象from prophet.plotimport plot_plotlyfrom plotlyimport graph_objs as go# 设置预测的起始日期和当前日期START ='2015-01-01'TODAY =date.today().strftime('%Y-%m-%d')#使用Streamlit创建应用标题st.title('StockForecast App')# 设置一个选择框,让用户选择股票stocks = ('MSFT','TSLA', 'GOOG', 'AAPL', 'NVDA')selected_stock =st.selectbox('Select dataset for prediction', stocks)#创建一个滑动条,让用户选择预测的年数,范围从14n_years =st.slider('Years of prediction:', 1, 4)period = n_years* 365  # 将年数转换为天数#定义一个缓存函数,用于加载股票数据,避免每次会话重新加载@st.cachedefload_data(ticker): data = yf.download(ticker, START,TODAY)  # 从Yahoo Finance下载股票数据 data.reset_index(inplace=True)  # 重置DataFrame的索引 return data# 显示数据加载状态data_load_state =st.text('Loading data...')data =load_data(selected_stock)  # 调用函数加载数据data_load_state.text('Loadingdata... done!')  # 更新加载状态# 显示原始数据的最后几行st.subheader('Rawdata')st.write(data.tail())#定义函数,绘制原始数据的开盘和收盘价格defplot_raw_data(): fig = go.Figure() fig.add_trace(go.Scatter(x=data['Date'],y=data['Open'], name='stock_open')) fig.add_trace(go.Scatter(x=data['Date'],y=data['Close'], name='stock_close')) fig.layout.update(title_text='Time Seriesdata with Rangeslider', xaxis_rangeslider_visible=True) st.plotly_chart(fig)plot_raw_data()# 使用Prophet进行预测df_train =data[['Date','Close']]df_train =df_train.rename(columns={'Date': 'ds', 'Close':'y'})m = Prophet()m.fit(df_train)future =m.make_future_dataframe(periods=period)forecast =m.predict(future)# 显示并绘制预测数据st.subheader('Forecastdata')st.write(forecast.tail())st.write(f'Forecastplot for {n_years} years')fig1 =plot_plotly(m, forecast)st.plotly_chart(fig1)# 显示预测组件st.write('Forecastcomponents')fig2 =m.plot_components(forecast)st.write(fig2)

脚本应用

· 算法交易

· 股价比较仪表板

5AutoImage下载器

在计算机视觉项目中,收集图像数据是一个关键挑战。正如Andrew Ng所说,如果你能收集到大量数据集,那么算法就不重要了。数据在提高模型性能和准确性方面起着关键作用。

# 导入所需的模块和函数fromsimple_image_download import simple_image_download as simp#创建一个响应对象,用于处理图片下载response =simp.simple_image_download# 设置关键词keyword ='Dog' # 指定下载的图片关键词为“Dog”# 下载图片try: response().download(keyword, 20) # 调用下载方法,尝试下载20张关键词为“Dog”的图片 print('Images downloadedsuccessfully.') # 如果下载成功,则输出成功消息except Exceptionas e: print('An error occurred:',e) # 如果下载过程中出现异常,输出错误信息

6、端口扫描器

让我们谈谈网络安全! 在计算机网络中,端口是允许不同进程或服务连接并通过网络交换数据的通信端点。端口通过数值标识,并与特定协议相关联。

# 导入socket库用于网络连接import socket#导入PrettyTable库用于生成表格,使输出结果更易于阅读from prettytableimport PrettyTable#定义一个字典,其中包含常用端口及其潜在的安全漏洞描述vulnerabilities ={ 80: 'HTTP(超文本传输协议) - 用于非加密的网页流量', 443: 'HTTPS(安全的HTTP) -用于加密的网页流量', 22: 'SSH(安全外壳协议) - 用于安全的远程访问', 21: 'FTP(文件传输协议) - 用于文件传输', 25: 'SMTP(简单邮件传输协议) - 用于电子邮件传输', 23: 'Telnet - 用于远程终端访问', 53: 'DNS(域名系统) - 用于域名解析', 110: 'POP3(邮局协议第3版) - 用于电子邮件获取', 143: 'IMAP(互联网消息访问协议) -用于电子邮件获取', 3306: 'MySQL - 用于MySQL数据库访问', 3389: 'RDP(远程桌面协议) -用于Windows的远程桌面连接', 8080: 'HTTP备用端口 - 常用作HTTP的次要端口', 8000: 'HTTP备用端口 - 常用作HTTP的次要端口', 8443: 'HTTPS备用端口 -常用作HTTPS的次要端口', 5900: 'VNC(虚拟网络计算) - 用于远程桌面访问', # 根据需要可继续添加更多端口及其安全漏洞描述}#定义一个函数,显示开放端口及其潜在的安全问题defdisplay_table(open_ports): table = PrettyTable(['开放端口','潜在安全问题']) for port in open_ports: vulnerability =vulnerabilities.get(port, '此端口没有与常见服务相关联的已知漏洞') table.add_row([port, vulnerability]) print(table)#定义一个函数,扫描目标主机的常用端口defscan_top_ports(target): open_ports = []  # 存储开放端口的列表 top_ports = [21, 22, 23, 25, 53, 80, 110,143, 443, 3306, 3389, 5900, 8000, 8080, 8443] # 定义常见的15个端口 for port in top_ports: try: sock =socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.settimeout(1)  # 设置连接超时时间 result = sock.connect_ex((target,port)) if result == 0: open_ports.append(port) sock.close() except KeyboardInterrupt: sys.exit() except socket.error: pass return open_ports# 主函数def main(): target =input('请输入要扫描的网站URL或IP地址:') open_ports = scan_top_ports(target) if not open_ports: print('目标主机没有开放的端口。') else: print('开放的端口及其相关的潜在安全问题:') display_table(open_ports)# 如果这个脚本被直接运行if __name__ =='__main__': main()

7密码管理器

关于成为数字自由职业者最糟糕的部分之一是,你需要记住许多密码,因为你每天都在为新网站注册。 这个自动化脚本可以帮助你管理所有密码,使它们既安全又只有你能访问,使用不同的加密技术。 这个脚本的最好之处在于它是一个网络应用,这意味着通过几处修改,你可以将其部署在云存储上,并且可以在任何地方访问所有密码,而不用担心安全问题。 它使用一个硬编码的自定义密钥进行加密和解密。如果你计划在共享平台上使用这个脚本,请确保将这个密钥保存在一个单独的安全文件中。

# 导入所需的库import streamlitas stimport csvfromcryptography.fernet import Fernetfromcryptography.fernet import InvalidToken# 自定义加密密钥(硬编码)CUSTOM_ENCRYPTION_KEY= b'u7wGgNdDFefqpr_kGxb8wJf6XRVsRwvb3QgITsD5Ft4=' #如果您计划在共享平台上使用此脚本,请确保将此密钥保存在一个单独的安全文件中。# 函数用于加密密码defencrypt_password(password): cipher_suite =Fernet(CUSTOM_ENCRYPTION_KEY) encrypted_password =cipher_suite.encrypt(password.encode()) # 将密码编码后加密 return encrypted_password# 函数用于解密密码defdecrypt_password(encrypted_password): if isinstance(encrypted_password,bytes): # 检查加密密码是否为bytes类型 try: cipher_suite =Fernet(CUSTOM_ENCRYPTION_KEY) decrypted_password =cipher_suite.decrypt(encrypted_password) # 解密 returndecrypted_password.decode() #将bytes解码为字符串 except InvalidToken: return 'InvalidToken' # 若密钥不正确,返回无效令牌信息 else: return None#函数用于将网站名和密码保存到CSV文件defsave_credentials(website_name, password): encrypted_password =encrypt_password(password) # 先加密密码 with open('credentials.csv', 'a',newline='') as csvfile: writer = csv.writer(csvfile) writer.writerow([website_name,encrypted_password.decode()]) #将加密后的密码解码为字符串后存储# 函数用于从CSV文件检索密码defretrieve_password(website_name): with open('credentials.csv', 'r') ascsvfile: reader = csv.reader(csvfile) for row in reader: if row[0] == website_name: encrypted_password =row[1].encode() # 重新编码为bytes return encrypted_password return None#使用Streamlit创建Web界面st.title('密码管理器')# 输入字段用于输入网站名和密码website_name =st.text_input('输入网站名:')password =st.text_input('输入密码:', type='password')# 保存按钮用于保存网站名和密码ifst.button('保存'): if website_name and password: save_credentials(website_name,password) st.success('网站名和密码已成功保存。') else: st.error('请填写所有字段。')# 检索按钮用于检索密码ifst.checkbox('检索密码'): website_name =st.selectbox('选择网站名:', options=[''] + [row[0] for row incsv.reader(open('credentials.csv', 'r'))]) key = st.text_input('输入您的加密密钥:',type='password') if st.button('检索密码'): if key ==str(CUSTOM_ENCRYPTION_KEY.decode()): if website_name: encrypted_password =retrieve_password(website_name) if encrypted_password: decrypted_password =decrypt_password(encrypted_password) st.success(f'网站**{website_name}** 的密码 -> **{decrypted_password}**') else:st.error('数据库中未找到密码。') elif key == '': pass else: st.error('无效的加密密钥!')

8批量邮件发送器 🆕

电子邮件列表是在线互动的货币,每个订阅者都是你数字部落中的宝贵成员。它们是有效数字营销的核心。 作为一个数字影响者,与你的粉丝保持互动很重要,但手动进行这一工作很困难,使用工具则可能花费一大笔钱。 这个自动化脚本利用Gmail自己的SMTP服务器发送批量电子邮件,仅需几分钟,允许你完全自定义并掌控。 确保你不要发送垃圾邮件给接收者,否则你会被Gmail列入黑名单。尝试将你的邮件限制在每天少于100封。

#导入smtplib库用于邮件传输import smtplib# 导入ssl库用于建立安全的连接import ssl# SMTP服务器的详细信息smtp_server ='smtp.gmail.com'  # 使用的Gmail的SMTP服务器地址smtp_port =465  # 使用的端口号,Gmail的SSL端口是465# 发送者和接收者的详细信息from_address ='Winzo Shop'  # 发件人地址或名称to_address = ['','']  # 接收者列表,可以添加多个接收邮箱地址# 认证信息username =''  # 发件人的邮箱账号password =''  # 发件人的邮箱密码# 邮件内容的详细信息subject= '🎉 独家优惠!您下次购物可享受10%的折扣'body = '''\亲爱的顾客,作为我们尊贵的客户,为了表达我们的感激之情,我们为您的下次购买提供了一项独家折扣。在结账时使用下面的优惠码,您可以享受订单10%的折扣:优惠码:DISCOUNT10无论您是在寻找时尚的服饰、潮流的配饰还是高质量的产品,现在是购物并节省开支的最佳时机!探索我们的最新系列,并给自己买些特别的东西。抓紧时间!此优惠仅限时有效。不要错过节省您最爱物品的机会。立即购物:https://感谢您选择WinzoShop。我们期待着不久再次为您服务!最好的祝福,Winzo Shop'''#创建一个SSL/TLS的上下文环境context =ssl.create_default_context()#使用SSL/TLS通过SMTP服务器连接withsmtplib.SMTP_SSL(smtp_server, smtp_port, context=context) as server: # 启用调试级别,打印服务器的响应信息 server.set_debuglevel(1) # 登录SMTP服务器 server.login(username, password) # 创建电子邮件消息 message = f'From:{from_address}\r\nSubject: {subject}\r\nTo: {to_address}\r\n\r\n{body}' message = message.encode()  # 将消息转换为字节格式 # 发送邮件 server.sendmail(from_address, to_address,message)

9、Readme.md 生成器

README.md文件作为你项目的门户,提供必要信息并吸引访客进一步探索。它被认为是你仓库中最重要的文件之一,但同时也是创建起来相当耗时的。

# 导入所需的模块import osimport hashlibimport shutil# 定义函数,用于获取文件的哈希值defget_file_hash(file_path): with open(file_path, 'rb') as f: # 以二进制读取模式打开文件 returnhashlib.sha256(f.read()).hexdigest() #使用SHA-256算法计算文件的哈希值并返回#定义函数,用于整理文件夹并移动重复的文件deforganize_and_move_duplicates(folder_path): # 创建一个字典来存储基于文件扩展名的目标文件夹 extension_folders = {} # 如果不存在“Duplicates”文件夹,则创建它 duplicates_folder =os.path.join(folder_path, 'Duplicates') os.makedirs(duplicates_folder,exist_ok=True) #使用exist_ok=True避免在文件夹已存在时引发错误 # 创建一个字典来存储文件哈希值 file_hashes = {} # 遍历文件夹中的文件 for filename in os.listdir(folder_path): file_path = os.path.join(folder_path,filename) if os.path.isfile(file_path): # 确保是文件而不是目录 # 获取文件扩展名 _, extension =os.path.splitext(filename) extension = extension.lower() # 将扩展名转换为小写,以避免大小写差异导致的分类错误 # 确定目标文件夹 if extension in extension_folders: destination_folder =extension_folders[extension] else: destination_folder =os.path.join(folder_path, extension[1:]) # 移除扩展名前的点并创建目录 os.makedirs(destination_folder,exist_ok=True) extension_folders[extension] =destination_folder # 计算文件哈希值 file_hash =get_file_hash(file_path) # 检查文件是否重复 if file_hash in file_hashes: # 文件是重复的,将其移动到“Duplicates”文件夹 shutil.move(file_path,os.path.join(duplicates_folder, filename)) print(f'将重复文件 {filename}移动到 Duplicates 文件夹。') else: # 存储文件哈希值 file_hashes[file_hash] =filename # 将文件移动到目标文件夹 shutil.move(file_path,destination_folder) print(f'将 {filename} 移动到{destination_folder}')# 如果这个脚本被直接运行if __name__ =='__main__': folder_path = input('请输入您要整理的文件夹路径:') organize_and_move_duplicates(folder_path)

10、OrganizeIT 2.0

你的下载文件夹是一团乱麻吗?

当你最需要时,你是否发现自己在寻找关键文件时手忙脚乱?

你是否尝试过多次组织文件夹,但总是无法成功?

这个自动化脚本可以帮助你在几分钟内整理你的文件夹。你只需要指定你想要清理的路径,这个脚本将自动根据文件扩展名将所有文件分到不同的文件夹中。

# 导入所需的模块import osimport hashlibimport shutil# 定义函数,用于获取文件的哈希值defget_file_hash(file_path): with open(file_path, 'rb') as f:  # 以二进制读取模式打开文件 returnhashlib.sha256(f.read()).hexdigest()  #使用SHA-256算法计算文件的哈希值并返回#定义函数,用于整理文件夹并移动重复的文件deforganize_and_move_duplicates(folder_path): # 创建一个字典来存储基于文件扩展名的目标文件夹 extension_folders = {} # 如果不存在“Duplicates”文件夹,则创建它 duplicates_folder =os.path.join(folder_path, 'Duplicates') os.makedirs(duplicates_folder,exist_ok=True)  #使用exist_ok=True避免在文件夹已存在时引发错误 # 创建一个字典来存储文件哈希值 file_hashes = {} # 遍历文件夹中的文件 for filename in os.listdir(folder_path): file_path = os.path.join(folder_path,filename) if os.path.isfile(file_path):  # 确保是文件而不是目录 # 获取文件扩展名 _, extension =os.path.splitext(filename) extension = extension.lower()  # 将扩展名转换为小写,以避免大小写差异导致的分类错误 # 确定目标文件夹 if extension in extension_folders: destination_folder =extension_folders[extension] else: destination_folder =os.path.join(folder_path, extension[1:]) # 移除扩展名前的点并创建目录 os.makedirs(destination_folder,exist_ok=True) extension_folders[extension] =destination_folder # 计算文件哈希值 file_hash =get_file_hash(file_path) # 检查文件是否重复 if file_hash in file_hashes: # 文件是重复的,将其移动到“Duplicates”文件夹 shutil.move(file_path,os.path.join(duplicates_folder, filename)) print(f'将重复文件 {filename}移动到 Duplicates 文件夹。') else: # 存储文件哈希值 file_hashes[file_hash] =filename # 将文件移动到目标文件夹 shutil.move(file_path,destination_folder) print(f'将 {filename} 移动到{destination_folder}')# 如果这个脚本被直接运行if __name__ =='__main__': folder_path = input('请输入您要整理的文件夹路径:') organize_and_move_duplicates(folder_path)

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多