python:基础知识详解

2019-04-25  本文已影响0人  JackHCC

$课程笔记

image

python相关函数查询

官方API文档

菜鸟教程python

w3school教程python

一.基本元素

变量
a="hello world"
变量类型
b=int(a)
c=flaot(a)
d=str(a)

• 字符串的拼接和整数乘法

a="hello"+"world"
b="hello"*2
语句
if 条件:
elif 条件:
else:
s = 0
for i in range(10): # 0,1,...9
    s += i
print(s)
s = 0
i = 0
while s<10:
    s += i
    i += 1
print(s)
from math import *
# use pi, cos, sin, ...
from math import cos, sin
# only use cos, sin
import math
# use math.cos, math.sin, ...
def double(x):
    return x * 2
turtle库详解

python:turtle库详解

python类型

类型

• 标量类型
—— 逻辑类型(bool)
—— 整数(int)、浮点数(float)、复数(complex)
—— 空 类型 型(None)
• 集合类型
—— 字符串(str)
—— 列表(list)
—— 字典(dict)
—— 元组(tuple)
—— 集合(set)
• 自定义类型
—— 类 class

数值类型

• 除法有两种:/, // 后者是整除
—— 7/3 = 2.3333333333333335
—— 7//3 = 2
—— 7.0 // 3.0 = 2.0
• 幂运算允许实数
—— 7 ** 2 = 49
—— 7 ** 0.5 = 2.6457513110645907
• 不同类型的数值运算就高不就低
—— int —— float —— complex

三元操作符

• 表达式

 x if c else y 

相当于

 c? x : y
字符串

• 字符串的进阶操作

'p' in s 

• 下标以0为开始

 s[0] # index: offset 0
 s[2:6] # slice: part of string
 s[:6] 
 s[6:]

• 逆序的下标

 s[-1]
 s[-3:-1]
 s[1:-1]
 s[-3:]

• 步长:begin:end:step

 s[::2]
 s[1::3]
 s[5:1::-1]
 "live"[::-1]
不可修改类型 Immutable

• 数值类型、字符串类型是不可修改类型
—— 后续讲解的元组(tuple)类型也是不可修改类型
• 它们的值是常数,不可以修改
—— 我们并不能把“1”修改为“2”,把“abc”改为“def”;
—— 作为值,它的含义是确定的、不变的。
• 赋值语句(Assignment)是给这些常数的值赋予不同的名称

字符串方法
 s = 'I love Python'
 s.count('on') # 查找子串出现次数
 s.find('ove') # 查找子串首见位置
 s.replace('Python', 'C++') # 替换

 three = '3'
 three.isdigit() # 是否为数字字符?
列表
 r = [1, 2.0, 3, 5] # list的字面构造
 r[1] # 正数下标自首部计数,首部为0
 r[-1] # 负数下标自尾部计数,尾部为-1
 r[1:3] # 前闭后开区间
 w = r + [10, 19] # 连接
 t = [0.0] * 10 # 重复
 len(r)
 r = [[9, 8], 2.0, 3, 'word']
 r[0:3] = [1, 2, 5, 6] # 修改片段

 r[1:3] = [] # 删除元素

 r[1:1] = [ 'new' ] # 赋值语句左右侧都是片段;等价于插入[1, 'new', 6, 'word']
 r[len(r):] = [ 'last' ] # 在尾部插入[1, 'new', 6, 'word', 'last']
 r.insert(0, 'f') # 在0位置增加新元素'f'
 del r[0]
 r.append(9) # 尾部增加元素
 r.sort() # in-place 排序
 r.reverse() # 逆序
[i for i in range(9)]
[i*2 for i in range(9)]
[i for i in range(100) if '4' not in str(i)]

• 补充
—— Python 一行语句过长,可以用 \ 续行
—— 若在括号(花方圆均可)内可以自由换行

字典
 g = {'Tom': 'boy', 'Mary': 'girl'}
 g['Tom'] # 以key为索引
 g.has_key('Mary')
 g['Jack'] = 'boy' # 增加键值对
 del g['Tom'] # 删除键,删除键到值的绑定

 h = {'Tom': 12, 'Mary': 'good'}
 'Per' in h # 在键的集合中检测
 h.get('Per', 'unknown') # 如果查找失败则返回缺省值
 h.keys() # 由键组成的列表,顺序不确定
 h.values() # 由值组成的列表,顺序不确定
 h.items() # 顺序同上
 len(h) # 键的数量
元组
 t = (1, 3, 2)
 t[1] # 3
 (a, b, c) = t # 元组赋值
 a, b, c # (1, 3, 2)
集合
s = set()
s = {1, 2, 3}
s.add(4) # {1,2,3,4}
s.add(1) # {1,2,3,4}
t = {1,2}
# &交集,|并集 - 差集
s - t # {3,4}
容器间转换

• list, set, dict 作为类型名可以实现转换
—— list("abc") = ["a", "b", "c"]
—— set([1,2,2]) = {1,2}

Python语句

pass语句

• pass是一个(占位)空语句,不做任何事情
• 动因
—— python利用缩进表达语句块,如果语句块是空的,不写会有错;
—— 这种情况下,可以写上pass

for循环语句

• for可以遍历任意的容器
—— 对词典遍历的是keys()
• range(n)是一个内置函数,返回0~n-1的列表
• range(start, stop, step)

break语句

• 跳出最内层的循环
• python没有直接跳出外层循环的语法手段
—— 通常会借助额外的flag变量
—— 异常处理

continue语句

• 它结束当前迭代,并跳到下一次迭代开头。即跳过循环体中余下的语句,但不结束循环。
• 可以用等价的if语句描述

for/while-else语句

• 只要不是break跳出循环,就执行else语句
• 相比C语言减少一个flag变量

r = [1, 3, 10, 98, -2, 48]
for i in r:
    if i < 0:
        print('input contains negative value!')
        break
else:
    print('input is OK')
exec和eval

• 动态地编写Python代码,并将其作为语句进
行执行或作为表达式进行计算
• 函数exec将字符串作为代码执行
• eval计算用字符串表示的Python表达式的值,
并返回结果。
• 如下代码来创建一个Python计算器

assert断言语句

• 要求某些条件得到满足,否则将引发异常
• 确保程序的参数合理
• 对于不合理的情况,明确引发异常

异常处理
try:
    1 / 0
except NameError:
    print("Unknown variable")         出现异常时执行。。。
else:
    print("That went well!")             没有出现异常时执行
finally:
    print("Cleaning up.")             任何情况下都会执行
函数

• 函数名:规则与变量名相同
• 参数列表:调用函数时传递给它的值
—— 可以由零个,一个或者多个参数组成
—— 当有多个参数时,各个参数用逗号分隔
• 函数体:函数被调用时执行的代码
—— 由一个或多个语句组成
—— 在执行到末尾或return语句时退出函数
—— 返回结果
• 函数调用的形式
—— 函数名( 参数列表 )
• 形式参数(名):定义函数时,函数名后面圆括号中的变量。形参只在函数内部有效。
• 实际参数(值):调用函数时,函数名后面圆括号中的变量。

参数能否修改:总结

• 凡是Immutable类型的参数,传入的对象值不可能修改
• 对于Mutable类型的参数:
—— 若对形参进行赋值,并不能改变传入对象的值
—— 若对形参进行in-place的修改,则该修改也反应在传入的对象上

关键字参数的缺省值

• 可以设定一些参数的缺省值(默认值)
• 如果调用者没有提供,则使用缺失值

def hello(name, greeting="Hello"):

• 允许用户提供任意数量的参数

def sum_of_all(*values):
作用域
匿名函数

• lambda可以用来定义函数

pow2_a = lambda x: x*x

def pow2_b(x):
      return x*x

两者功能相同

模块

• 对于稍微大型的程序,代码量较大,不宜
放在一个文件中
• 模块可以将代码分散在不同的文件

主模块
if __name__ == "__main__":
      do_something()

文本处理

字符的分类

• 数字 digits 01234567890
• 字母 letter
大写ABCDEFGHIJKLMNOPQRSTUVWXYZ
小写 abcdefghijklmnopqrstuvwxyz
• 空白字符:空格,\t\n\r\v
• 对应Unicode,上述概念有一定拓展。

字符串对象方法
格式化

• 字符串的格式化有三种方法
• %, format, f-string

"the number is %d" % 30
name = "John"
age = 23
print("%s is %d years old." % (name, age))
"{0} {1}, you may have won ${2}" .format("Mr.", "Smith",10000)
 'int, {0:5}, in a field of width 5'.format(7)
 ' {0:10.5f}, fixed at 5 decimal places.'.format(3.1415926)
 name = "Eric"
 age = 24
 f"Hello, {name}. You are {age}."

f-string是python3版本的新语法,是一种表达式。

 "www.ustb.edu.cn".split(".")
 [ int(i) for i in "166.111.4.80".split(".") ]
 ".".join([ f"{i}" for i in [166, 111, 4, 80] ])
正则表达式

• 匹配国内电话号码:\d{3}‐\d{8}|\d{4}‐\d{7}
—— 如 0511-4405222 或 021-87888822
• 腾讯QQ号:[1‐9][0‐9]{4,}
—— 腾讯QQ号从10000开始
• 中国邮政编码:[1‐9]\d{5}(?!\d)
—— 中国邮政编码为6位数字
• 匹配身份证:\d{15}|\d{18}
—— 中国的身份证为15位或18位
• 匹配ip地址:\d+.\d+.\d+.\d+
—— 提取ip地址时有用

Python的正则表达式模块

• 模块导入 import re
• 匹配:re.match() 查找字符串的开始部分是否匹配,不向后查找(类似字符串startswith)
• 查找:re.search() 查找是否存在匹配(类似字符串find)
• 替换:re.sub() 替换正则表达式(类似字符串replace)

 s = "2019‐03‐20 is a rainy day"
 pat = "\\d‐\\d‐\\d"
 m = re.match(pat, s)

 m.start()
 m.end()
 m.group()  #返回匹配对象(Match),有start, end, group方法
s = "It is reported that 2019‐03‐20 is a rainyday."
pat = "\\d‐\\d‐\\d"
m = re.search(pat, s)
m.start()
m.end()
m.group() 
s = """You smiled and talked to me of nothing and I felt that for this I had been waiting long."
re.findall("\\b(\\w+ed)\\b", s)
re.finditer(...) # 类似,但返回一个个Match对象
import re
print re.sub("([0‐9]{2})/([0‐9]{2})/([0‐9]{4})",
"\\3‐\\1‐\\2",
"This is a test 01/30/2019.")
文件
<变量名>=open(file, mode = 'r')

—— open函数有两个参数:文件名和打开模式。文件名可以是包含完整路径的名字,或当前路径下的文件名。
—— 第二个参数制定文件打开模式。
• open()函数提供7种基本的打开模式
'r' 以只读方式打开文件(默认)如果文件不存在,返回异常FileNotFoundError。
'w' 以写入的方式打开文件,文件不存在则创建,会覆盖已
存在的文件。
'x' 打开一个新文件来写数据。文件不存在则创建,如果数
据已经存在则返回异常FileExistsError。
'a' 以写入模式打开,文件不存在则创建,如果文件存在,
则在末尾追加写入。
'b' 以 二进制模式打开文件。
't' 以 文本模式打开 (默认)。
'+' 可读写模式(可添加到其它模式中使用)。
• 模式的组合使用
—— 'r','w','x','a'可以和'b','t','+'组合使用,形成既表达读写又表达文件模式的方式。
例如:
——'wb'表示“写二进制数据”
——'x+b'表示读写一个新的二进制文件

fo = open(fname ,"rt")
for line in fo.readlines():
    print(line)
fo.close()
f1 = open(f1name, "rt")
f2 = open(f1name, "wt")
f2.write(f1.read().upper())
f1.close()
f2.close()
f = open('todos.txt')
for chore in f
    print(chore, end='')
tasks.close()
#使用with语句重写这个代码
with open('todos.txt') as f:
for chore in f:
    print(chore, end='')

• with确保即使发生异常,也可以正确的关闭文件

f1 = codecs.open(fname, "r", "utf‐8")
f2 = codecs.open(fname, "w", "gb2312")
f = open("alice.txt", "rt")
all = f.read()
f.close()
count_word = {}
for w in all.split():
    w_lowercase = w.lower()
    count_word[w_lowercase] = \
                                        count_word.get(w_lowercase, 0) + 1
result = [(v, k) for k, v in count_word.items()]
result.sort()

top10 = result[‐10:]
for v,k in top10[::‐1]:
    print(f"Word {k}, occurs {v} times")
汉字的处理

OOP编程

• 类是类型概念的发展。
—— 对象是广义的“数据值”。
—— 对象所属的数据类型就是“类”。
—— 用于描述复杂数据的静态和动态行为。
• 类(class):描述相似对象的共性。包括
—— 数据
—— 操作:方法(method)
• 对象是类的实例(instance)
—— 创建对象
• 类的封装:数据和操作结合成一个程序单元,对外部隐藏内部实现细节。
—— 不允许用户直接操作类中被隐藏的信息。
—— 用户也无需了解隐藏的信息就能使用该类。
• 类对外公开方法名称和调用格式,即界面。
—— 外界向对象发消息。(方法名及参数)
—— 对象响应消息,执行相应方法。
—— 外界只能按对象允许的方式来处理对象数据。
• 封装的好处
—— 安全:对象自己的方法处理自己的数据
—— 易用:使用者无需了解内部实现细节
—— 易维护:实现者修改内部实现不会影响使用者
—— 标准化:同类甚至不同类的对象对使用者都呈现同样的操作界面
• 方法定义同函数定义

def <methodname>(self, other params):

—— 方法是依附于类的函数,普通函数则是独立的。
—— 方法的第一个参数是专用的,习惯用名字self。
—— 大体上等价于C++的this
—— 只能通过向对象发消息来调用方法。
• 对象是数据和操作的结合。
—— 方法对应于操作
—— 对象的数据以实例变量形式定义。
—— 实例变量:self.varname
—— 对象变量和所指向的数据本质上是一个词典
—— self.varname 即 self["varname"]
—— 实例变量的赋值主要出现在init()方法中。

class Circle:
""" Class definition for a circle """
def __init__(self, radius):
    self.radius = radius
def getRadius(self):
    return self.radius
def getArea(self):
" Obtain the area of a circle"
    return math.pi*self.radius**2
继承

• 在OOP程序设计中,当我们定义一个class的时候,可以从某个现有的class继承,新的class称为子类(Subclass),而被继承的class称为基类、父类或超类(Base class、Super class) 。
• 继承是面向对象的重要特征之一,继承是两个类或者多个类之间的父子关系,子类继承了父类的所有实例变量和方法。
• 继承实现了代码的重用。重用已经存在的数据和行为,减少代码的重新编写。
• Python在类名后用一对圆括号表示继承关系,括号中的类表示父类。

class 类名(被继承的类):
多态

• 当对一个对象调用draw()函数时,它会根据自己的对象类型执行不同的draw方法
—— FilledDrawableCircle.draw()
—— DrawableCircle.draw()
• 对于相同的方法,会有不同的实现版本,这就是多态(Polymorphism)

科学计算与可视化

Numpy

• NumPy(Numeric Python)是Python语言的一个扩展包。
• 由多维数组对象和数组计算函数共同组成的库,支持多维数组、矩阵运算以及大量数值计算功能。

• 安装:pip install numpy
• 导入:import numpy as np
import numpy as np
x = np.array([1, 2, 3])
y = np.array([4.0, 5, 6])
print(x.dtype, x.shape, x.ndim)
print(y.dtype, y.shape, y.ndim)
z = x + y
print(z)
array = np.array([[0,1,2],[2,3,4]])
# [[0 1 2]
#  [2 3 4]]
array = np.zeros((2,3))
# [[0. 0. 0.]
# [0. 0. 0.]]
array = np.ones((2,3))
# [[1. 1. 1.]
# [1. 1. 1.]]

• eye 单位矩阵
• 浮点数优先用linspace,避免累计误差
• np.random 类似于random

array = np.eye(3)
# [[1. 0. 0.]
# [0. 1. 0.]
# [0. 0. 1.]]
array = np.arange(0, 10, 2)
# [0, 2, 4, 6, 8]
array = np.linspace(0, 1, 11)
# [0. , 0.1, 0.2, 0.3,…, 0.7, 0.8, 0.9, 1. ]
array = np.random.randint(0, 10, (3,3))
# [[6 4 3]
# [1 5 6]
# [9 8 5]])
a = np.arange(9)
a[0]
# 0
a[3:7]
# array([3, 4, 5, 6])
a[:7:2]
# array([0, 2, 4, 6])
a[::‐1]
#array([8, 7, 6, 5, 4, 3, 2, 1, 0])

• 多维数组:每一个维度都可以进行索引或切片,
返回一个标量或多维的子数组(view)。
• 对此子数组的修改可能会反应在原数据上!

b = np.array([[0,1,2],[3,4,5]])
#[[0 1 2]
#  [2 3 4]]
b[0,1]
# 1
b[1,:]
#[3,4,5]
b[:,2]
#[2,5]
arr = np.array([[1., 2., 3.], [4., 5., 6.]])
print(arr)
[[1. 2. 3.]
[4. 5. 6.]]
print(arr * arr)
[[ 1. 4. 9.]
[16. 25. 36.]]
print(arr ‐ arr)
[[0. 0. 0.]
[0. 0. 0.]]
x = np.arange(10)
mod5 = x % 1 == 1
x [ mod5 ] # [1, 6]
x [ x > 5 ] ?

• 整数型数组(或list)可以作为索引
• 逐个取出每个整数对应下标的元素,得到ndarray数组的子集

x = np.arange(10)*10
# array([ 0, 10, 20, 30, 40,
50, 60, 70, 80, 90])
x[[1,3]]
# array([ 10, 30])
x[[5,3,7]]
# array([ 50, 30, 70])
A = np.ones((4,1))
array([[1.],
[1.],
[1.],
[1.]]
B = np.zeros((4,2))
array([[0., 0.],
[0., 0.],
[0., 0.],
[0., 0.]])
C = np.concatenate([A, B], axis=1)
array([[1., 0., 0.],
[1., 0., 0.],
[1., 0., 0.],
[1., 0., 0.]])
a = np.array([1,2,3,4,5,6])
a = a.reshape(3,2)
"""array([[1, 2],
[3, 4],
[5, 6]])"""
a = a.reshape(2,‐1)
x = np.array([[1, 2, 3], [4, 5, 6]])
print(np.ravel(x))
[1 2 3 4 5 6]
for i in x.flat: #属性,不需要加(),返回iterator
    print(i)
x = np.arange(4).reshape((2,2))
"""array([[0, 1],
[2, 3]])"""
np.transpose(x) # x.transpose((1,0)), or x.T
"""array([[0, 2],
[1, 3]])"""
np.savez('data.npz', a=a)
data = np.load('data.npz')
a = data['a'] # data是一个词典

• 读入文本文件
• 可以指定注释、分隔符、编码等

from io import StringIO
# 用字符串模拟一个file对象
c = StringIO("0 1\n2 3")
np.loadtxt(c)
array([[ 0., 1.],
[ 2., 3.]])

• 读入图像文件

from scipy.misc import imread
im = imread("lenna.png")
print(im.shape, im.dtype)
# (330, 330, 3) uint8
im_grey = im[:,:,0]*0.299 + im[:,:,1]*0.587 + im[:,:,2]*0.114
import matplotlib.pyplot as plt
plt.imshow(im_grey, cmap='gray')
plt.show()
 np.sum([[0, 1], [0, 5]])
#6
 np.sum([[0, 1], [0, 5]], axis=0)
#array([0, 6])
 np.sum([[0, 1], [0, 5]], axis=1)
#array([1, 5])
 np.sum([])
#0.0
x = array([[0, 1],
[2, 3]])
x.astype(np.float32)
"""
array([[0., 1.],
[2., 3.]], dtype=float32)
"""
a = np.array([[2, 0], [0, 1]])
b = np.array([[4, 1], [2, 2]])
c = np.dot(a, b)  
"""
array([[8, 2],
[2, 2]])
"""
 a = np.array([5,3,2,4,1])
 a.argsort()
array([4, 2, 1, 3, 0], dtype=int64)
 a = np.array([[3,1], [1,2]])
 b = np.array([9,8])
 x = np.linalg.solve(a, b)
 x
array([ 2., 3.])
np.allclose(np.dot(a, x), b)
MATPLOTLIB

• Python绘图库。
• 由 John Hunter (1968-2012) 创建。
• 拥有一套和Matlab几乎相同语法的绘图库。
• 也拥有另一套面向对象的绘图库。
http://matplotlib.org/ 参考 Example 和 Gallery。

import numpy as np
from matplotlib.pyplot import *
#or: from matplotlib.pylab import * 
# pylab = pyplot + numpy
x = np.linspace(0, 5, 10)
y = x ** 2
figure()
plot(x, y, 'r‐o')
xlabel('x')
ylabel('y')
title('title')
show()
import numpy as np
import matplotlib.pyplot as plt
a = b = np.linspace(0, 3, 50)
c = np.exp(a)
d = c[::‐1]
plt.plot(a, c, 'r‐‐', label='Model length')
plt.plot(a, d, 'b:', label='Data length')
plt.plot(a, c+d, 'k', label='Total message length')
legend = plt.legend(loc='upper center', shadow=True)
legend.get_frame().set_facecolor('#00FFCC')
plt.show()
x = np.linspace(0.0, 6.28, 100)
y1 = np.cos(x)
y2 = np.sin(x)
plt.subplot(2, 1, 1)
plt.plot(x, y1, 'yo‐')
plt.grid(True)
plt.subplot(2, 1, 2)
plt.plot(x, y2, 'r.‐')
plt.xlabel('time (s)')
plt.show()
mu, sigma = 100, 15
x = mu + sigma * np.random.randn(10000)
n, bins, patches = plt.hist(x, 50,
normed=1,
facecolor='g',
alpha=0.75)
plt.xlabel('Smarts')
plt.ylabel('Probability')
plt.title('Histogram of IQ')
plt.text(60, .025,
r'$\mu=100,\ \sigma=15$')
plt.axis([40, 160, 0, 0.03])
plt.grid(True)
plt.show()
x = np.random.random(50)
y = np.random.random(50)
c = np.random.random(50)  # color of points
s = 500 * np.random.random(50)  # size of points
fig, ax = plt.subplots()
im = ax.scatter(x, y, c=c, s=s, cmap=plt.cm.jet)
# Add a colorbar
fig.colorbar(im, ax=ax)
# set the color limits
im.set_clim(0.0, 1.0)

网络爬虫

检查网站地图

• Sitemap(网站地图)
• 网站提供的Sitemap文件可以帮助爬虫定位网站所有网页的链接;
• Sitemap文件提供了爬取网站的有效方式,但该文件经常存在缺失、过期或不完整。

检测网站构建技术

• 构建网站的技术类型会对爬取产生影响。
—— 例如网页是动态生成的还是静态页面。
• 安装 builtwith 库,将URL作为参数,该库
返回网站使用的技术特征。
• pip install builtwith

调研网站的所有者

• 根据网站的所有者,判定爬虫的下载速度等;
• 为了找到网站的所有者,可以使用WHOIS协议查询域名的注册者。
• 安装:pip install python-whois

下载单个网页

• python提供了urllib2, requests等库

import requests
url = 'http://www.weather.com.cn/weather/101010100.shtml' # URL地址
header = {
'User‐Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36
(KHTML, like Gecko) Chrome/53.0.2785.104 Safari/537.36
Core/1.53.3226.400 QQBrowser/9.6.11681.400'
}
req = requests.get(url, headers=header, timeout=60)
req.encoding = 'utf‐8' # 设置文本编码
code = req.status_code # 返回状态,200代表OK
print(code)

• 遇到错误怎么办?(code!=200)
• 下载时遇到的错误经常是临时性的:
_ 如服务器过载时返回的503 Service Unavailable错误;
_ 对于此类错误,可以尝试重新下载。
• 非临时性错误
_ 如果服务器返回的是404 Not Found错误,说明该网页目前并不存在,再次尝试同样的请求也通常会再次出错。
• 400+错误发生在客户端,500+错误则发生在服务端。
• 在code为500+时可以重试下载,但通常应该等待一段时间。

分析网页的三类技术

• 正则表达式
_ 无视HTML语言,直接利用正则表达式筛选出所需的部分,包括天气和URL;
• BeatifulSoup
_ 将HTML进行解析,利用树结构进行分析;
• lxml
_ 将HTML进行解析,基于XPATH查询语言进行分析。

from bs4 import BeautifulSoup
html_doc = """<html><head><title>The Dormouse's story</title></head>
<body>
<p class="title"><b>The Dormouse's story</b></p>
<p class="story">Once upon a time there were three little sisters;
and their names were
<a href="http://example.com/elsie" class="sister"
id="link1">Elsie</a>,
<a href="http://example.com/lacie" class="sister"
id="link2">Lacie</a> and
<a href="http://example.com/tillie" class="sister"
id="link3">Tillie</a>;
and they lived at the bottom of a well.</p>
<p class="story">...</p>
"""
soup = BeautifulSoup(html_doc)
print(soup.prettify()) # 排版

soup.title
# <title>The Dormouse's story</title>
soup.title.name
# 'title'
soup.title.string
# 'The Dormouse's story'
soup.title.parent.name
# 'head'
soup.p
# <p class="title"><b>The Dormouse's story</b></p>
soup.p['class']
# 'title'

soup.a
# <a class="sister" href="http://example.com/elsie"
id="link1">Elsie</a>
soup.find_all('a')
# [<a class="sister" href="http://example.com/elsie"
id="link1">Elsie</a>,
#  <a class="sister" href="http://example.com/lacie"
id="link2">Lacie</a>,
#  <a class="sister" href="http://example.com/tillie"
id="link3">Tillie</a>]
soup.find(id="link3")
# <a class="sister" href="http://example.com/tillie"
id="link3">Tillie</a>

• 从文档中找到所有<a>标签的链接

for link in soup.find_all('a'):
      print(link.get('href'))
# http://example.com/elsie
# http://example.com/lacie
# http://example.com/tillie

• 从文档中获取所有文字内容

print(soup.get_text())
# The Dormouse's story
#
# The Dormouse's story
#
# Once upon a time there were three little sisters; and their\names were
# Elsie, Lacie and ...

图形界面开发GUI

python图形化GUI:pyQt5详解
python图形化GUI:pyQt5-tools详解

MVC

• Model(模型)是应用程序中用于处理应用程序数据逻辑的部
分,通常模型对象负责在数据库中存取数据。
• View(视图)是应用程序中处理数据显示的部分。通常视图是依据模型数据创建的。
• Controller(控制器)是应用程序中处理用户交互的部分。通常控制器负责从视图读取数据,控制用户输入,并向模型发送数据。
• MVC 分层有助于管理复杂的应用程序,因为您可以在一个时间内专门关注一个方面。例如,您可以在不依赖业务逻辑的情况下专注于视图设计。同时也让应用程序的测试更加容易。
• MVC 分层同时也简化了分组开发。不同的开发人员可同时开发视图、控制器逻辑和业务逻辑。

python:PIL图像处理

自动化

EXCEL自动化

• Excel 是 Windows 环境下流行的、强大的电子表格应用。
—— 包括LibreOffice Calc,OpenOffice Calc,WPS等软件也可以读写xlsx格式。
• openpyxl 模块让 Python 程序能读取和修改Excel 电子表格文件。最新版本2.6.2。
https://openpyxl.readthedocs.io
• 安装:pip install openpyxl

 import openpyxl
 wb = openpyxl.load_workbook('example.xlsx')
 wb.sheetnames
 sheet = wb['Sheet3']
 sheet.title
 anotherSheet = wb.active
 anotherSheet
 sheet = wb['Sheet1']
 sheet['A1']
 sheet['A1'].value
 c = sheet['B1']
 c.value

for i in range(1, 5):
    print(i, sheet.cell(row=i, column=2).value)
 for rowOfCellObjects in sheet['A1':'C3']:
      for cellObj in rowOfCellObjects:
            print(cellObj.coordinate, cellObj.value)
      print('‐‐‐ END OF ROW ‐‐‐')
for i in sheet.rows:
      print(i)
for i in sheet.columns:
      print(i)
import pprint
resultFile = open('result.py', 'w')
resultFile.write(
'pay_sum = ' + pprint.pformat(pay_sum)
)
resultFile.close()
import openpyxl
wb = openpyxl.Workbook()
print(wb.sheetnames)
sh = wb.active
sh.title = "My Data"
wb.save("mydata.xlsx")
import openpyxl
>>> wb = openpyxl.Workbook()
>>> wb.get_sheet_names()
['Sheet']
>>> sh1 = wb.create_sheet()
<Worksheet "Sheet1">
>>> wb.get_sheet_names()
['Sheet', 'Sheet1']
>>> wb.create_sheet(index=0, title='First Sheet')
<Worksheet "First Sheet">
>>> wb.get_sheet_names()
['First Sheet', 'Sheet', 'Sheet1']
>>> wb.remove_sheet(sh1)   #删除表
>>> wb.get_sheet_names()
['First Sheet', 'Sheet']
import openpyxl
wb = openpyxl.Workbook()
sheet = wb.active
sheet['A1'].value = 'Hello world!'
wb.save("hello.xlsx")
import openpyxl
wb = openpyxl.Workbook()
sheet = wb.active
for i in range(1, 10):
sheet.cell(row=i+1, column=1).value = i
sheet.cell(row=1, column=i+1).value = i
for i in range(1, 10):
for j in range(1, 10):
sheet.cell(row=i+1, column=j+1).value=i*j
wb.save("99.xlsx")
WORD自动化

• Microsoft公司的Word是一套功能丰富的办公软件,所提供的docx格式可以存储文本以及字体、颜色等丰富的信息。
• docx的读写比txt文件要复杂,需要第三方库的支持。
• pip install python‐docx
• 注意:导入的时候用 import docx

import docx
doc = docx.Document('libai.docx')
print(len(doc.paragraphs)
# 8
print(doc.paragraphs[0].text)
# '铁杵成针'
print(doc.paragraphs[2].text)
# '李白是唐代的大诗人,但是小时候读书并不用功。...'
print(doc.paragraphs[2].runs)
#[<docx.text.run.Run at 0x1e0e56a3c50>,...]
print(doc.paragraphs[2].runs[0].text)
#'李白是唐代的大诗人,'
print(doc.paragraphs[2].runs[1].text)
#'但是小时候读书并不用功'
import docx
def getText(filename):
      doc = docx.Document(filename)
      fullText = []
      for para in doc.paragraphs:
            fullText.append(para.text)
      return '\n'.join(fullText)
import docx
doc = docx.Document('libai.docx')
doc.paragraphs[2].runs[0].underline = True
doc.save('restyled‐libai.docx')
import docx
doc = docx.Document()
doc.add_heading('静夜思', 0)
doc.add_heading('李白', 1)
for s in ["床前明月光", "疑是地上霜", "举头望明月",
"低头思故乡"]:
para = doc.add_paragraph(s)
para.add_run("/")
doc.add_picture("green.jpg")
doc.save('mydoc.docx')
PDF自动化

• PDF 表示 Portable Document Format 便携式文件格式,由Adobe Systems在1993年用于文件交换所发展出的文件格式。
• 本部分专注两件事:
—— 从 PDF 读取文本内容
—— 从已有的文档页面生成新的 PDF。
• pip install pyPDF2

import PyPDF2
with open('04067093.pdf', 'rb') as pdfFile:
pdfReader = PyPDF2.PdfFileReader(pdfFile)
print("Total pages: ", pdfReader.numPages)
page0 = pdfReader.getPage(0)
print(page0.extractText())
import PyPDF2
pdf1File = open('00294849.pdf', 'rb')
pdf2File = open('04067093.pdf', 'rb')
pdf1Reader = PyPDF2.PdfFileReader(pdf1File)
pdf2Reader = PyPDF2.PdfFileReader(pdf2File)
pdfWriter = PyPDF2.PdfFileWriter()
for pageNum in range(pdf1Reader.numPages):
      pageObj = pdf1Reader.getPage(pageNum)
      pdfWriter.addPage(pageObj)
for pageNum in range(pdf2Reader.numPages):
      pageObj = pdf2Reader.getPage(pageNum)
      pdfWriter.addPage(pageObj)
pdfOutputFile = open('combined.pdf', 'wb')
pdfWriter.write(pdfOutputFile)
pdfOutputFile.close(); pdf1File.close(); pdf2File.close()
import io
from pdfminer.converter import TextConverter
from pdfminer.pdfinterp import PDFPageInterpreter
from pdfminer.pdfinterp import PDFResourceManager
from pdfminer.pdfpage import PDFPage
def extract_text_from_pdf(pdf_path):
    resource_manager = PDFResourceManager()
    fake_file_handle = io.StringIO()
    converter = TextConverter(resource_manager, fake_file_handle)
    page_interpreter = PDFPageInterpreter(resource_manager, converter)
    with open(pdf_path, 'rb') as fh:
        for page in PDFPage.get_pages(fh, caching=True):
            page_interpreter.process_page(page)
        text = fake_file_handle.getvalue()
    converter.close()
    fake_file_handle.close()
    if text:
        return text

if __name__ == '__main__':
print(extract_text_from_pdf('CH9‐图形界面开发A.pdf'))
图像处理自动化

• 图像处理已经是深入日常生活,Photoshop的缩写已经成为图像处理的代名词。
• 如果需要编辑大量的图像,手工编辑可能是漫长、枯燥的工作。
• Pillow 是一个第三方 Python 模块,用于处理图像文件。该模块包含一些函数,可以很容易地裁剪图像、调整图像大小,以及编辑图像的内容,从而轻松地自动编辑成千上万的图像。

>>> from PIL import ImageColor
>>> ImageColor.getcolor('red', 'RGBA')
(255, 0, 0, 255)
>>> ImageColor.getcolor('RED', 'RGBA')
(255, 0, 0, 255)
>>> ImageColor.getcolor('Black', 'RGBA')
(0, 0, 0, 255)
>>> ImageColor.getcolor('chocolate', 'RGBA')
(210, 105, 30, 255)
>>> ImageColor.getcolor('CornflowerBlue', 'RGBA')
(100, 149, 237, 255)
>>> from PIL import Image
>>> img = Image.open('horse.jpg')
>>> img.size
  (1674, 1116)
>>> width, height = img.size
>>> img.format
'JPG'
>>> img.save('horse.png')
from PIL import Image
im = Image.new('RGBA', (100, 200), 'purple')
im.save('purpleImage.png')
im2 = Image.new('RGBA', (20, 20))
im2.save('transparentImage.png')
croppedIm = img.crop(
(600, 200, 1000, 800))
croppedIm.save('cropped‐horse.png')
from PIL import Image
img = Image.open('horse.jpg')
croppedIm = img.crop((600, 200, 1000, 800))
horsehead = croppedIm.copy()
img.paste(horsehead, (1200, 200))
img.save('horse2.jpg')
from PIL import Image
img = Image.open('horse.jpg')
width, height = img.size
img44 = img.resize((width//4, height//4), Image.NEAREST)
img42 = img.resize((width//4, height//2), Image.NEAREST)
imgr30 = img.rotate(30)
img44.save('horse44.jpg')
img42.save('horse42.jpg')
imgr30.save('horse_r30.jpg')
  1. 图片像素很多时,本方法很慢。
img = Image.new('RGB', (200, 100), 'black')
print(img.getpixel((0, 0)))
for x in range(100):
for y in range(50):
img.putpixel((x, y), (210, 210, 210))
img.save('putPixel.png')
from PIL import Image, ImageDraw
im = Image.new('RGBA', (200, 200), 'white')
draw = ImageDraw.Draw(im)
draw.line([(0, 0), (199, 0), (199, 199), (0, 199), (0,
0)], fill='black')
draw.rectangle((20, 30, 60, 60), fill='blue')
draw.ellipse((120, 30, 160, 60), fill='red')
draw.polygon(((57, 87), (79, 62), (94, 85), (120, 90),
(103, 113)), fill='brown')
for i in range(100, 200, 10):
draw.line([(i, 0), (200, i ‐ 100)], fill='green')
im.save('drawing.png')
键盘鼠标自动化

• 白盒:完成了解docx/xlsx格式细节,通过python直接生成符合格式的文档。
• 灰色:Word/Excel提供某种控制接口(如COM接口),通过COM接口操作Word/Excel软件达到预期目标。
• 黑色:缺乏控制接口,仅能通过模拟键盘和鼠标事件驱动GUI软件。

import pyautogui as ag
width, height = ag.size()
print(width, height)
#1366, 768
import pyautogui
for i in range(10):
ag.moveTo(100, 100, duration=0.25)
ag.moveTo(200, 100, duration=0.25)
ag.moveTo(200, 200, duration=0.25)
ag.moveTo(100, 200, duration=0.25)
print('Press Ctrl‐C to quit.')
try:
    while True:
        x, y = pyautogui.position()
        print(f"mouse at {x:4d}, {y:4d}")
except KeyboardInterrupt:
    print('\nDone.')
import pyautogui as ag
import time
time.sleep(5)
ag.click()
distance = 200
while distance > 0:
    ag.dragRel(distance, 0, duration=0.2) # move right
    distance = distance ‐ 5
    ag.dragRel(0, distance, duration=0.2) # move down
    ag.dragRel(‐distance, 0, duration=0.2) # move left
    distance = distance ‐ 5
    ag.dragRel(0, ‐distance, duration=0.2) # move up
import pyautogui
im = pyautogui.screenshot()
im.save("capture.png")

• 做GUI自动测试时,可以利用截图分析按钮是否正常或者变灰(利用Pillow库的getpixel方法)。
• 可以做一个软件,随着鼠标移动,自动取得不同位置的颜色。

keyDown('shift');
press('1');
keyUp('shift')

相当于 Shift-1 ,即“ ! ”键
• hotkey() 按参数自左向右依次模拟按键倒序模拟释放。
_ hotkey('ctrl', 'alt', 'shift', 's')

数据存储与程序调试

python:数据存储与程序调试

上一篇下一篇

猜你喜欢

热点阅读