一云博客 - python
type: channel
link: https://blog.yiyunt.cn/index.php/tag/python/
items: [python] Python日志记录库loguru使用指北
items: SQLAlchemy之一对多关系
items: 宝塔上部署FastAPI的步骤和一些注意点
items: Python 数据结构
items: Python利用psutil库进行监控进程和资源
items: Python 31条 pip 命令全解析
items: 14个Python自动化实战脚本
items: Python脚本利用adb进行手机控制的方法
items: python3.6根据m3u8下载mp4视频
items: python爬虫爬取视频时，实现实时进度条显示

[python] Python日志记录库loguru使用指北
type: item
date: 2024-09-01T01:51:07+08:00
description: Loguru是一个功能强大且易于使用的开源Python日志记录库。它建立在Python标准库中的logging模块之上，并提供了更加简洁直观、功能丰富的接口。Logging模块的使用见： Python日志记录库logging总结 。Loguru官方仓库见：loguru，loguru官方文档见： loguru-doc。Loguru的主要特点包括：简单易用：无需复杂的配置和定制即可实现基本的日志记录和输出。灵活的日志格式：支持自定义日志格式，并提供丰富的格式化选项。丰富的日志级别：支持多种日志级别，例如DEBUG、INFO、WARNING、ERROR和CRITICAL。多种日志目标：可以将日志输出到终端、文件、电子邮件、网络服务器等目标。强大的日志处理功能：支持日志过滤、格式化、压缩、旋转等功能。支持异步日志记录：能够极大地提升日志记录的性能。支持跨进程、跨线程的日志记录：可以安全地记录多进程、多线程应用程序的日志。Loguru与logging是Python中常用的两个日志记录库，但两者在功能和易用性方面存在一些差异，如下所示：特性Logurulogging易用性更简单易用相对复杂日志格式更灵活较简单日志级别更丰富较少日志目标更多种类较少日志处理功能更强大较弱异步日志记录支持不支持跨进程、跨线程支持支持支持总的来说，loguru在易用性、功能性和性能方面都优于logging。如果要一个简单、强大且易于使用的日志系统，loguru是一个很好的选择。而如果只是需要快速输出一些调试信息，print可能就足够了。不过，对于生产环境，使用loguru或其他日志系统通常会更加合适。Loguru安装命令如下：pip install loguru# 查看loguru版本 import loguru print(loguru.__version__) # 输出：0.7.21 使用说明1.1 基础用法简单使用 Loguru的核心概念是只有一个全局的日志记录器，也就是logger。这个设计使得日志记录变得非常简洁和一致。使用Loguru时，你不需要创建多个日志实例，而是直接使用这个全局的logger来记录信息。这不仅减少了配置的复杂性，也使得日志管理更加集中和高效。from loguru import logger logger.debug("这是一个调试信息")输出：2024-06-29 19:57:44.506 | DEBUG | __main__::3 - 这是一个调试信息Loguru日志输出默认格式如下：时间戳：表示日志记录的具体时间，格式通常为年-月-日 时:分:秒.毫秒。日志级别：表示这条日志的严重性级别。进程或线程标识：表示日志来自哪个模块或脚本。 main 表示日志来自主模块。如果是其他文件会显示文件名。文件名和行号：记录日志消息的函数名和行号。日志消息：实际的日志内容，此外loguru支持使用颜色来区分不同的日志级别，使得日志输出更加直观.日志等级Loguru可以通过简单的函数调用来记录不同级别的日志，并自动处理日志的格式化和输出。这一特点可以让使用者专注于记录重要的信息，而不必关心日志的具体实现细节。Loguru支持的日志级别，按照从最低到最高严重性排序：TRACE: 最详细的日志信息，用于追踪代码执行过程。Loguru默认情况下使用DEBUG级别作为最低日志记录级别，而不是TRACE级别。这是因为TRACE级别会产生大量的日志信息。DEBUG: 用于记录详细的调试信息，通常只在开发过程中使用，以帮助诊断问题。INFO: 用于记录常规信息，比如程序的正常运行状态或一些关键的操作。SUCCESS: 通常用于记录操作成功的消息，比如任务完成或数据成功保存。WARNING: 用于记录可能不是错误，但需要注意或可能在未来导致问题的事件。ERROR: 用于记录错误，这些错误可能会影响程序的某些功能，但通常不会导致程序完全停止。CRITICAL: 用于记录非常严重的错误，这些错误可能会导致程序完全停止或数据丢失。from loguru import logger logger.debug("这是一条跟踪消息") logger.debug("这是一条调试信息") logger.info("这是一条普通信息") logger.success("操作成功完成") logger.warning("这是一条警告信息") logger.error("这是一条错误信息") logger.critical("这是一条严重错误信息")输出：2024-06-29 19:58:11.535 | DEBUG | __main__:<module>:3 - 这是一条跟踪消息 2024-06-29 19:58:11.536 | DEBUG | __main__:<modu…

SQLAlchemy之一对多关系
type: item
date: 2024-09-01T01:17:00+08:00
description: 1.创建单表class Test(Base): __tablename__ = 'user' nid = Colume(Integer,primary_key=True,autoincrement=True) name = Colume(String(32))2.创建一对多class Team(Base): __tablename__ = 'team' tid = Colume(Integer,primary_key=True,autoincrement=True) caption = Colume(String(32)) class user(Base): __tablename__ = 'user' nid = Colume(Integer,primary_key=True,autoincrement=True) name = Colume(String(32)) team_id = Colume(Integer,ForeignKey('team.gid'))写完类，接下来就是把类转化为数据库表了。3.生成表、删除表def init_db(): #根据Base去找它的子类，把所有的子类生成表。 Base.metadata.create_all(engine) def drop_db(): #把Base所有的子类对应表删除。 Base.metadata.drop_all(engine)from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import Column, Integer, String, ForeignKey, UniqueConstraint, Index from sqlalchemy.orm import sessionmaker, relationship from sqlalchemy import create_engine engine = create_engine("mysql+pymysql://python:python@192.168.0.57:3306/python_mysql", max_overflow=5) Base = declarative_base() # 单表 class Test(Base): __tablename__ = 'test' nid = Column(Integer, primary_key=True, autoincrement=True) name = Column(String(32)) # 一对多 class Team(Base): __tablename__ = 'team' tid = Column(Integer, primary_key=True, autoincrement=True) caption = Column(String(32)) class user(Base): __tablename__ = 'user' nid = Column(Integer, primary_key=True, autoincrement=True) name = Column(String(32)) team_id = Column(Integer, ForeignKey('team.tid')) def init_db(): Base.metadata.create_all(engine) def drop_db(): Base.metadata.drop_all(engine) init_db()执行完上面代码后，就会在对应库生成test、user、group三张表，user表的group_id以group表的gid为外键。4.生成表后开始操作表，添加team表数据from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import Column, Integer, String, ForeignKey, UniqueConstraint, Index from sqlalchemy.orm import sessionmaker, relationship from sqlalchemy import create_engine engine = create_engine("mysql+pymysql://python:python@192.168.0.57:3306/python_mysql", max_overflow=5) Base = declarative_base() # 单表 class Test(Base): __tablename__ = 'tes…

宝塔上部署FastAPI的步骤和一些注意点
type: item
date: 2024-09-01T01:09:36+08:00
description: {callout color="#999999"}为了运维方便，选择直接用宝塔来管理python fastapi的项目，虽然直接部署可能性能更好更灵活，但是我选择了低层本，每个人的选择可能是不一样的，各有 考虑吧。本文的大逻辑是先写一个helloworld的程序，然后再部署到服务器上{/callout}步骤一：先本地运行一个基于fastapi的helloWorld例子，方便后面在服务器上验证编写基于FastApi的Hello World文件main.pyimport uvicorn from fastapi import FastAPI app = FastAPI() @app.get("/") def sayHi(): return {"message":"Hello world!"} # 启动uvicorn服务，默认端口8000 uvicorn myapi:api --reload if __name__ == '__main__': uvicorn.run('main:app')显示本地运行跑通，本地可以使用vscode编译器，并在运行dos命令pip install fastapi[all] uvicorn main:app --reloadreload参数是为了修改代码后的热部署，运行没有报错后可以浏览器访问： http://127.0.0.1:8000如果看到打印信息则说明OK步骤二：在宝塔上部署python的环境商店安装插件python进程管理插件Python项目管理器：管理应用实例进程守护管理器：实例进程的守护进入Python项目管理器，首先安装python版本，尽量与本地的一致，避免出现本地好的，服务器上出现问题，特别怕依赖包不一致的问题。本地查看版本的命令是python --version在本地生成requirements.txt，否则宝塔创建项目会报错。创建命令如下pip freeze >requirements.txt pip install -r requirements.txt将代码上传到宝塔的/www/wwwpython/helloworld在python进程管理插件创建项目，具体参数如下，记得选择gunicon在配置修改参数，重启。默认为worker_class = 'geventwebsocket.gunicorn.workers.GeventWebSocketWorker' 修改为worker_class = 'uvicorn.workers.UvicornWorker'这里有一个坑，启动后系统会自动暂停，日志报错如下的话，是2个问题，一是启动文件名为main.py，二是启动文件是app，即在main.py中启动命令是：uvicorn.run('main:app')具体报错信息如下：Worker failed to boot.Traceback (most recent call last): File "/www/wwwpython/helloworld/helloworld_venv/lib/python2.7/site-packages/gunicorn/arbiter.py", line 586, in spawn_worker worker.init_process() File "/www/wwwpython/helloworld/helloworld_venv/lib/python2.7/site-packages/gunicorn/workers/ggevent.py", line 203, in init_process super(GeventWorker, self).init_process() File "/www/wwwpython/helloworld/helloworld_venv/lib/python2.7/site-packages/gunicorn/workers/base.py", line 135, in init_process self.load_wsgi() File "/www/wwwpython/helloworld/helloworld_venv/lib/python2.7/site-packages/gunicorn/workers/base.py", line 144, in load_wsgi self.wsgi = self.app.wsgi() File "/www/wwwpython/helloworld/helloworld_venv/lib/python2.7/site-packages/gunicorn/app/base.py", line 67, in wsgi self.callable = self.load() …

Python 数据结构
type: item
date: 2024-06-06T21:12:42+08:00
description: 逻辑结构特点：只是描述数据结构中数据元素之间的联系规律是从具体问题中抽象出来的数学模型，是独立于计算机存储器的(与机器无关)逻辑结构分类线性结构集合中必存在唯一的一个 "第一个元素"集合中必存在唯一的一个 "最后的元素"除最后元素之外，其他数据元素均有唯一的 "后继"除第一元素之外，其他数据元素均有唯一的 "前驱"树形结构(层次结构)树形结构指的是数据元素之间存在着"一对多"的树形关系的数据结构，是一类重要的非线性数据结构。在树形结构中，树根结点没有前驱结点，其余每个结点有且只有一个前驱结点。叶子结点没有后续结点，其余每个结点的后续节点数可以是一个也可以是多个。图状结构（网状结构)图是一种比较复杂的数据结构。在图结构中任意两个元素之间都可能有关系，也就是说这是一种多对多的关系。其他结构除了以上几种常见的逻辑结构外，数据结构中还包含其他的结构，比如集合等。有时根据实际情况抽象的模型不止是简单的某一种，也可能拥有更多的特征。存储结构特点:是数据的逻辑结构在计算机存储器中的映象（或表示)存储结构是通过计算机程序来实现的，因而是依赖于具体的计算机语言的。存储结构分类顺序存储顺序存储( Sequential Storage ):将数据结构中各元素按照其逻辑顺序存放于存储器一片连续的存储空间中。链式存储链式存储(Linked Storage )∶将数据结构中各元素分布到存储器的不同点，用记录下一个结点位置的方式建立它们之间的联系，由此得到的存储结构为链式存储结构。索引存储索引存储（ lndexed Storage ):在存储数据的同时，建立一个附加的索引表，即索引存储结构=数据文件+索引表。线性表的链式存储只能操作头部节点指向下一个定义将线性表L=(a0,a1.......an-1)中各元素分布在存储器的不同存储块，称为结点，每个结点（尾节点除外）中都持有一个指向下一个节 点的引用，这样所得到的存储结构为链表结构。特点逻辑上相邻的元素ai, ai+1，其存储位置也不一定相邻;存储稀疏，不必开辟整块存储空间。对表的插入和删除等运算的效率较高。逻辑结构复杂，不利于遍历。栈先进后出 --> 水桶定义栈是限制在一端进行插入操作和删除操作的线性表（俗称堆栈），允许进行操作的一端称为"栈顶”，另一固定端称为"栈底”，当栈中没有元素时称为空栈"。特点栈只能在一端进行数据操作栈模型具有先进后出或者叫做后进先出的规律队列先进先出 --> 排队定义队列是限制在两端进行插入操作和删除操作的线性表，允许进行存入操作的一端称为队尾”，允许进行删除操作的一健称为“队就-b特点:队列只能在队头和队尾进行数据操作队列模型具有先进先出或者叫做后进后出的规律树形结构定义树( Tree )是n ( n≥0 )个节点的有限集合T，它满足两个条件∶有且仅有一个特定的称为根(Root )的节点;其余的节点可以分为m ( m≥0 )个互不相交的有限集合T1、T2、......、Tm，其中每一个集合又是一棵树，并称为其根的子树( Subtree ) 。基本概念一个节点的子树的个数称为该节点的度数，一棵树的度数是指该树中节点的最大度数。度数为零的节点称为树叶或终端节点，度数不为零的节点称为分支节点，除根节点外的分支节点称为内部节点。一个节点的子树之根节点称为该节点的子节点，该节点称为它们的父节点，同一节点的各个子节点之间称为兄弟节点。一棵树的根节点没有父节点，叶节点没有子节点。一个节点系列k1,k2，......,ki,ki+1,......,kj,并满足ki是ki+1的父节点，就称为一条从k1到kj的路径，路径的长度为j-1,即路径中的边数。路径中前面的节点是后面节点的祖先，后面节点是前面节点的子孙。节点的层数等于父节点的层数加一，根节点的层数定义为树中节点层数的最大值称为该树的高度或深度。m ( m≥0 ）棵互不相交的树的集合称为森林。树去掉根节点就成为森林，森林加上一个新的根节点就成为树。二叉树定义二叉树( Binary Tree )是n ( n≥0 )个节点的有限集合，它或者是空集( n=0 ），或者是由一个根节点以及两棵互不相交的、分别称为左子树和右子树的二叉树组成。二叉树与普通有序树不同，二叉树严格区分左孩子和右孩子，即使只有一个子节点也要区分左右。二叉树的特征工叉树第i ( i≥1)层上的节点最多为2i-1个。深度为k ( k≥1)的二叉树最多有2k一1个节点。在任意一棵二叉树中，树叶的数目比度数为2的节点的数目多一。满二叉树︰深度为k ( k≥1)时有2k一1个节点的二叉树。完全二叉树∶只有最下面两层有度数小于2的节点，且最下面一层的叶节点集中在最左边的若干位置上。二叉树的遍历沿某条搜索路径周游二叉树，对树中的每一个节点访问一次且仅访问一次。先序遍历︰先访问树根，再访问左…

Python利用psutil库进行监控进程和资源
type: item
date: 2024-04-30T14:51:02+08:00
description: 《Python利用psutil库进行监控进程和资源》psutil是Python系统和进程工具库,它提供了一种跨平台的方式来获取系统信息、管理系统进程、监控系统性能、操作系统资源等,下面就跟随小编一起来... python作为一门强大的编程语言，拥有丰富的标准库和第三方库，使得开发者可以轻松完成各种任务。在系统监控和管理方面，psutil库无疑是一个强大的工具，它可以轻松地获取系统信息、管理进程、监控系统性能等。本文将深入探讨psutil库，介绍它的基本概念、用法和示例代码，帮助大家更好地理解和利用这个强大的库。什么是psutil库psutil是Python系统和进程工具库（Python System and Process Utilities）。它提供了一种跨平台的方式来获取系统信息、管理系统进程、监控系统性能、操作系统资源等。无论是在Windows、linux还是MACOS，psutil都能提供一致的API，使得开发者可以轻松地编写跨平台的代码。安装psutil库要开始使用psutil库，首先需要安装它。可以使用pip来进行安装：pip install psutil安装完成后，就可以导入并开始使用psutil库了。import psutil获取系统信息获取CPU信息import psutil # 获取CPU核心数 cpu_count = psutil.cpu_count(logical=False) print(f"Physical CPU Count: {cpu_count}") # 获取逻辑CPU核心数（包括超线程） logical_cpu_count = psutil.cpu_count(logical=True) print(f"Logical CPU Count: {logical_cpu_count}") # 获取CPU使用率 cpu_usage = psutil.cpu_percent(interval=1, percpu=True) for i, usage in enumerate(cpu_usage, 1): print(f"CPU {i} Usage: {usage}%")获取内存信息import psutil # 获取内存总量 total_memory = psutil.virtual_memory().total print(f"Total Memory: {total_memory / (1024 ** 3):.2f} GB") # 获取可用内存 available_memory = psutil.virtual_memory().available print(f"Available Memory: {available_memory / (1024 ** 3):.2f} GB") # 获取内存使用率 memory_usage = psutil.virtual_memory().percent print(f"Memory Usage: 1.15MB%")获取磁盘信息import psutil # 获取所有磁盘分区信息 disk_partitions = psutil.disk_partitions() for partition in disk_partitions: print(f"Device: {partition.device}") print(f"Mountpoint: {partition.mountpoint}") print(f"Fstype: {partition.fstype}") print("") # 获取指定分区的使用情况 disk_usage = psutil.disk_usage("/") print(f"Total: {disk_usage.total / (1024 ** 3):.2f} GB") print(f"Used: {disk_usage.used / (1024 ** 3):.2f} GB") print(f"Free: {disk_usage.free / (1024 ** 3):.2f} GB") print(f"Usage: {disk_usage.percent}%")获取网络信息import psutil # 获取网络接口列表 network_interfaces = psutil.net_if_addrs() for interface, addresses in network_interfaces.items(): print(f"Interface: {interface}") for address in addresses: print(f" Family: {address.family}") print(f" Addres…

Python 31条 pip 命令全解析
type: item
date: 2024-04-18T09:45:30+08:00
description: 首先，pip 是个啥？简单来说，pip 就是 Python 的包管理器，就像手机里的应用商店一样，可以方便地帮你安装、升级或卸载 Python 的各种第三方库。命令 1：安装 pip如果你是Python新手，很可能系统已经自带pip。验证是否已安装，只需在命令行输入：python -m pip --version若未安装，可参考官方指引进行安装。命令 2：安装 Python 库想装个requests库试试水？一句命令搞定！pip install requests这就是pip最基础也是最常见的用法，它会自动处理库及其依赖关系。命令 3：升级库世界日新月异，库也要保持最新状态。要升级已安装的所有库：pip list --outdated # 查看待升级库 pip upgrade <package_name> # 升级指定库命令 4：卸载库不再需要某个库时，我们可以这样卸载：pip uninstall <package_name>命令 5：搜索库在决定安装某个库之前，你可能想先了解下有哪些可用的库能满足你的需求。这时可以使用 search 命令：pip search <keyword>比如查找与机器学习相关的库，你可以输入 pip search machine learning 。命令 6：查看已安装库详细信息想知道已安装的库具体版本和其他详情？ show 命令可以帮助你：pip show <package_name>命令 7：只下载库而不安装有时你可能需要离线环境安装包或者备份当前环境的依赖，那么可以使用 download 命令只下载不安装：pip download <package_name>命令 8：创建requirements文件在项目开发中，为了方便团队成员统一环境，我们可以创建一个包含所有依赖的 requirements 文件：pip freeze > requirements.txt这会列出当前环境中所有已安装库及其版本，并保存到 requirements.txt 文件中。而要根据这个文件安装所有依赖，只需：pip install -r requirements.txt命令 9：指定库版本安装在某些情况下，你可能需要安装特定版本的库，比如安装 requests 库的2.25.1版本：pip install requests==2.25.1命令 10：检查是否存在安全漏洞pip 配合 Safety 工具可以检查已安装库的安全性：pip install safety safety check --full-report这会扫描所有已安装的库，并报告是否有已知的安全漏洞。命令 11：创建虚拟环境并激活为了避免不同项目间依赖冲突，我们通常会在每个项目下创建独立的虚拟环境，然后使用 pip 进行管理：python -m venv my_project_env # 创建虚拟环境 source my_project_env/bin/activate # Linux/Mac激活环境 my_project_env\Scripts\activate.bat # Windows激活环境在虚拟环境中，你可以放心使用 pip 安装和管理项目的专属依赖。命令 12：清理未使用的库或缓存随着项目迭代，有些不再使用的库可能会被遗忘，这时可以使用 autoremove 命令来清除：pip-autoremove <package_name>同时，你也可以清理 pip 下载缓存以释放磁盘空间：pip cache purge命令 13：查看 pip 自身的版本信息及更新 pip要查看 pip 本身的版本，只需运行：pip --version为了确保 pip 始终保持最新，可使用如下命令升级 pip 自身：python -m pip install --upgrade pip当然，pip 的功能确实丰富多样，让我们继续探索：命令 14：指定源安装库在某些网络环境下，可能需要从国内镜像或者其他自定义源下载和安装库。例如使用阿里云的Python 镜像源：pip install -i https://mirrors.aliyun.com/pypi/simple/ <package_name>或永久更改 pip 默认源（推荐在配置文件中修改）：pip config set global.index-url https://mirrors.aliyun.com/pypi/simple/命令 15：分发本地构建的库如果你自己开发了一个 Python 包，并希望在本地测试安装，可以先打包成 whl 或 tar.gz 格式，然后通过 pip 进行安装：# 假设你已经将项目打包为my_package-0.1.0.whl pip install ./my_package-0.1.…

14个Python自动化实战脚本
type: item
date: 2024-04-18T09:24:06+08:00
description: 1、批量文件重命名神器在工作中，我们常常需要对大量文件进行批量重命名，Python帮你轻松搞定！ import os def batch_rename(path, prefix='', suffix=''): for i, filename in enumerate(os.listdir(path)): new_name = f"{prefix}{i:03d}{suffix}{os.path.splitext(filename)[1]}" old_file = os.path.join(path, filename) new_file = os.path.join(path, new_name) os.rename(old_file, new_file) # 使用示例： batch_rename('/path/to/your/directory', 'file_', '.txt')2、自动发送邮件通知告别手动发送，用Python编写定时发送邮件的自动化脚本。import smtplib from email.mime.text import MIMEText def send_email(to_addr, subject, content): smtp_server = 'smtp.example.com' username = 'your-email@example.com' password = 'your-password' msg = MIMEText(content) msg['Subject'] = subject msg['From'] = username msg['To'] = to_addr server = smtplib.SMTP(smtp_server, 587) server.starttls() server.login(username, password) server.sendmail(username, to_addr, msg.as_string()) server.quit() # 使用示例： send_email('receiver@example.com', '每日报告提醒', '今日报告已生成，请查收。')3、定时任务自动化执行使用Python调度库，实现定时执行任务的自动化脚本。import schedule import time def job_to_schedule(): print("当前时间：", time.ctime(), "任务正在执行...") # 定义每天9点执行任务 schedule.every().day.at("09:00").do(job_to_schedule) while True: schedule.run_pending() time.sleep(1) # 使用示例： # 运行此脚本后，每天上午9点会自动打印当前时间及提示信息4、数据库操作自动化简化数据库管理，Python帮你自动化执行CRUD操作。import sqlite3 def create_connection(db_file): conn = None try: conn = sqlite3.connect(db_file) print(f"成功连接到SQLite数据库：{db_file}") except Error as e: print(e) return conn def insert_data(conn, table_name, data_dict): keys = ', '.join(data_dict.keys()) values = ', '.join(f"'{v}'" for v in data_dict.values()) sql = f"INSERT INTO {table_name} ({keys}) VALUES ({values});" try: cursor = conn.cursor() cursor.execute(sql) conn.commit() print("数据插入成功！") except sqlite3.Error as e: print(e) # 使用示例： conn = create_connection('my_database.db') data = {'name': 'John Doe', 'age': 30} insert_data(conn, 'users', data) # 在适当时候关闭数据库连接 conn.close()5、网页内容自动化抓取利用BeautifulSoup和requests库，编写Python爬虫获取所需网页信息。import requests from bs4 import BeautifulSou…

Python脚本利用adb进行手机控制的方法
type: item
date: 2024-03-29T10:25:41+08:00
description: 这篇文章主要介绍了Python脚本利用adb进行手机控制的方法，文中通过示例代码介绍的非常详细，对大家的学习或者工作具有一定的参考学习价值，需要的朋友们下面随着小编来一起学习学习吧一. adb 相关命令：关闭adb服务：adb kill-server启动adb服务 adb start-server查询当前运行的所有设备 adb devices可能在adb中存在多个虚拟设备运行 可以指定虚拟设备运行 -s 虚拟设备名称重启设备 adb reboot --指定虚拟设备 adb -s 设备名称 reboot查看日志 adb logcat 清除日志 adb logcat -c进入linux shell下 adb shell 其中常用的linux命令 cd cat 等等 输入su可以获取超级管理员名称了 要确定是否有哪些命令 进入 system/bin目录 就知道了传入文件到设备中 adb push 本地文件 远程目录从设备中拷贝文件到本地 adb -s emulator-5556 pull /data/config.ini d:/显示当前运行的全部模拟器： adb devices安装应用程序： adb install -r 123.apk获取模拟器中的文件： adb pull 向模拟器中写文件： adb push 进入模拟器的shell模式： adb shell卸载apk包： adb shell cd data/app rm 123.apk exit adb uninstall 123.apk adb install -r 123.apk查看adb命令帮助信息： adb help删除系统应用： adb remount （重新挂载系统分区，使系统分区重新可写）。 adb shell cd system/app rm 123.apk获取管理员权限： adb root19、复制文件：复制一个文件或目录到设备：adb push 如：adb push update.zip /sdcard/从设备上复制一个文件或目录：adb pull 如：adb pull /sdcard/update.zip.20、取得当前运行设备的实例的列表及每个实例的状态：adb devices21：这条命令模拟android手机在屏幕坐标（X,Y）处进行了点击操作。adb shell input tap22：这条命令模拟Android手机从屏幕坐标（X1,Y1）滑动到坐标（X2,Y2）的操作。adb shell input swipe 23:Luiautomator dump dump: creates an XML dump of current UI hierarchy 这个命令是用来成成当前界面的UI层次，并用XML格式进行展示 。这样就可以获取各个组件的位置了注：如果PC要想同时控制多台Android手机，必须在adb 后面添加-s例如：adb -s 13b6e4c4 shell input tap 400 400表示对13b6e4c4这台Android手机进行在屏幕上（400,400）坐标位置进行模拟的点击事件。24.能看到设备信息就代表设备已经连接成功了，接下来的命令就是adb install 路径+包名.apk例如我的安装包放在桌面，那么命令就是adb install C:\Users\hyh\Desktop\XXX.apk* adb shell uiautomator dump /mnt/sdcard/window_dump.xml 获得手机当前界面的UI信息，生成window_dump.xml* adb shell input text “123” 输入text举例：1、打开cmd，进入到当前文件夹中，输入命令 adb devices 查看当前与电脑连接的设备（前提是，手机打开usb调试模式），可以查看已连接成功的手机。2、 若手机成功连接，输入命令 adb shell input tap 100 100 , 表示点击屏幕上坐标为（100，100）的点，如果不知道需要点击的点的具体位置的话可以在手机开发者模式中设置。二. adb 模拟按键：比如使用 adb shell input keyevent 命令，不同的 keycode 能实现不同的功能，完整的 keycode 列表详见 KeyEvent，摘引部分我觉得有意思的如下:Keycode含义3HOME 键4返回键5打开拨号应用6挂断电话24增加音量25降低音量26电源键27拍照（需要在相机应用里）64打开浏览器82菜单键85播放/暂停86停止播放87播放下一首88播放上一首122移动光标到行首或列表顶部123移动光标到行末或列表底部126恢复播放127暂停播放164静音176打开系统设置187切换应用2…

python3.6根据m3u8下载mp4视频
type: item
date: 2024-03-28T17:36:32+08:00
description: 这篇文章主要为大家详细介绍了python3.6根据m3u8下载mp4视频，具有一定的参考价值，感兴趣的小伙伴们可以参考一下需要下载某网站的视频，chrome浏览器按F12打开开发者模式，发现视频链接是以"blob:http"开头的链接，打开这个链接后找不到网页，网上查了下，找到了下载方法，在这里做个记录，如果有错误，欢迎指出。程序在Windows 10下运行，不过Linux应该也没问题。使用到的有re模块，requests模块和Crypto模块，其中requests模块和Crypto模块如果没安装可以使用pip命令安装。（Crypto模块安装感觉比较坑，我是从anaconda里拷贝了一份）下面开始正题：注：以下使用的m3u8文件所在的网站是自己搭建用来测试的，链接可能会失效。首先在chrome的network里找到一个m3u8文件的请求，可以通过它下载视频。通过Preview可以看到m3u8文件的内容。这里m3u8文件比较重要的内容有两个。一个是URI后面的链接，这个是加密和解密的秘钥，如果m3u8文件里有这个URI，那么这个视频就是经过了加密的，加密的方法可以看URI前面，这里是AES-128加密算法。另一个是以ts结尾链接，这个是视频片段，如果是没进行加密的，可以直接打开这个链接下载视频片段，下载下来的是后缀为ts的文件，一般可以直接播放，不过时间很短。如果是加密过的，下载后播放会提示视频文件已损坏。知道这些后，就可以进行下载了，先获取m3u8文件的内容，然后解析出秘钥（key）和ts的链接，然后下载key对每一个ts进行解密，保存到一个mp4文件里。下载用的是requests模块，解析key和ts的链接是用的re模块，解密用的是Crypto模块。使用Crypto需要注意三个地方，一个是安装和导入，第二个是Crypto里AES.new的参数，第三个是decrypt方法的参数。下面先看代码。导入模块：import re import requests from Crypto.Cipher import AES初始设置：# 保存的mp4文件名 name = "dream_it_possible.mp4" # m3u8文件的url url = "http://www.jiuyi.info/static/video/secret/dream_it_possible.m3u8" # 请求头，不一定需要，看网站更改 headers = { "Referer": "http://www.jiuyi.info/video/dream_it_possible", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 " "(KHTML, like Gecko) Chrome/71.0.3578.80 Safari/537.36", }获取m3u8文件内容，并解析出key和ts文件的url。# 获取m3u8文件内容 r = requests.get(url) # 通过正值表达式获取key和ts的url k = re.compile(r"http://.*?\.key") # key的正则匹配 t = re.compile(r"http://.*?\.ts") # ts的正则匹配 key_url = k.findall(r.text)[0] # key的url ts_urls = t.findall(r.text) # ts的url列表下载并解密ts文件，保存为mp4文件。# 下载key key = requests.get(key_url).content # 解密并保存ts for ts_url in ts_urls: ts_name = ts_url.split("/")[-1] # ts文件名 # 解密，new有三个参数， # 第一个是秘钥（key）的二进制数据， # 第二个使用下面这个就好 # 第三个IV在m3u8文件里URI后面会给出，如果没有，可以尝试把秘钥（key）赋值给IV sprytor = AES.new(key, AES.MODE_CBC, IV=key) # 获取ts文件二进制数据 ts = requests.get(ts_url).content # 密文长度不为16的倍数，则添加二进制"0"直到长度为16的倍数 while len(ts) % 16 != 0: ts += b"0" # 写入mp4文件 with open(name, "ab") as file: # decrypt方法的参数需要为16的倍数，如果不是，需要在后面补二进制"0" file.write(sprytor.decrypt(ts)) print(…

python爬虫爬取视频时，实现实时进度条显示
type: item
date: 2024-03-28T17:05:12+08:00
description: 一、全部代码展示from contextlib import closing from requests import get url = 'https://v26-web.douyinvod.com/57cdd29ee3a718825bf7b1b14d63955b/615d475f/video/tos/cn/tos-cn-ve-15/72c47fb481464cfda3d415b9759aade7/?a=6383&br=2192&bt=2192&cd=0%7C0%7C0&ch=26&cr=0&cs=0&cv=1&dr=0&ds=4&er=&ft=jal9wj--bz7ThWG4S1ct&l=021633499366600fdbddc0200fff0030a92169a000000490f5507&lr=all&mime_type=video_mp4&net=0&pl=0&qs=0&rc=ank7OzU6ZnRkNjMzNGkzM0ApNmY4aGU8MzwzNzo3ZjNpZWdiYXBtcjQwLXNgLS1kLTBzczYtNS0tMmE1Xi82Yy9gLTE6Yw%3D%3D&vl=&vr=' with closing(get(url, stream=True)) as response: chunk_size = 1024 # 单次请求最大值 # response.headers['content-length']得到的数据类型是str而不是int content_size = int(response.headers['content-length']) # 文件总大小 data_count = 0 # 当前已传输的大小 with open('文件名.mp4', "wb") as file: for data in response.iter_content(chunk_size=chunk_size): file.write(data) done_block = int((data_count / content_size) * 50) # 已经下载的文件大小 data_count = data_count + len(data) # 实时进度条进度 now_jd = (data_count / content_size) * 100 # %% 表示% print("\r [%s%s] %d%% " % (done_block * '█', ' ' * (50 - 1 - done_block), now_jd), end=" ")注：上面的url已过期，需要各位自己去找网页上的视频url二、解释1.with closing我们在日常读取文件资源时，经常会用到with open() as f:的句子。但是使用with语句的时候是需要条件的，任何对象，只要正确实现了上下文管理，就可以使用with语句，实现上下文管理是通过__enter__和__exit__这两个方法实现的。with用法（没有实现上下文管理）class Door(): def open(self): print('Door is opened') def close(self): print('Door is closed') with Door() as d: d.open() d.close()结果报错了：with用法（实现上下文管理）用__enter__和__exit__实现了上下文管理class Door(): def open(self): print('Door is opened') def close(self): print('Door is closed') with Door() as d: d.open() d.close() 结果没报错： closing用法（完美解决上述问题）一个对象没有实现上下文，我们就不能把它用于with语句。这个时候，可以用 contextlib 中的closing()来把该对象变为上下文对象。class Door(): def __enter__(self): print('Begin') return self def __exit__(self, exc_type, exc_value, traceback): if exc_type: print('Error') else: print('End') def open(self): print('Door is opened') def close(self): print('Door is closed') with Door() as d: d.open() d.close()例如：用with语句使用requests中的get(url)…