每天在工作和生活中做的事,我如何用 Python 让它们变得更轻松?
2019-10-21 12:35:45 Author: sspai.com(查看原文) 阅读量:307 收藏

在生活和工作中,往往充斥着一些枯燥且乏味的事情。所以要让自己从机械地重复性劳动中解放出来,才是解放身心的正确姿势。

本文列举了我自己平时在工作和生活中的七个小场景,每个场景都是带有这样「重复性」性质的事情,一起看看我是如何用 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 样式的工作记录文档。基本思路如下:

  1. 自动新建一个以日期命名的文件夹
  2. 在文件夹里又新建一个 .md 格式的 Markdown 文档
  3. 然后在 .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官方店铺 🛒


文章来源: https://sspai.com/post/57061
如有侵权请联系:admin#unsafe.sh