这是一个目录的标题
一点感慨
断断续续使用Python快两年了,从一开始的半窍不通,到看小甲鱼python课程从列表字典学起(学了一半),到后来出于工作照喵画虎东拼西凑写代码简化工作,写点小程序,现在是否能称得上初入大门了呢?不过很多东西还只限于了解皮毛,写个文记录一下用过的内容,随用更新。
1 爬虫
去年公司突发奇想换了新系统,新系统完全由自己团队研发,bug频出,现在行情不好,总部技术人员又来一批走一批,导致城市公司的需求排期遥遥无期,所以爬的最多的居然是自己公司的系统…不给我开发就自己整|ー` )
#可以亘古不变的开头
import requests
from bs4 import BeautifulSoup
import time
Session方法模拟登录
#登录
url = 'www.abcd.com'
headers = {
'User-Agent': 'balabaldetails'
}
s = requests.Session()
resp = s.get(url=url, headers = headers)
s = requests.Session()
resp_get = s.get(url, headers = headers)
bs = BeautifulSoup(resp_get.content.decode(), 'lxml')
ex = bs.find('input',attrs = {'name': 'execution'}).get('value')
print('拿到ex了')
form_data = {
'username': '123',
'password': '***',
'deviceCode': '123',
'execution': ex,
'_eventId': 'submit'
}
resp = s.post(url, headers = headers,data = form_data)
获取Cookies
cookies_list = [] #列表
for key, value in resp_get.cookies.items():
cookie = key + '=' + value
cookies_list.append(cookie)
#print(key,'=', value)
接下来就有好几种方法处理resp了,看情况用
1.1 json
json_get = json.loads(resp.text)
1.2 bs
soup = BeautifulSoup(resp_get.content.decode(), 'lxml')
b = soup.find('tbody',attrs = {'id':'addTr'}).tr.find_all('td')
#由于find_all找出来是个列表,不能直接.text,所以这里利用列表做个循环,例如
c = [div.span.text
for div in soup.find_all('div',attrs = {'class':'ItemP'})]
1.3 re
其实一直懒得看正则。。最近才开始学,起因是FF14高级触发器要用正则写,书到用时方恨少,于是紧急花了一个周末的两个早晨去研究。
实际看下来还挺有意思,感觉像在用一种普通人看不明白的加密语言和机器交流(想到了Spy Family的欧豆桑一边主持HimeSama的城堡party一边用脚给Spy发摩斯密码的场景,真的很酷)
目前只会写些简单的,刚了解了下懒惰匹配和贪婪匹配,至于什么?<=?>就…还没搞明白@-@
pattern = re.compile(r'(^正则表达式$)')
search = re.search(pattern, resp.text)
之前遇到一个例子,我想查找特定字符之前最近的某个字符,例如下面这段话:
图书A,作者:张三
出版社:人民出版社
图书B,作者:李四
出版社:大猫出版社
图书C,作者:王五
出版社:大猫出版社
我想获得的是,大猫出版社出版的书的作者名称
一开始这样写的
作者:[\s\S]*?大猫出版社
但这样匹配的逻辑是从左往右出现的第一个“作者”,到最短的“大猫出版社”为止
红下划线是我想要的范围
搜索了也没找到解决方法(我也很难描述这个问题)
最后实际使用时,由于一次不能满足需求,就在结果上又用了一次正则匹配姑且得到了想要的结果
1.4 etree
不得不说这应该是最简单方便的方法(如果结点名不重复)
强大的Chrome提供了右键直接复制结点树的功能…代码都不用写了直接复制进去,谢谢你谷歌
#放个模板
html = etree.HTML(resp.text)
result = html.xpath('//*[@id="base_info"]/div[2]/div[2]/div[1]/div/a/text()')
2 Pandas和Numpy
本来学python是看中了广告铺天盖地打的自动化功能
虽然人家说的是没错,然而这块我用的最少…因为我们的数据有很多需要修改,很多都不是能直接用系统导出数据(事儿多的业务不用系统规则,额外制定了一堆规则让我手动调业绩),所以目前只用在处理一些不怎么需要调整的数据上
又是可以亘古不变的开头
import numpy as np
import pandas as pd
import time
import os
from datetime import datetime, timedelta
说起来其实我分不清哪些是time的哪些是datetime的,所以干脆一并全导入
2.1 一些简单处理
def imported(files):
print('正在读取:'+ files)
df = pd.read_excel(files)
return df
#StartT = str(input('输入开始日期:(例如“2021-12-01”)'))
EndM = str(input('输入结束月份:(例如“1”)'))
EndD = str(input('输入结束日:(例如“23”)'))
EndT = EndM + '.' + EndD
#整理时发现自己偷了个懒年份直接写2022了
thisM = datetime(2022,int(EndM),1,0,0,0) #本月起始时间
thisW = datetime(2022,int(EndM),int(EndD),23,59,59) #本周结束时间
lastW = thisW - timedelta(days=7) #本周开始时间
res = pd.DataFrame([]) #建一个空表等着合并
filename = 'D:\\A表名' + EndT + '.xlsx'
df1 = imported(filename)
#替换某列的文字(和Excel的区别在于它不是部分文字匹配)
df1['要替换的列名'].replace(['原词A','原词B'], ['新词A','新词B'],inplace = True)
#分列
df1['Day'] = df1['时间'].str.split(' ',expand = True)[0]
#关键字组合去重
df1.drop_duplicates(subset = ['Key1','Key2','Key3'],keep='first',inplace=True)
#原始数据时间列不是datetime格式,新建一列用来放整理过的时间
df1['date'] = pd.to_datetime(df1['带看录入时间'],format='%Y-%m-%d')
#设置为索引以供筛选日期
time_dk = df1.set_index(['date'])
#排序以供筛选日期
time_dk = time_dk.sort_index()
#根据日期截取想要的数据作为一个新df
week_dk = time_dk[lastW:thisW] #本周
month_dk = time_dk[thisM:thisW] #本月
#分组统计,相当于Excel的Pivot
leiji_dk = time_dk.groupby(['Key1','Key2','Key3'])['Value'].count().unstack().reset_index()
#数据连接 有点一言难尽
z = shangzhou_fy.join([shangzhou_dk.set_index('员编'),shangzhou_a.set_index('员编'),shangzhou_b.set_index('员编'),
shangzhou_c.set_index('员编'),shangzhou_d.set_index('员编'),
shangzhou_e.set_index('员编'),shangzhou_f.set_index('员编'),
shangzhou_g.set_index('员编')],how = 'outer')
#删除列
z.drop(z.columns[[3,6,9,12,15,18,20,23]], axis=1, inplace=True)
#数据再连接
result = pd.merge(z.reset_index(),df_hmc.loc[:,['员工 ID','姓名','部门描述']],how='left',left_on = '员编', right_on = '员工 ID')
#结果导出
result.to_excel('D:/周累计' + EndT + '.xlsx')
额…怎么硕呢…当时想把10个表的数据根据业务员id汇总(类似Excel根据countifs链接10个表),然后相同格式代码我就真复制粘贴写了10段…总之能用,但是屎山(第一要义:能跑就行)
2.2 表格合并
这个是之前导表只能一个月一导,合并数据量又太大,好卡,就用这个合并
import numpy as np
import pandas as pd
#import matplotlib.pyplot as plt
#%matplotlib inline
#import seaborn as sns
import time
import os
#文件夹路径,合并此路径下所有文件
path = "C:\\Users\\Administrator\\Downloads\\DataA"
files = os.listdir(path)
df = pd.DataFrame([],)
for filename in files:
print('正在读取:'+filename)
filename = 'C:\\Users\\Administrator\\Downloads\\Data\\'+filename
df1 = pd.read_excel(filename)
df = pd.concat([df,df1])
print('就这就这就这?(๑•́ ∀ •̀๑) ')
now_time = time.strftime("%Y-%m-%d.%H-%M-%S", time.localtime())
print(now_time,'执行保存中...')
df.to_excel('房源列表'+str(now_time)+'.xlsx',index = False)
print('保存好啦ヽ(•̀ω•́ )ゝ')
不要问我seaborn和plt是干嘛用的,只能说当初有做BI的幻想
3 操控飞书bot
可能是受到“高效团队用飞书”+给了利益的原因,公司抛弃了钉钉用上了飞书
飞书群内可以添加bot,个人也可以创建应用程序来控制bot,不过基本上所有权限都需要管理员审批,如果公司规模大分布于全国,并且不是总部,再加上自身不是专业技术人员,那基本很难获取到什么权限,所以我只拿它往群里定时发发消息
具体飞书开发人员帮助文档其实写的很详细,我不会做网页和小程序,能看懂的很有限
#群bot接口,可以在群内看到
boturl = 'https://open.feishu.cn/open-apis/bot/v2/hook/***'
import datetime
import requests
import urllib.request
import time
today = datetime.date.today()
yesterday = today - oneday
chinese_time = yesterday.__format__('%Y年%m月%d日')
#获取token,官方也有给方法
def gettoken():
url='https://open.feishu.cn/open-apis/auth/v3/***'
res = requests.get(url=boturl)
print(res)
token=res.json()
token_text=token['tenant_access_token']
return token_text
#上传图片获取image_key,这里首先你要有一个应用程序,才能获取到headers的信息,其实这里也是官方给的方法
def upload(path, token):
url = 'https://open.feishu.cn/open-apis/im/v1/images'
headers = {'Authorization': 'Bearer {}'.format(token)}
with open(path, 'rb')as f:
image = f.read()
files = {
"image": image
}
data = {
"image_type": "message"
}
resp = requests.post(url, headers=headers, files=files, data=data)
print(resp.text)
img_key = resp.json()['data']['image_key']
return img_key
#主程序提交
if __name__ == '__main__':
for num in [['a','pic1'],['b','pic2']]:
path = 'C:\\Users\\Administrator\\Desktop\\{}.jpg'.format(num[1])
token = gettoken()
image_key = upload(path,token)
#富文本消息 post
data = {
"msg_type": "post",
"content": {
"post": {
"zh_cn": {
"title": str(chinese_time) + "【{}】日报".format(num[0]),
"content": [
[
{
"tag": "img",
"image_key": image_key
}
]
]
}
}
}
}
res = requests.post(url=csboturl, json = data) #bbxlurl;csboturl
print(res.text)
time.sleep(10)
print('休息10秒继续')
4 程序打包
最近增加了新的业务,帮同事写了一个很小很小的程序方便她工作,就想着打包成exe再拷过去
搜索了一下大家用的基本都是pyinstaller,怎么安装不太记得了,但使用我熟
参考了两篇很好懂的文章,放俩注释12
4.1 普通打包
打开cmd,cd到想要存放的文件夹,把.py和.ico也扔进去
pyinstaller -F -i name.ico name2.py
符号 | 意义 |
---|---|
-F | 只生成一个exe文件 |
-c | 使用默认配置 |
-w | 不带控制台(windows特供) |
-i | 替换图标 |
似乎我也就用到这几个,个人喜欢带控制台的
但这个打包出来应该至少200M起步,用upx-dir方法能压缩几十M吧,打包完仍然很大
之前谁和我说文件夹形式打包,生成文件会小的,我打包单独exe 370M,文件夹800+M
4.2 虚拟环境打包
其实注释的两篇文章过程写很详细了
安装两个库
pip install virtualenv
pip install virtualenvwrapper-win
我的理解,virtualenv是本体,virtualenvwrapper-win是操纵本体的,后面这个不装也行,但装了简单
创建虚拟环境
mkvirtualenv YourName
激活虚拟环境
workon YourName
当cmd显示为(YourName)F:…的时候就说明是处于虚拟环境中了
然后pip你用到的库,用什么pip什么,别忘了pip install pyinstaller
如果这里报错no matching distribution found for xxx
先想下这个库是不是python自带的,自带的不用另外安装
如果不是,可以去这里3查查原因
然后继续pyinstaller -F -i name.ico name2.py就行了,应该会很明显的发现,打包速度upup
之前打包完370M的exe变成了20M,效果显著,舒服了
附常用命令
退出当前虚拟环境:deactivate
删除某个虚拟环境:rmvirtualenv 虚拟环境名称
列出所有虚拟环境:lsvirtualenv
5 下步计划
- 程序打包exe
- 减小打包体积
- 程序可视化,用Tkinker做一个小程序出来
两点感慨
第一次在写博客,CSDN都把模板做这么详细了,真是方便又好用
可视化,人类进步的阶梯!