在生活和工作中,往往充斥着一些枯燥且乏味的事情。所以要让自己从机械地重复性劳动中解放出来,才是解放身心的正确姿势。
本文列举了我自己平时在工作和生活中的七个小场景,每个场景都是带有这样「重复性」性质的事情,一起看看我是如何用 Python 这门简单易懂的编程语言去解决这些事情吧。
全文我都以 macOS 环境来模拟实际的操作情况,当中的代码也可以在 Windows 下运行,稍微修改路径即可。
🗂场景 1:批量修改文件名
一般来说,注重信息安全的公司都不会允许员工私自安装第三方软件。这样的情况就发生在公司给我配的 Windows 笔记本上。
如果你用是的 macOS,那么你可以很快地选中相同类型的一批文件,然后右键调出系统自带的重命名功能批量修改文件命名。但是这些命名修改只能实现一些简单地头尾修改或是替换,如果想要修改文件拓展名则不行。
所以不管是用 Windows 也好,还是用 macOS 也好,我就自己写一个简单的 Python 脚本吧!假设我现在有这么一堆文件,都是 .png
为后缀的,我想把它们全部都换成 .jpg
格式。
普通版
碰上我上面说的这种无法私自安装第三方软件的用不了的情况,那么你就要自己手动一个一个右键然后重命名了。
Python 版
我可以简单利用 Python 内置的 os
库来进行文件命名的修改操作。
#!usr/bin/env python3
#coding:utf-8
import os
os.chdir(r'/Users/linxiaoyue/Desktop/pictures')
#os.listdir() 函数可以直接获取当前文件夹下所有可见文件的文件名
old_names = os.listdir(os.getcwd())
new_names = list(map(lambda x: x.replace('.png', '.jpg'), old_names))
# 使用内置的 zip 方法一一对应地进行迭代
for old_name, new_name in zip(old_names, new_names):
os.renames(old_name, new_name) #os.renames()方法直接替换文件名
print('文件已完成重命名……✅')
一般的文件名重命名到这就可以结束了。
但是如果碰到是这种中英文标点混杂的极端方式命名的文件,只想要以当中的中文来命名怎么办?
这时候就可以加入一个正则表达式的功能,可以让我们的程序更加强大。关于正则表达式的相关介绍可以参考王树义老师的这篇文章:
👉 关联阅读:如何用 Python 和正则表达式抽取文本结构化信息?
Python 正则版
#!usr/bin/env python3
#coding:utf-8
import re
import os
os.chdir(r'/Users/linxiaoyue/Desktop/rename_file')
old_names = os.listdir(os.getcwd())
###################################
def file_rename(text):
contexts = re.findall(r'[\u4e00-\u9fa5]', text)
return ''.join(contexts) + '.md'
new_names = list(map(file_rename, old_names))
###################################
for old_name, new_name in zip(old_names, new_names):
os.renames(old_name, new_name) #os.renames()方法直接替换文件名
这里我就仅调用了 Python 内置的 re
库用来实现正则表达式方法, \u4e00-\u9fa5
这一范围内的 unicode 字符已经基本涵盖了所有中文单字,可以直接将当中所有中文抽取出来后再拼贴起来。最后利用内置的 map
函数对旧文件名中的每个文件名进行替换操作,并再转换成列表形式。
这样,复杂的命名情况也能迎刃而解。
📃场景 2:工作模板
不知道你们是否有对每天工作记录的习惯?我每天到公司都会建立一个以当天日期命名的工作记录文件夹,当中存放简单的工作索引并将当天工作的所有文件都会放到里面。一方面,便于我不会将工作需要的文件乱放;另一方面,还便于我回顾我这周都做了哪些事情并给同事上报工作计划。
普通版
没学过编程的朋友可能思路就是:新建一个以当天日期命名的文件夹→新建一个 Word 或记事本→打开 Word 或记事本→复制黏贴相应模板或输入相关内容→保存文档。
如果这样做每天你可能要花上大概 5、6 分钟来做,那这样就少那么 5、6 分钟来逛少数派了(少数派打钱!逃)
Python 版
基本上我打开 Word 的次数屈指可数,因为要写报告的次数不算多;反而是 Markdown 的 .md
格式或者普通的记事本的 .txt
格式才是我比较喜欢的。所以我就通过 Python 写了一个每天自动生成模板,并创建一个 Markdown 样式的工作记录文档。基本思路如下:
- 自动新建一个以日期命名的文件夹
- 在文件夹里又新建一个
.md
格式的 Markdown 文档 - 然后在
.md
文档中写入模板
理清思路后就花了 10 分钟写了以下的代码:
#!usr/bin/env python3
#coding:utf-8
import time
import os
os.chdir(r'/Users/linxiaoyue/Desktop/')
def main():
# 创建文件夹
today_date = time.strftime(('%Y%m%d'), time.localtime()) #time.localtime()用于生成当前时间
file_path = os.getcwd() + '/{}'.format(today_date) #os.getcwd() 用于获取当前 Python 的当前路径
if os.path.exists(file_path): #检测当前路径是否已经存在文件夹
raise ValueError('🚨工作记录文件夹已存在:{}'.format(file_path))
else:
print('文件夹已生成✔')
os.mkdir(file_path) #如果路径不存在文件夹则新建一个
os.chdir(file_path)
# 模板内容
template = """# {} 工作记录
1.
2.
3.
""".format(time.strftime('%Y/%m/%d'), time.localtime())
print('✨✨✨✨✨ 模板内容生成!✨✨✨✨✨')
print(template)
# 创建模板文档
with open(r'{}工作记录.md'.format(today_date), 'w+', encoding='utf-8') as f:
f.write(template)
print('✨✨✨✨✨ 记录文件路径生成完毕!✨✨✨✨✨')
print(file_path)
if __name__ == '__main__':
main()
这里我主要就利用了 Python 内置的 os
库和 time
库。前者主要是对系统进行操作,后者顾名思义就是有关于一些时间的处理。当中模板的写法看起来好像蛮丑陋地,但是其实只有这样写才能显示出 Markdown 相关样式。
如果你是习惯性地使用电脑来记录固定格式的文档,如日记、合同等,你可以尝试一下我的这个思路。如果是涉及到生成固定模板的 Word,那我推荐你去了解一下 docx
这个第三方库。
📥场景 3:信息获取
前不久我的同事让我帮他处理一个项目的文本数据,要求很简单:将文本中带有上海相关地址的信息(区、镇、街道)进行隐藏处理。
我的思路就是:将数据中包含地址的文本和包含地址信息的文本相匹配,匹配上的文本替换成「XXX」符号。
那么问题来了,我去哪里找一个包含地址信息的文本数据呢?好在我找到了一个包含上海区、镇街道相关名称的网页,那么我如何把上面的数据拿下来呢?
普通版
换做是以前懵懂单纯的我,我肯定是:打开网页 → 复制黏贴到 Excel 中 → 去除多余空格。如果数量少其实也就手动复制黏贴了,但是数量多了肯定没辙;而且我相信我国目前的城市,下设街镇数目肯定不是那种屈指可数的……
Python版
带着「偷懒」的思维,我肯定是想着怎么从这个网站上把公开的信息给爬下来。于是就有了下面的代码:
#!usr/bin/env python3
#coding:utf-8
import requests
from bs4 import BeautifulSoup
url = 'http://www.tcmap.com.cn/shanghai/'
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36'
}
response = requests.get(url, headers=headers) #发送HTTP请求
response .encoding = 'gb18030' #设置一下网站的中文编码
soup = BeautifulSoup(response.text, 'html.parser') #使用 BeautifulSoup 进行解析
streets = []
# 找到数据对应的 html 节点,然后使用get_text()函数获取
for street in soup.find_all('a', class_='blue'):
streets.append(street.get_text())
# 最后写入到相关文件夹中
with open(r'/Users/linxiaoyue/Desktop/address.txt', 'w', encoding='utf-8') as f:
f.write('\n'.join(streets[:238]))
这里我仅用第三方的 requests
库访问链接,然后用 Beautifulsoup
库来提取页面源代码中的数据,最后将得到的数据存储到一个列表中。
不过这里注意的是,因为我爬取的这个网站应该是比较久远了,所以在网页维护上做的不是特别规范,所以也会爬取到一些其他的东西。我想要的数据到第 238 位索引截止。(感兴趣的朋友可以试着把 streets[:238]
连同方括号的所有内容去掉,看看会出现什么信息。)
拿到这些地址数据后,我就可以快速做掉同事交办的任务了!
⚙️场景 4:数据结构化
每个月发工资后,人事部都会发一封包括基本工资、五险一金等工资的相关明细,样式如下(文中金额为虚构):
可是邮件的内容都是文本,不是结构化的数据,该怎么办呢?
普通版
复制……黏贴……
Python 版
仔细观察可以看到,基本上有用的部分都是「,」英文逗号分隔,然后用「:」英文冒号隔开。那么我的思路:将文本先分别按这两个符号进行分割,然后结构化成 DataFrame
类型,最后将行列对调一下。
实现过程如下:
#!usr/bin/env python3
# coding:utf-8
import pandas as pd
import re
import os
def salaryInfo(date, content):
result = re.split(r',', content) #对逗号分割
#将分割后的数据转成 Pandas 中的 Series 类型再利用str高效 API 进行二次分割
data = (pd.Series(result)
.str
.split(':', expand=True)
)
data.columns = ['item', 'value']
#封装数值提取
def clean_salary(text):
try:
text = text.strip()
if text == '':
return 0
elif isinstance(text, (str)):
return float(text)
#巧妙利用 ValueError 报错来执行其他操作
except ValueError:
return text.strip()
#使用 DataFrame 类型下 applymap 这个高效的方法
data = data.applymap(lambda text: clean_salary(text))
#数据转置
columns = data.T.iloc[0].tolist()
all_data = data.T[1:]
all_data.columns=columns
all_data =all_data.reset_index(drop=True)
all_data['日期']=date
cols= all_data.columns.tolist()
order_cols = cols[-1:] + cols[:-1]
all_data = all_data[order_cols]
#这里方法同场景 2 的文件夹建立
FILE_PATH = 'Users/linxiaoyue/Desktop/salary.xlsx'
if not os.path.exists(FILE_PATH):
all_data.to_excel(FILE_PATH, index=False)
print('工资明细已生成……✅')
else:
print('工资明细已经存在,创建失败❌')
if __name__ == '__main__':
date = '20190101'
content = ''
salaryInfo(date=date, content=content)
这部分可能需要你对 Pandas
这个数据分析的重要第三方库有一些了解,Pandas
为我们提供了许多方便的数据操作 API,是用 Python 来进行数据分析和数据挖掘必学库之一。
这里有个巧妙的地方就在于封装的 clean_text()
函数中,我使用了 try-except
的这么一个基本框架来去将二次分割后的数据进行操作,如果不这么做的话那么整个程序到下一步时就会报错,因此无法处理对应明细的字段名称。同时因为里面不包含日期时间,所以就自己手动指定。
以上只是我最初的版本,在修改版中我同样给这个脚本添加了命令行用法, 最终呈现效果我还是很满意的:
🎭场景 5:测试数据生成
我的同事又给了我一个任务:问我能不能找大概 300 个姓名数据来作为我们给充当一下给客户展示的例子。
简单来说就是找一批人名的数据就行了。那么是不是说就是又重新要找个公开人名信息的网站,然后爬取呢?No!能有更偷懒的办法我肯定不会去重复「造轮子」(有人用代码实现类似的功能就不要自己去重新写一个)。
普通版
不学编程的我,打开百度,输入取名大全,默默复制黏贴……
Python 版
有程序思维的我,找到了一个名叫 Faker 的第三方库。此 Faker 非 LOL 的 Faker 大魔王,但是顾名思义就是与「假」有关,可以生成各种假数据。查阅官网文档后你就可以发现,它能创造一批测试数据,包括但不限于人名、公司名、地址名、时间、银行卡号……
实例如下:
from faker import Faker
fake = Faker(locale='zh-CN') #locale参数进行本地化设置
names = [fake.name() for i in range(300)]
with open(r'/Users/linxiaoyue/Desktop/names.txt', mode='w', encoding='utf-8') as f:
f.write('\n'.join(names))
仅仅几行代码量,我就直接搞定了这项任务。除了 Faker
之外,Python 还有很多好玩有趣又或是强大的第三方库,如果大家想看的话,评论留言我可以写一篇介绍一些比较好用又好玩的第三方库。(是不是自己挖了坑?)
🖼场景 6:Bing 首页每日壁纸下载
我一直觉得微软 Bing 搜索页的背景图都蛮好看的,所以打算每天一打开电脑就运行下载当天的背景图设为桌面的壁纸。可打开官网一看,好像并没有任何保存图片的选项……
普通版
打开没有保存图片的选项,似乎就说明好像不能直接保存,那么就只能去寻求第三方的壁纸软件了……
Python 版
既然网页有这个背景图,那说明肯定是已经存在图片资源,让我按 F12
打开 Chrome 浏览器开发者工具看看。
稍微检查一下,发现源代码中这一行 id="bgImgProgLoad"
的节点好像就是包含背景图片资源的源代码;再切换到 Sources
选项卡中发现直接就可以看到图片了。
然后我们再将鼠标挪到图片中选中在新窗口打开,就发现壁纸直接就呈现在我们眼前,可保存图片的选项也出现了。
再让我们看看图片的路径地址,我们可以发现源代码中的 /th?
那一段字符其实就是图片的路径地址。
所以就代码就很简单了:
#!usr/bin/env python3
#coding:utf-8
import requests
from bs4 import BeautifulSoup
from urllib.request import urlretrieve
base_url = 'https://cn.bing.com'
response = requests.get(base_url)
soup = BeautifulSoup(response.text, 'html.parser')
#提取源代码中 data-ultra-definition-src 的属性值,然后拼贴到一起
pic_path = soup.find('div', attrs={'id': 'bgImgProgLoad'})['data-ultra-definition-src']
pic_url = base_url + pic_path
urlretrieve(url=pic_url, filename=r'/Users/linxiaoyue/Desktop/today_wallpaper.jpg')
这里我还是使用 requests
+ BeautifulSoup
的组合拳,然后找到 id="bgImgProgLoad"
节点中的 data-ultra-definition-src
值和 base_url
拼贴在一起就是图片的路径了。
唯一不同的就是调用了 urllib.request
下的 urlretrieve()
函数,该函数可以打开一个链接并下载当中内容,所以就相当于是简易版的「迅雷」了。
不过这仅仅只是下载,我们还可以加入如:显示「下一张」(或上一张)壁纸、命令行实现下载等,有基础的朋友可以自己动手尝试一下。
🔗场景 7:批量获取下载链接
无论是在手机还是在 iPad 上,我都可以将 B 站视频进行缓存,但是电脑不借助第三方软件的话似乎就没办法实现缓存。那么我在 B 站看到别人从 Youtube 上搬运的一套很不错的 Python 免费教程,我又想存电脑上看咋办? 下载似乎是个好办法。
这里我就使用到 Downie 3 这一下载工具,它不仅可以解析 Youtube 链接,还能解析 B 站视频的链接。
但是如何批量获取到整个课程的所有链接呢?
普通版
通常的做法就是批量⌃Ctrl+C
复制视频页链接,然后修改后面的页数,最后再复制黏贴到下载器中。
如果是短短几个视频,那这么做也还说得过去;但是如果是超过 10 个以上,自己点击半天那么估计也得花一些时间。且如果这种需求常有的话,难免觉得自己是个机器人。
Python 版
既然学过 Python,那么是不是我可以利用循环生成相对应的页数,然后和不变的 URL 部分进行黏贴就好了?有了想法就暴躁地敲出如下代码:
#!usr/bin/env python3
#coding:utf-8
base = 'https://www.bilibili.com/video/av6785636?p=' #基础 URL
urls = [base + str(page) for page in range(1, 31)] #列表解析式生成页数
# 以「写入」模式(write)和「UTF-8」的编码格式打开一个文本,
# 并将所有连接以换行符进行分隔保存进一个.txt 文档中
with open('/Users/linxiaoyue/Desktop/urls.txt', mode='w', encoding='utf-8') as f:
f.write('\n'.join(urls))
这几行代码就简简单单地能够快速把链接快速生成,并且保存在桌面上,这样你就可以把所有东西都复制黏贴了进下载栏里了。
当然这个版本已经就可以达到我们的需求。但我不想每次都打开 VS Code 运行 Python ,可又想快速生成怎么办?那我们就以「命令行」的风格来试一下!
命令行版
#!usr/bin/env python3
#coding:utf-8
import argparse
def get_urls(url, page):
url_list = [url + str(p) for p in range(1, page+1) ]
with open(r'C:/Users/linxiaoyue/Desktop/url.txt', 'w', encoding='utf-8') as f:
f.write('\n'.join(url_list))
parser = argparse.ArgumentParser(description='批量生成下载视频链接')
parser.add_argument('--url', '-u', help='url 参数,必要参数', required=True, type=str)
parser.add_argument('--page', '-p', help='page 参数,必要参数', required=True, type=int)
args = parser.parse_args()
if __name__ == "__main__":
try:
get_urls(args.url, args.page)
except Exception as e:
print(e)
这里我借助了 Python 内置的 argparse
库,这个库可以让你以命令行地方式来运行 Python 程序。前面其他的场景其实也可以通过这个库修改成命令行式实现,篇幅有限就不过多讲解,有基础的朋友可以去研究一下。
结尾
这些事情的初衷都是因为一个字「懒」,这也并不是说明我懒惰,而是不想将时间浪费在一些机械枯燥的重复性操作上。 所以出于「偷懒」的心态,结合自己所学的技能去实现功能需求,让自己从下一次的重复操作中解放出来。 以上仅是一些我常用的小脚本,能用 Python 来做的有趣的事情还远远不止这些。 如果你们还有接触过编程或者有用编程语言做了哪些有趣的事,也欢迎补充和分享。
> 下载少数派 客户端、关注 少数派公众号 ,让你的工作更有效率 ⏱
> 特惠、好用的硬件产品,尽在 少数派sspai官方店铺 🛒
没有评论:
发表评论