工作过程中,经常会用python 执行一些自动化,脚本操作。非Python专业大头兵,最近汇总的一些常用操作。
1. 如何在list中查找
for x in []:
if x meet condition:
#do sone action
2. 字符串转换成数字
s=”99”
int(s)
3. python 生产随机数
import random
random.randint(1, 50) #1~50之间的随机数
4. 创建文件夹
os.mkdir()
创建子目录
os.makedirs()
os.makedirs('temp/1/1/')
5. 检查文件夹是否存在
os.path.exists
6. 检查文件夹是否存在
枚举目录
os.walk(dir)
def enumDirs(dir):
abs_files=[]
for root, dirs, files in os.walk(dir):
for file in files:
s=os.path.join(root, file)
print(f'abs file={s}')
abs_files.append(s)
pass
或者
os.listdir(dir) #只能获取档次dir的所有文件,文件夹
7. list获取文件绝对路径
listdir(dir)
for item in dir:
absPath=os.path.join(dir, item)
#absPath 可以用
8. 删除子目录,还有子文件
os.removedirs(dir) #依赖没有子文件
shutil.rmtree(dir) #直接全部干掉
9. 检查是否是一个文件
os.path.isfile(filename)
10. 生产一个随机数
import random
random.randint(0, 9) #生成0,9之间的随机数
11. 读写txt文件
按行读取文件
with open(filename, ‘r’, encoding=’utf-8’) as file_to_read:
while True:
lines=file_to_read.readline()
if not lines:
break;
process_line(lines)
写文件
with open(filename, ‘w’) as file_to_write:
file_to_write.write(‘this is a line’)
12. python unitest 传递参数
可以通过命令行传递参数,也可以使用环境变量来传递参数
windows
SET HOST=localhost
from os import environ
print(envirom[‘HOST’])
13. list拼接字符串
str=‘’
list=[‘123’,’2222’]
str.join(list)
#output 1232222
14. 日期字符串转date
def str2date(s):
#2021-11-05 06:35:18.370
try:
return datetime.datetime.strptime(s,'%Y-%m-%d %H:%M:%S.%f')
except ValueError:
print('convert str to date failed.%s' %(s))
print(s)
sys.exit(-1)
return ''
15. timer
import threading
def func():
print(“timer cb”)
timer=threading.Timer(5, func)
timer的基本用法
传递参数
def func(*argc **kvgc):
print()
timer=threading.Timer(5, func, (), {“param1”:1})
16. 执行windows cmd命令
import subprocess
return subprocess.Popen(cmd, shell=True, stdout=None)
os.system(cmd)
执行并且返回output内容
def exec(cmd):
output=subprocess.getoutput(cmd)
return output
17. python 获取html表单
import pandas as pd
simpsons=pd.read_html(‘xxxxx.html’)
只能获取html里面有table的内容,不是div哦
18. 命令行参数click
经常写脚本处理相关任务的时候,比如会用到命令行参数,可以用getopt库,这里使用click库,click使用起来非常方便,功能超级强大
@click.group()
def helper():
pass
@click.command(‘—type’)
def work():
pass
helper.add(work)
if __name__==“__main__”:
helper()
官方网址
https://click.palletsprojects.com/en/8.1.x/
19. 定义一个属性
class ebook(Base):
__tablename__='book'
@property
def helper():title(self):
pass
#二进制方式读取
With open(“filename.zip”, mode=”rb”) as zip_file:
context=zip_file.read()
21. 获取文件大小
Import os
Statinfo=os.state(filename)
os.st_size
22. 获取类名和方法名称
logger.info("Enter %s:%s"%(self.__class__.__name__,sys._getframe().f_back.f_code.co_name))
logger.info("Leave %s:%s"%(self.__class__.__name__,sys._getframe().f_back.f_code.co_name))
23. 去掉字符串的前后空格换行
str.strip()
24. 查找整个单词
def findWholeWord(w):
return re.compile(r'\b({0})\b'.format(w), flags=re.IGNORECASE).search
a=findWholeWord(‘aaaa’)(str)
if a :
find it
else
No find
25. 字符串startswith
判断字符串是否xxx开始
27. python logger的使用
import logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
logger=logging.getLogger(__name__)
不写什么大型的代码,直接贴代码,打log
28. 好用的f
打印log,或者debug 的时候,很多中方法f用起来非常方便
s=‘helloworld’
print(f’string={s}’) # string=helloworl
29. 好用的pytest
如果写的代码多了,一般写一些算法函数的时候,要么单独搞个test来测试,或者简单点,搞个单元测试。在工作目录里面创建一个test_xxx.py文件,然后倒入你要测试的函数,类,直接写测试方法。写完之后在目录执行pytest -s 就可以自动执行
备注:-s 会把print的语句输出出来
近在处理一些和有关电影的工作,需要用到一些北美电影票房数据,而这部分数据最权威的网站当属Box Office Mojo(以下简称BOM),于是就上去查看了一下。估计经常关注这个网站的盆友们都知道,这个网站最近进行了改版,网页排版全面更新,还专门针对移动设备进行了优化(以前的网站页面只有电脑版的),页面虽然好看了不少,但却少了很多数据,之前的网站几乎所有数据都能查到,而现在则只能查到部分数据,有些数据则要到BOM Pro版才能查到,而这个服务是收费的。为了更好地使用数据,还想不花钱,那就只有自己动手丰衣足食,所以笔者就自己写了个Python爬虫,爬取了过去多年的票房数据。以下就以"北美电影票房每日票房数据"为例,介绍一下如何爬取,其他票房数据类似,只需修改少数代码即可。
图1. 要抓取的部分网页的截图
这个爬虫程序完全采用Python语言完成,使用软件为Anaconda 2019.10版(这个目前是最新版的,理论上其包含的各种Python库也是最新的或接近最新的,所以下面的爬虫程序在部分老版软件上可能会出问题,如有问题请及时更新)。爬虫程序主要包括两部分:爬取并存储数据,以及根据数据简单绘制图片。下面就一一讲解一下。
一、爬取和存储数据
# 首先把需要的包都导入进来。
import requests
import pandas as pd
import time
import matplotlib.pyplot as plt
import matplotlib.dates as mdate
import pylab as mpl # 导入中文字体,避免显示乱码
# 这个是我们要用到的每日票房的URL,中间的%s是一会儿要替换的年份
urltemplate=r'https://www.boxofficemojo.com/daily/%s/?view=year'
#这个是数据保存的地方,放在了桌面的一个Excel文档中,因为数据很少,所以根本用不到数据库,Excel足以,当然这里也可以用CSV格式。这里我的路径中包含中文,使用时没有问题,如果大家出现问题,最好使用英文路径。
fileLoc=r'C:\BoxOffice\Box Office Mojo票房爬虫\Daily\daily-data.xlsx'
# 这个是爬虫头部,防止网站的反爬机制。
headers={'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36'}
下面是爬虫主体部分,这里有三点要说明,一是mode='a'这里,这个是0.25.1版pandas以后才有的功能,之前的老版本没有这个功能;二是,不知道是不是我的网络有问题,在爬取过程中有掉线的现象出现,所以在这里用了requests.ConnectionError来处理掉线问题;三是,用了一个小窍门,如果直接用pd.read_html(url)也可以读取网页中的数据,但这里先用requests读取网页,再把requests读取的网页代码放入pd.read_html中,这样既可避免网站的反爬虫机制,也可以加快读取速度,因为pd.read_html直接读取网页实在太慢了。
def scraper(file, headers, urltemp, year_start, year_end):
writer=pd.ExcelWriter(file, engine='openpyxl', mode='a')
for i in range(year_start, year_end+1):
url=urltemp % i
try:
r=requests.get(url, headers=headers)
if r.status_code==200:
source_code=r.text
df=pd.read_html(source_code)
df=df[0]
df.to_excel(writer, sheet_name=str(i), index=False)
time.sleep(2)
except requests.ConnectionError:
print('Can not get access to the %s year daily data now' % i)
return
writer.save()
writer.close()
scraper(fileLoc, headers, urltemplate, 1977, 2019)
因为网站只提供到最早1977年的数据,所以就把1977年到2019年数据都给抓下来。
图2. 抓取的部分数据的截图
二、根据数据简单绘图
# 下面这个str_to_datetime函数,是除掉数据Date列中一些不必要的文字,比如有些数据带有“New Year’s Eve”字样,要把这些东西去掉
def str_to_datetime(x):
if len(x) > 14:
temp=x.split('2019')
x=temp[0]+'2019'
return x
# 这个str_to_num函数是把“Top 10 Gross”列的数据都转换成数值,因为这些数据从Excel读取到pandas后,都是string格式的数据,要转换成数值格式
def str_to_num(x):
x=x.replace('$', '')
x=x.replace(',', '')
x=int(x)
return x
table=pd.read_excel(fileLoc, sheet_name='2019')
data=table[['Date', 'Top 10 Gross']]
data['Date']=data['Date'].apply(str_to_datetime)
data['Top 10 Gross']=data['Top 10 Gross'].apply(str_to_num)
# 设置x轴和y轴的数据,x轴是时间数据,y轴是票房数据,其值太大,所以改小点,方便作图
x=pd.to_datetime(data['Date'])
y=data['Top 10 Gross']/1000000
# 找出票房数据中最大的那个值和其在序列y中的位置,然后找出对应x序列的位置,也就是对应的哪一天
max_loc=y.idxmax()
max_y=y.max()
max_date=x.loc[max_loc]
# 设置相关参数
mpl.rcParams['font.sans-serif']=['SimHei'] # 设置为黑体字
fig=plt.figure(figsize=(16, 6.5))
# 生成axis对象
ax=fig.add_subplot(111) # 本例的figure中只包含一个图表
ax.set_ylim([0, 200])
plt.tick_params(labelsize=13)
# 设置x轴为时间格式,这个要注意,否则x轴显示的将是类似于‘796366’这样的转码后的数字格式
ax.xaxis.set_major_formatter(mdate.DateFormatter('%Y-%m-%d'))
plt.xticks(pd.date_range(x[len(x)-1], x[0], freq='M'), rotation=90)
text=r'票房最高的一天是%s,其票房为%.2f亿' % (max_date.date(), max_y/100)
plt.annotate(text, xy=(max_date, max_y), fontsize=14, \
xytext=(max_date+pd.Timedelta(days=10), max_y+10), \
arrowprops=dict(arrowstyle="->", connectionstyle="arc3"), \
xycoords='data')
plt.ylabel('票房/百万美元', fontdict={'size':14})
plt.plot(x, y)
完成后这个图片效果如下
图3. 2019年北美票房每日数据图
三、结语
上面这个爬虫程序比较简单,并没有用到数据库、多线程等复杂技术,我们更多地应该从所得到的数据中来挖掘更多的价值,笔者接下来会从这些数据中来分析一下好莱坞电影行业过去一年的发展,届时会分享给大家,敬请期待。
在这,我们接续昨天的 Python 数据处理(二),将以 R 语言的形式,重新实现一遍同样的数据提取操作
为什么我要这么做呢,其实我是这么想的:
下面进入正题
在 Python 爬虫项目中,最常用的是 requests 模块。
而在 R 中,我们使用 rvest 模块,进行网页解析以及获取网页内容。
# install "rvest" package
install.packages("rvest")
# library
library(rvest)
我们还是以昨天的链接为例
首先用 read_html 读取网页链接
然后用 html_text 读取整个网页内容,返回的是一个字符串
# 网页链接
URL <- "http://rest.kegg.jp/get/cpd:C01290"
# 获取 URL 网页
res <- read_html(URL)
# 读取网页文本
text <- html_text(res)
# 将文本按行分割
# strsplit 返回的是长度为 1 的 list,因此,可以用 unlist 转换为 character
line_list <- unlist(strsplit(text, split = '\n'))
# 新建空 list,用于存储我们的数据
data <- list()
for (i in 1:length(line_list)) {
line <- line_list[i]
# 提取前 12 个字符,substr(x, start, stop)
# 提取 start,stop 指定的 x 中字符的起始和结束位置
prefix <- substr(line, 1, 12)
# 判断是否包含字母数字
if (grepl("\\w+", prefix)) {
# 去除多余的空白字符
key <- sub(pattern = "\\s+", replacement = "", x = prefix)
}
# 获取 line 中位置 13 到末尾的字符,nchar(x) 计算字符串 x 的长度
value <- substr(line, 13, nchar(line))
if (key == "ENTRY") {
# 在这,使用 perl 形式的正则 perl = TRUE,以多个空白字符分隔字符串
data$entry <- unlist(strsplit(value, split = "\\s+", perl = TRUE))[1]
} else if (key == "NAME") {
v <- substr(value, 1, nchar(value)-1)
data$name <- c(data$name, v)
} else if (key == "ENZYME") {
v <- unlist(strsplit(value, split = "\\s+", perl = TRUE))
data$enzyme <- c(data$enzyme, v)
} else if (key == "DBLINKS") {
v = unlist(strsplit(value, ": "))
data$dblinks[v[1]] <- v[2]
}
}
输出提取的信息
> data
$entry
[1] "C01290"
$name
[1] "Lactosylceramide"
[2] "beta-D-Galactosyl-(1->4)-beta-D-glucosyl-(11)-ceramide"
[3] "beta-D-Galactosyl-1,4-beta-D-glucosylceramide"
[4] "Gal-beta1->4Glc-beta1->1'Cer"
[5] "LacCer"
[6] "Lactosyl-N-acylsphingosine"
[7] "D-Galactosyl-1,4-beta-D-glucosylceramid"
$enzyme
[1] "2.4.1.92" "2.4.1.206" "2.4.1.228" "2.4.1.274" "2.4.99.1" "2.4.99.9" "3.2.1.18" "3.2.1.22"
[9] "3.2.1.23" "3.2.1.47" "3.2.1.52"
$dblinks
PubChem ChEBI LIPIDMAPS LipidBank
"4509" "17950" "LMSP0501AB00" "GSG1147"
仔细看看代码逻辑,和 Python 是很像的。
其中一些函数可以映射到 Python 中的函数,虽然他们之间用法、参数、返回值会有点差别,但是作用是类似的。
上面代码中我们都是用 R 自带的字符串操作,用起来比较麻烦,不是很得心应手。
后面,我会给大家讲讲 R 的字符串操作模块 stringr,能极大提升我们开发效率。
*请认真填写需求信息,我们会在24小时内与您取得联系。